test.v
上传用户:bltddc
上传日期:2020-07-09
资源大小:4428k
文件大小:19k
源码类别:

SCSI/ASPI

开发平台:

VHDL

  1. //
  2. // Copyright (c) 1999 Thomas Coonan (tcoonan@mindspring.com)
  3. //
  4. //    This source code is free software; you can redistribute it
  5. //    and/or modify it in source code form under the terms of the GNU
  6. //    General Public License as published by the Free Software
  7. //    Foundation; either version 2 of the License, or (at your option)
  8. //    any later version.
  9. //
  10. //    This program is distributed in the hope that it will be useful,
  11. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //    GNU General Public License for more details.
  14. //
  15. //    You should have received a copy of the GNU General Public License
  16. //    along with this program; if not, write to the Free Software
  17. //    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  18. //
  19. `timescale 1ns / 10ps
  20. module test;
  21. // For 50Mhz, period is 20ns, so set CLKHI to 10 and CLKLO to 10
  22. parameter CLKHI = 10;
  23. parameter CLKLO = 10;
  24. // Define some codes for each instruction opcode.  These have nothing to do
  25. // with the actual encoding of the instructions.  This is for display purposes.
  26. //
  27. parameter NOP = 1;
  28. parameter MOVWF = 2;
  29. parameter CLRW = 3;
  30. parameter CLRF = 4;
  31. parameter SUBWF = 5;
  32. parameter DECF = 6;
  33. parameter IORWF = 7;
  34. parameter ANDWF = 8;
  35. parameter XORWF = 9;
  36. parameter ADDWF = 10;
  37. parameter MOVF = 11;
  38. parameter COMF = 12;
  39. parameter INCF = 13;
  40. parameter DECFSZ = 14;
  41. parameter RRF = 15;
  42. parameter RLF = 16;
  43. parameter SWAPF = 17;
  44. parameter INCFSZ = 18;
  45. parameter BCF = 19;
  46. parameter BSF = 20;
  47. parameter BTFSC = 21;
  48. parameter BTFSS = 22;
  49. parameter OPTION = 23;
  50. parameter SLEEP = 24;
  51. parameter CLRWDT = 25;
  52. parameter TRIS = 26;
  53. parameter RETLW = 27;
  54. parameter CALL = 28;
  55. parameter GOTO = 29;
  56. parameter MOVLW = 30;
  57. parameter IORLW = 31;
  58. parameter ANDLW = 32;
  59. parameter XORLW = 33;
  60. // *** Basic Interface to the PICCPU
  61. reg clk;
  62. reg reset;
  63. // Declare I/O Port connections
  64. reg  [7:0] porta; // INPUT
  65. wire [7:0] portb; // OUTPUT
  66. wire [7:0] portc; // OUTPUT
  67. // Declare ROM and rom signals
  68. wire [10:0] pramaddr;
  69. wire [11:0] pramdata;
  70. // *** Expansion Interface
  71. wire [7:0] expdin;
  72. wire [7:0] expdout;
  73. wire [6:0] expaddr;
  74. wire expread;
  75. wire expwrite;
  76. // Debug output ports on the core.  These are just internal signals brought out so
  77. // they can be observed.
  78. //
  79. wire [7:0] debugw;
  80. wire [10:0] debugpc;
  81. wire [11:0] debuginst;
  82. wire [7:0] debugstatus;
  83.  
  84. // Instantiate one CPU to be tested.
  85. cpu cpu (
  86.    .clk (clk),
  87.    .reset (reset),
  88.    .paddr (pramaddr),
  89.    .pdata (pramdata),
  90.    .portain (porta),
  91.    .portbout (portb),
  92.    .portcout (portc),
  93.    .expdin (expdin),
  94.    .expdout (expdout),
  95.    .expaddr (expaddr),
  96.    .expread (expread),
  97.    .expwrite (expwrite),
  98.    .debugw (debugw),
  99.    .debugpc (debugpc),
  100.    .debuginst (debuginst),
  101.    .debugstatus (debugstatus)
  102. );
  103. // Instantiate the Program RAM.
  104. pram pram (
  105.    .clk (clk),
  106.    .address (pramaddr),
  107.    .we (1'b0), // This testbench doesn't allow writing to PRAM
  108.    .din (12'b000000000000), // This testbench doesn't allow writing to PRAM
  109.    .dout (pramdata)
  110. );
  111. // Output of the DDS in the Expansion module (see section on the DDS Demo in docs).
  112. wire [7:0] dds_out;
  113. // Instantiate one PICEXP (Expansion) module.  This one is a DDS circuit.
  114. exp exp(
  115.    .clk (clk),
  116.    .reset (reset),
  117.    .expdin (expdin),
  118.    .expdout (expdout),
  119.    .expaddr (expaddr),
  120.    .expread (expread),
  121.    .expwrite (expwrite),
  122.    .dds_out (dds_out)
  123. );
  124. // This is the only initial block in the test module and this is where
  125. // you select what test you want to do.
  126. //
  127. initial begin
  128.    $display ("Free-RISC8.  Version 1.0");
  129.    
  130.    // Just uncomment out the test you want to run!
  131.    
  132.    // ** This is our top-level "Basic Confidence" test.
  133.    basic;
  134.    
  135.    // ** This is the DDS example.  Make sure the DDS circuit is in the Verilog command line.
  136.    //dds_test;
  137. end
  138. // Event should be emitted by any task to kill simulation.  Tasks should
  139. // use this to close files, etc.
  140. //
  141. event ENDSIM;
  142. // Capture some data
  143. task capture_data;
  144.    begin
  145.       $dumpfile ("risc8.vcd");
  146.       $dumpvars (0, test);
  147.       @(ENDSIM);
  148.       $dumpflush;
  149.    end
  150. endtask
  151. // Reset
  152. task reset_pic;
  153.    begin
  154.       reset = 1;
  155.       #200;
  156.       reset = 0;
  157.       $display ("End RESET.");
  158.    end
  159. endtask
  160.   
  161. // Drive the clock input
  162. task drive_clock;
  163.    begin
  164.       clk  = 0;
  165.       forever begin
  166.          #(CLKLO) clk = 1;
  167.          #(CLKHI) clk = 0;
  168.       end
  169.    end
  170. endtask
  171. // *************  BASIC CONFIDENCE Test Tasks **************
  172. //
  173. // BASIC CONFIDENCE Test.
  174. //
  175. // This task will fork off all the other necessary tasks to cause reset, drive the clock, etc. etc.
  176. //
  177. // 
  178. task basic;
  179.    
  180.    integer  num_outputs;
  181.    integer  num_matches;
  182.    integer  num_mismatches;
  183.    
  184.    begin
  185.       $display ("Free-RISC8 1.0.  This is the BASIC CONFIDENCE TEST.");
  186.       #1;
  187.    
  188.       $display ("Loading program memory with %s", "basic.rom");
  189.       $readmemh ("basic.rom", pram.mem);
  190.       fork
  191.          // Capture data
  192.          capture_data;
  193.          
  194.          // Run the clock
  195.          drive_clock;
  196.          
  197.          // Do a reset
  198.          reset_pic;
  199.          
  200.          // Monitor the number of cycles and set an absolute maximum number of cycles.
  201.          monitor_cycles (5000);
  202.          
  203.          // More specific monitors
  204.          //monitor_inst;
  205.          monitor_portb;
  206.          monitor_portc;
  207.          
  208.          // Drive PORTA with a toggling pattern.  This is for one of the subtests.
  209.          //
  210.          basic_drive_porta;
  211.          
  212.          // Monitor the counting pattern on PORTB.  This is our self-checking scheme for the test.
  213.          // 
  214.          begin
  215.             // 
  216.             num_outputs = 9;  // Expect exactly 7 changes on the PORTB (0..6).
  217.             
  218.             // Call the following task which will watch PORTB for the patterns.
  219.             //
  220.             basic_monitor_output_signature (num_outputs, num_matches, num_mismatches);
  221.             
  222.             // See how we did!
  223.             repeat (2) @(posedge clk);
  224.             $display ("Done monitoring for output signature.  %0d Matches, %0d Mismatches.", num_matches, num_mismatches);
  225.             if (num_matches == num_outputs && num_mismatches == 0) begin
  226.                $display ("SUCCESS.");
  227.             end
  228.             else begin
  229.                $display ("Test FAILED!!");
  230.             end
  231.             
  232.             // We are done.  Throw the ENDSIM event.
  233.             ->ENDSIM;
  234.             #0;
  235.             $finish;
  236.          end
  237.          
  238.          // Catch end of simulation event due to max number of cycles or pattern from PIC code.
  239.          begin
  240.             @(ENDSIM);  // Catch the event.
  241.             
  242.             // Got it!
  243.             $display ("End of simulation signalled.  Killing simulation in a moment.");
  244.             #0; // Let anything else see this event...
  245.             $finish;
  246.          end
  247.       join
  248.    end
  249. endtask
  250. // Monitor PORTB for an incrementing pattern.  This is how we are doing our self-checking.
  251. // A good run will count from ZERO up to some number.
  252. //
  253. task basic_monitor_output_signature;
  254.    input   num_outputs;
  255.    output  num_matches;
  256.    output  num_mismatches;
  257.    
  258.    integer  num_outputs;
  259.    integer  num_matches;
  260.    integer  num_mismatches;
  261.    
  262.    integer      i;
  263.    reg [7:0]    expected_output;
  264.    begin
  265.       num_matches    = 0;
  266.       num_mismatches = 0;
  267.       
  268.       expected_output = 8'h00;
  269.       
  270.       i = 0;
  271.       while (i < num_outputs) begin
  272.          // Wait for any change on output port B.
  273.          @(portb);
  274.          #1;  // Wait for a moment for any wiggling on different 
  275.               // bits to seetle out, just in case there's any gate-level going on..
  276.          if (portb == expected_output) begin
  277.             $display ("MONITOR_OUTPUT_SIGNATURE: Expected output observed on PORTB: %h", portb);
  278.             num_matches = num_matches + 1;
  279.          end
  280.          else begin
  281.             $display ("MONITOR_OUTPUT_SIGNATURE: Unexpected output on PORTB: %h", portb);
  282.             num_mismatches = num_mismatches + 1;
  283.          end
  284.             
  285.          expected_output = expected_output + 1;
  286.          i = i + 1;
  287.       end
  288.    end
  289. endtask
  290. task basic_drive_porta;
  291.    begin
  292.       forever begin
  293.          porta = 8'h55;
  294.          repeat (32) @(posedge clk);
  295.          porta = 8'hAA;
  296.          repeat (32) @(posedge clk);
  297.       end
  298.    end
  299. endtask
  300. // *************  DDS Demo Test Tasks **************
  301. //
  302. // DDS Test.
  303. //
  304. // This task will fork off all the other necessary tasks to cause reset, drive the clock, etc. etc.
  305. //
  306. // In a waveform viewer, check out PORTC[1:0] and also check out the 'dds_out' output.
  307. // You should see a modulated sine wave (e.g. FSK).
  308. //
  309. task dds_test;
  310.    
  311.    begin
  312.       $display ("Free-RISC8 1.0.  This is the DDS Demo.");
  313.       #1;
  314.    
  315.       $display ("Loading program memory with %s", "dds.rom");
  316.       $readmemh ("dds.rom", pram.mem);
  317.       fork
  318.          // Capture data
  319.          capture_data;
  320.          
  321.          // Run the clock
  322.          drive_clock;
  323.          
  324.          // Do a reset
  325.          reset_pic;
  326.          
  327.          // Monitor the number of cycles and set an absolute maximum number of cycles.
  328.          monitor_cycles (3000); // <--- this appeared about right for DDS demo to finish all bits
  329.          
  330.          // More specific monitors
  331.          //monitor_inst;
  332.          //monitor_portb;
  333.          //monitor_portc;
  334.          
  335.          // Catch end of simulation event due to max number of cycles or pattern from PIC code.
  336.          begin
  337.             @(ENDSIM);  // Catch the event.
  338.             
  339.             // Got it!
  340.             $display ("End of simulation signalled.  Killing simulation in a moment.");
  341.             #0; // Let anything else see this event...
  342.             $finish;
  343.          end
  344.       join
  345.    end
  346. endtask
  347. // *****************************  Generic Tasks  **************************  //
  348. // CYCLE monitor and end-of-simulation checker.
  349. //
  350. task monitor_cycles;
  351.    input max_cycles;
  352.    
  353.    integer max_cycles;
  354.    integer cycles;
  355.    begin
  356.       cycles = 0;
  357.       fork
  358.          // Count cycles.
  359.          forever begin
  360.             @(posedge clk);
  361.             cycles = cycles + 1;
  362.          end
  363.          
  364.          // Watch for max cycles.  If we detect max cycles then throw our testbench ENDSIM event.
  365.          //
  366.          begin
  367.             wait (cycles == max_cycles);
  368.             $display ("MAXIMUM CYCLES EXCEEDED!");
  369.             ->ENDSIM;
  370.          end
  371.       join
  372.    end
  373. endtask
  374. // Generic Debug Display stuff.
  375. //
  376. task monitor_rom;
  377.    begin
  378.       forever begin
  379.          @(negedge clk);
  380.          $display ("ROM Address = %h, Data = %h", pramaddr, pramdata);
  381.       end
  382.    end
  383. endtask
  384. task monitor_porta;
  385.    reg [7:0] last_porta;
  386.    begin
  387.       forever begin
  388.          @(negedge clk);
  389.          if (last_porta !== porta) begin
  390.             $display ("porta changes to: %h", porta);
  391.             last_porta = porta;
  392.          end
  393.       end
  394.    end         
  395. endtask
  396. task monitor_portb;
  397.    reg [7:0] last_portb;
  398.    begin
  399.       forever begin
  400.          @(negedge clk);
  401.          if (last_portb !== portb) begin
  402.             $display ("MONITOR_PORTB: Port B changes to: %h", portb);
  403.             last_portb = portb;
  404.          end
  405.       end
  406.    end
  407. endtask
  408. task monitor_portc;
  409.    reg [7:0] last_portc;
  410.    begin
  411.       forever begin
  412.          @(negedge clk);
  413.          if (last_portc !== portc) begin
  414.             $display ("MONITOR_PORTC: Port C changes to: %h", portc);
  415.             last_portc = portc;
  416.          end
  417.       end
  418.    end
  419. endtask
  420. task monitor_w;
  421.    reg [7:0] last_w;
  422.    begin
  423.       forever begin
  424.          @(negedge clk);
  425.          if (debugw !== last_w) begin
  426.             $display ("W = %0h", debugw);
  427.          end
  428.          last_w = debugw;
  429.       end
  430.    end
  431. endtask
  432. task monitor_pc;
  433.    begin
  434.       forever begin
  435.          @(negedge clk);
  436.          $display ("PC = %0h", debugpc);
  437.       end
  438.    end
  439. endtask
  440. // Monitor the INST register (e.g. the instruction) and display something
  441. // resembling a disassembler output.  We'll use several helping tasks to
  442. // look up an appopriate mnemonic.
  443. //
  444. task monitor_inst;
  445.    reg [11:0]    last_pc;
  446.    integer       opcode;
  447.    reg [8*8-1:0] mnemonic;
  448.    
  449.    begin
  450.       fork
  451.          // Always keep a copy of the LAST value of the PC.  This is because
  452.          // of our pipelining.  The PC is really one value ahead.  You really
  453.          // want to see the address that corresponds to the instruction you
  454.          // are looking at.
  455.          //
  456.          forever begin
  457.             @(posedge clk);
  458.             last_pc = debugpc;
  459.          end
  460.          begin
  461.             #6;
  462.             forever begin
  463.                @(negedge clk);
  464.                
  465.                // OK.  We have an instruction.  Take this instruction and call some tasks
  466.                // to help us display a pretty output line.  We will look up a nice mnemonic, etc.
  467.                //
  468.                lookup_opcode   (debuginst, opcode);  // Look up a simpler "opcode" number instead of the actual instruction.
  469.                lookup_mnemonic (opcode, mnemonic);   // Look up the ASCII instruction name
  470.                
  471.                // Depending on the specific instruction, we want to print out different stuff.
  472.                // We may need to print out the 'K' field for literal instructions, or the 'f' field
  473.                // for the MOVF types of instruction, or only the address and mnemonic for
  474.                // simple instructions like SLEEP or CLRW.
  475.                //
  476.                if (opcode == CLRW   || 
  477.                    opcode == NOP    || 
  478.                    opcode == CLRWDT ||
  479.                    opcode == OPTION ||
  480.                    opcode == SLEEP) begin
  481.                   // These are instructions with no additional arguments.  Display the PC and MNEMONIC only.
  482.                   //
  483.                   $display ("MONITOR_INST: %h %s", last_pc, mnemonic);
  484.                end
  485.                else if (debuginst[11:10] == 2'b00) begin
  486.                   // These are the instructions with a register address.  Display the 'd' and 'f' fields.
  487.                   //
  488.                   $display ("MONITOR_INST: %h %s %0d(0x%h), %s", 
  489.                      last_pc, mnemonic,
  490.                      debuginst[4:0], debuginst[4:0],
  491.                      (debuginst[5]) ? "f" : "W"
  492.                   );
  493.                end
  494.                else if (debuginst[11:10] == 2'b01) begin
  495.                   // These are the "Bit-Oriented" instructions with a bit reference and register address.  
  496.                   // Display the 'b' and 'f' fields.
  497.                   //
  498.                   $display ("MONITOR_INST: %h %s bit=%d, f=%0d(0x%h)", 
  499.                      last_pc, mnemonic,
  500.                      debuginst[7:5],
  501.                      debuginst[4:0], debuginst[4:0]
  502.                   );
  503.                end
  504.                else if (debuginst[11] == 1'b1) begin
  505.                   // These are the "Literal and Control" instructions with a literal field.  Display the 'k' field.
  506.                   //
  507.                   $display ("MONITOR_INST: %h %s %0d(0x%h)", 
  508.                      last_pc, mnemonic,
  509.                      debuginst[7:0], debuginst[7:0]
  510.                   );
  511.                end
  512.                else begin
  513.                   $display ("MONITOR_INST: --- Unhandled instruction.. %h", debuginst);
  514.                end
  515.             end
  516.          end
  517.       join   
  518.    end
  519. endtask
  520. // Given the actual 12-bit instruction, return the "opcode".  This is just an integer number
  521. // to help us handle printing and such and does NOT correspond to any hardware encoding.
  522. //
  523. task lookup_opcode;
  524.    input inst;
  525.    output opcode;
  526.    
  527.    reg [11:0] inst;
  528.    integer    opcode;
  529.    begin
  530.       casex (inst)
  531.          12'b0000_0000_0000: opcode = NOP;
  532.          12'b0000_001X_XXXX: opcode = MOVWF;
  533.          12'b0000_0100_0000: opcode = CLRW;
  534.          12'b0000_011X_XXXX: opcode = CLRF;
  535.          12'b0000_10XX_XXXX: opcode = SUBWF;
  536.          12'b0000_11XX_XXXX: opcode = DECF;
  537.          12'b0001_00XX_XXXX: opcode = IORWF;
  538.          12'b0001_01XX_XXXX: opcode = ANDWF;
  539.          12'b0001_10XX_XXXX: opcode = XORWF;
  540.          12'b0001_11XX_XXXX: opcode = ADDWF;
  541.          12'b0010_00XX_XXXX: opcode = MOVF;
  542.          12'b0010_01XX_XXXX: opcode = COMF;
  543.          12'b0010_10XX_XXXX: opcode = INCF;
  544.          12'b0010_11XX_XXXX: opcode = DECFSZ;
  545.          12'b0011_00XX_XXXX: opcode = RRF;
  546.          12'b0011_01XX_XXXX: opcode = RLF;
  547.          12'b0011_10XX_XXXX: opcode = SWAPF;
  548.          12'b0011_11XX_XXXX: opcode = INCFSZ;
  549.          // *** Bit-Oriented File Register Operations
  550.          12'b0100_XXXX_XXXX: opcode = BCF;
  551.          12'b0101_XXXX_XXXX: opcode = BSF;
  552.          12'b0110_XXXX_XXXX: opcode = BTFSC;
  553.          12'b0111_XXXX_XXXX: opcode = BTFSS;
  554.          // *** Literal and Control Operations
  555.          12'b0000_0000_0010: opcode = OPTION;
  556.          12'b0000_0000_0011: opcode = SLEEP;
  557.          12'b0000_0000_0100: opcode = CLRWDT;
  558.          12'b0000_0000_0101: opcode = TRIS;
  559.          12'b0000_0000_0110: opcode = TRIS;
  560.          12'b0000_0000_0111: opcode = TRIS;
  561.          12'b1000_XXXX_XXXX: opcode = RETLW;
  562.          12'b1001_XXXX_XXXX: opcode = CALL;
  563.          12'b101X_XXXX_XXXX: opcode = GOTO;
  564.          12'b1100_XXXX_XXXX: opcode = MOVLW;
  565.          12'b1101_XXXX_XXXX: opcode = IORLW;
  566.          12'b1110_XXXX_XXXX: opcode = ANDLW;
  567.          12'b1111_XXXX_XXXX: opcode = XORLW;
  568.          default:            opcode = 0;
  569.       endcase
  570.    end
  571. endtask
  572. // Given the opcode (see task 'lookup_opcode') return the ASCII string for the instruction.
  573. //
  574. task lookup_mnemonic;
  575.    input opcode;
  576.    output mnemonic;
  577.    
  578.    integer opcode;
  579.    reg [8*8-1:0]  mnemonic;
  580.    begin
  581.       case (opcode)
  582.          NOP: mnemonic = "NOP     ";
  583.          MOVWF:  mnemonic = "MOVWF   ";
  584.          CLRW: mnemonic = "CLRW    ";
  585.          CLRF: mnemonic = "CLRF    ";
  586.          SUBWF: mnemonic = "SUBWF   ";
  587.          DECF: mnemonic = "DECF    ";
  588.          IORWF: mnemonic = "IORWF   ";
  589.          ANDWF: mnemonic = "ANDWF   ";
  590.          XORWF: mnemonic = "XORWF   ";
  591.          ADDWF: mnemonic = "ADDWF   ";
  592.          MOVF: mnemonic = "MOVF    ";
  593.          COMF: mnemonic = "COMF    ";
  594.          INCF: mnemonic = "INCF    ";
  595.          DECFSZ: mnemonic = "DECFSZ  ";
  596.          RRF: mnemonic = "RRF     ";
  597.          RLF: mnemonic = "RLF     ";
  598.          SWAPF: mnemonic = "SWAPF   ";
  599.          INCFSZ: mnemonic = "INCFSZ  ";
  600.          // *** Bit-Oriented File Register Operations
  601.          BCF: mnemonic = "BCF     ";
  602.          BSF: mnemonic = "BSF     ";
  603.          BTFSC: mnemonic = "BTFSC   ";
  604.          BTFSS: mnemonic = "BTFSS   ";
  605.          // *** Literal and Control Operations
  606.          OPTION: mnemonic = "OPTION  ";
  607.          SLEEP: mnemonic = "SLEEP   ";
  608.          CLRWDT: mnemonic = "CLRWDT  ";
  609.          TRIS:  mnemonic = "TRIS    ";
  610.          RETLW: mnemonic = "RETLW   ";
  611.          CALL: mnemonic = "CALL    ";
  612.          GOTO: mnemonic = "GOTO    ";
  613.          MOVLW: mnemonic = "MOVLW   ";
  614.          IORLW: mnemonic = "IORLW   ";
  615.          ANDLW: mnemonic = "ANDLW   ";
  616.          XORLW: mnemonic = "XORLW   ";
  617.          default: mnemonic = "-XXXXXX-";
  618.       endcase
  619.    end
  620. endtask
  621. endmodule