⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpu_test.v

📁 RISC(reduced instruction setcomputer
💻 V
字号:
`timescale 1ns / 10ps

module cpu_test;

parameter CLKHI = 10;
parameter CLKLO = 10;


parameter NOP	= 1;
parameter MOVWF	= 2;
parameter CLRW	= 3;
parameter CLRF	= 4;
parameter SUBWF	= 5;
parameter DECF	= 6;
parameter IORWF	= 7;
parameter ANDWF	= 8;
parameter XORWF	= 9;
parameter ADDWF	= 10;
parameter MOVF	= 11;
parameter COMF	= 12;
parameter INCF	= 13;
parameter DECFSZ = 14;
parameter RRF	= 15;
parameter RLF	= 16;
parameter SWAPF	= 17;
parameter INCFSZ = 18;
parameter BCF	= 19;
parameter BSF	= 20;
parameter BTFSC	= 21;
parameter BTFSS	= 22;
parameter OPTION = 23;
parameter SLEEP	= 24;
parameter CLRWDT = 25;
parameter TRIS	= 26;
parameter RETLW	= 27;
parameter CALL	= 28;
parameter GOTO	= 29;
parameter MOVLW	= 30;
parameter IORLW	= 31;
parameter ANDLW	= 32;
parameter XORLW	= 33;

reg		clk;
reg		reset;

reg  [7:0]	porta; 
wire [7:0]	portb; 
wire [7:0]	portc; 

wire [10:0]	pramaddr;
wire [11:0]	pramdata;


wire [7:0]	expdin;
wire [7:0]	expdout;
wire [6:0]	expaddr;
wire		expread;
wire		expwrite;


wire [7:0]	debugw;
wire [10:0]	debugpc;
wire [11:0]	debuginst;
wire [7:0]	debugstatus;
 

cpu cpu (
   .clk		(clk),
   .reset	(reset),
   .paddr	(pramaddr),
   .pdata	(pramdata),
   .portain	(porta),
   .portbout	(portb),
   .portcout	(portc),
   .expdin	(expdin),
   .expdout	(expdout),
   .expaddr	(expaddr),
   .expread	(expread),
   .expwrite	(expwrite),
   .debugw	(debugw),
   .debugpc	(debugpc),
   .debuginst	(debuginst),
   .debugstatus	(debugstatus)
);


pram pram (
   .clk		(clk),
   .address	(pramaddr),
   .we		(1'b0),	// testbench doesn't allow writing to PRAM
   .din		(12'b000000000000),	//testbench doesn't allow writing to PRAM
   .dout	(pramdata)
);

wire [7:0] dds_out;


exp exp(
   .clk		(clk),
   .reset	(reset),
   .expdin	(expdin),
   .expdout	(expdout),
   .expaddr	(expaddr),
   .expread	(expread),
   .expwrite	(expwrite),
   .dds_out	(dds_out)
);


initial begin
   $display ("Free-RISC8.  Version 1.0");
   

   basic;
   

end


event ENDSIM;


task capture_data;
   begin
      $dumpfile ("risc8.vcd");
      $dumpvars (0, cpu_test);
      @(ENDSIM);
      $dumpflush;
   end
endtask

// Reset
task reset_pic;
   begin
      reset = 1;
      #200;
      reset = 0;
      $display ("End RESET.");
   end
endtask
  
// Drive the clock input
task drive_clock;
   begin
      clk  = 0;
      forever begin
         #(CLKLO) clk = 1;
         #(CLKHI) clk = 0;
      end
   end
endtask

//  BASIC CONFIDENCE Test Tasks 

task basic;
   
   integer  num_outputs;
   integer  num_matches;
   integer  num_mismatches;
   
   begin
      $display ("Free-RISC8 1.0.  This is the BASIC CONFIDENCE TEST.");
      #1;
   
      $display ("Loading program memory with %s", "basic.rom");
      $readmemh ("basic.rom", pram.mem);

      fork

         capture_data;
         

         drive_clock;
         

         reset_pic;
         
 
         monitor_cycles (5000);
         

         monitor_portb;
         monitor_portc;
         
          basic_drive_porta;
         
         begin
 
            num_outputs = 9; 
            
             basic_monitor_output_signature (num_outputs, num_matches, num_mismatches);

            repeat (2) @(posedge clk);
            $display ("Done monitoring for output signature.  %0d Matches, %0d Mismatches.", num_matches, num_mismatches);
            if (num_matches == num_outputs && num_mismatches == 0) begin
               $display ("SUCCESS.");
            end
            else begin
               $display ("Test FAILED!!");
            end
            
             ->ENDSIM;
            #0;
            $finish;
         end
         
          begin
            @(ENDSIM); 
            
              $display ("End of simulation signalled.  Killing simulation in a moment.");
            #0; 
            $finish;
         end
      join
   end
endtask

// Monitor PORTB 

task basic_monitor_output_signature;
   input   num_outputs;
   output  num_matches;
   output  num_mismatches;
   
   integer  num_outputs;
   integer  num_matches;
   integer  num_mismatches;
   
   integer      i;
   reg [7:0]    expected_output;
   begin
      num_matches    = 0;
      num_mismatches = 0;
      
      expected_output = 8'h00;
      
      i = 0;
      while (i < num_outputs) begin

         @(portb);
         #1;  
              
         if (portb == expected_output) begin
            $display ("MONITOR_OUTPUT_SIGNATURE: Expected output observed on PORTB: %h", portb);
            num_matches = num_matches + 1;
         end
         else begin
            $display ("MONITOR_OUTPUT_SIGNATURE: Unexpected output on PORTB: %h", portb);
            num_mismatches = num_mismatches + 1;
         end
            
         expected_output = expected_output + 1;
         i = i + 1;
      end
   end
endtask

task basic_drive_porta;
   begin
      forever begin
         porta = 8'h55;
         repeat (32) @(posedge clk);
         porta = 8'hAA;
         repeat (32) @(posedge clk);
      end
   end
endtask

// DDS Demo Test Tasks

task dds_test;
   
   begin
      $display ("Free-RISC8 1.0.  This is the DDS Demo.");
      #1;
   
      $display ("Loading program memory with %s", "dds.rom");
      $readmemh ("dds.rom", pram.mem);

      fork
         capture_data;

         drive_clock;

         reset_pic;
         
         monitor_cycles (3000); 

         begin
            @(ENDSIM); 

            $display ("End of simulation signalled.  Killing simulation in a moment.");
            #0;
            $finish;
         end
      join
   end
endtask

// Generic Tasks 

task monitor_cycles;
   input max_cycles;
   
   integer max_cycles;
   integer cycles;
   begin
      cycles = 0;
      fork

         forever begin
            @(posedge clk);
            cycles = cycles + 1;
         end
         
          begin
            wait (cycles == max_cycles);
            $display ("MAXIMUM CYCLES EXCEEDED!");
            ->ENDSIM;
         end
      join
   end
endtask

// Generic Debug Display stuff.

task monitor_rom;
   begin
      forever begin
         @(negedge clk);
         $display ("ROM Address = %h, Data = %h", pramaddr, pramdata);
      end
   end
endtask

task monitor_porta;
   reg [7:0] last_porta;
   begin
      forever begin
         @(negedge clk);
         if (last_porta !== porta) begin
            $display ("porta changes to: %h", porta);
            last_porta = porta;
         end
      end
   end         
endtask

task monitor_portb;
   reg [7:0] last_portb;
   begin
      forever begin
         @(negedge clk);
         if (last_portb !== portb) begin
            $display ("MONITOR_PORTB: Port B changes to: %h", portb);
            last_portb = portb;
         end
      end
   end
endtask

task monitor_portc;
   reg [7:0] last_portc;
   begin
      forever begin
         @(negedge clk);
         if (last_portc !== portc) begin
            $display ("MONITOR_PORTC: Port C changes to: %h", portc);
            last_portc = portc;
         end
      end
   end
endtask

task monitor_w;
   reg [7:0] last_w;
   begin
      forever begin
         @(negedge clk);
         if (debugw !== last_w) begin
            $display ("W = %0h", debugw);
         end
         last_w = debugw;
      end
   end
endtask

task monitor_pc;
   begin
      forever begin
         @(negedge clk);
         $display ("PC = %0h", debugpc);
      end
   end
endtask

// Monitor the INST register 

task monitor_inst;
   reg [11:0]    last_pc;
   integer       opcode;
   reg [8*8-1:0] mnemonic;
   
   begin
      fork

         forever begin
            @(posedge clk);
            last_pc = debugpc;
         end

         begin
            #6;
            forever begin
               @(negedge clk);
               
               lookup_opcode   (debuginst, opcode); 
               lookup_mnemonic (opcode, mnemonic); 

               if (opcode == CLRW   || 
                   opcode == NOP    || 
                   opcode == CLRWDT ||
                   opcode == OPTION ||
                   opcode == SLEEP) begin

                  $display ("MONITOR_INST: %h %s", last_pc, mnemonic);
               end
               else if (debuginst[11:10] == 2'b00) begin

                  $display ("MONITOR_INST: %h %s %0d(0x%h), %s", 
                     last_pc, mnemonic,
                     debuginst[4:0], debuginst[4:0],
                     (debuginst[5]) ? "f" : "W"
                  );
               end
               else if (debuginst[11:10] == 2'b01) begin

                  $display ("MONITOR_INST: %h %s bit=%d, f=%0d(0x%h)", 
                     last_pc, mnemonic,
                     debuginst[7:5],
                     debuginst[4:0], debuginst[4:0]
                  );
               end
               else if (debuginst[11] == 1'b1) begin

                  $display ("MONITOR_INST: %h %s %0d(0x%h)", 
                     last_pc, mnemonic,
                     debuginst[7:0], debuginst[7:0]
                  );
               end
               else begin
                  $display ("MONITOR_INST: --- Unhandled instruction.. %h", debuginst);
               end
            end
         end
      join   
   end
endtask


task lookup_opcode;
   input inst;
   output opcode;
   
   reg [11:0] inst;
   integer    opcode;
   begin
      casex (inst)
         12'b0000_0000_0000: opcode = NOP;
         12'b0000_001X_XXXX: opcode = MOVWF;
         12'b0000_0100_0000: opcode = CLRW;
         12'b0000_011X_XXXX: opcode = CLRF;
         12'b0000_10XX_XXXX: opcode = SUBWF;
         12'b0000_11XX_XXXX: opcode = DECF;
         12'b0001_00XX_XXXX: opcode = IORWF;
         12'b0001_01XX_XXXX: opcode = ANDWF;
         12'b0001_10XX_XXXX: opcode = XORWF;
         12'b0001_11XX_XXXX: opcode = ADDWF;
         12'b0010_00XX_XXXX: opcode = MOVF;
         12'b0010_01XX_XXXX: opcode = COMF;
         12'b0010_10XX_XXXX: opcode = INCF;
         12'b0010_11XX_XXXX: opcode = DECFSZ;
         12'b0011_00XX_XXXX: opcode = RRF;
         12'b0011_01XX_XXXX: opcode = RLF;
         12'b0011_10XX_XXXX: opcode = SWAPF;
         12'b0011_11XX_XXXX: opcode = INCFSZ;

         12'b0100_XXXX_XXXX: opcode = BCF;
         12'b0101_XXXX_XXXX: opcode = BSF;
         12'b0110_XXXX_XXXX: opcode = BTFSC;
         12'b0111_XXXX_XXXX: opcode = BTFSS;


         12'b0000_0000_0010: opcode = OPTION;
         12'b0000_0000_0011: opcode = SLEEP;
         12'b0000_0000_0100: opcode = CLRWDT;
         12'b0000_0000_0101: opcode = TRIS;
         12'b0000_0000_0110: opcode = TRIS;
         12'b0000_0000_0111: opcode = TRIS;
         12'b1000_XXXX_XXXX: opcode = RETLW;
         12'b1001_XXXX_XXXX: opcode = CALL;
         12'b101X_XXXX_XXXX: opcode = GOTO;
         12'b1100_XXXX_XXXX: opcode = MOVLW;
         12'b1101_XXXX_XXXX: opcode = IORLW;
         12'b1110_XXXX_XXXX: opcode = ANDLW;
         12'b1111_XXXX_XXXX: opcode = XORLW;

         default:            opcode = 0;
      endcase
   end
endtask

// Given the opcode return the ASCII string for the instruction.

task lookup_mnemonic;
   input opcode;
   output mnemonic;
   
   integer opcode;
   reg [8*8-1:0]  mnemonic;
   begin
      case (opcode)
         NOP:		mnemonic = "NOP     ";
         MOVWF: 	mnemonic = "MOVWF   ";
         CLRW:		mnemonic = "CLRW    ";
         CLRF:		mnemonic = "CLRF    ";
         SUBWF:		mnemonic = "SUBWF   ";
         DECF:		mnemonic = "DECF    ";
         IORWF:		mnemonic = "IORWF   ";
         ANDWF:		mnemonic = "ANDWF   ";
         XORWF:		mnemonic = "XORWF   ";
         ADDWF:		mnemonic = "ADDWF   ";
         MOVF:		mnemonic = "MOVF    ";
         COMF:		mnemonic = "COMF    ";
         INCF:		mnemonic = "INCF    ";
         DECFSZ:	mnemonic = "DECFSZ  ";
         RRF:		mnemonic = "RRF     ";
         RLF:		mnemonic = "RLF     ";
         SWAPF:		mnemonic = "SWAPF   ";
         INCFSZ:	mnemonic = "INCFSZ  ";


         BCF:		mnemonic = "BCF     ";
         BSF:		mnemonic = "BSF     ";
         BTFSC:		mnemonic = "BTFSC   ";
         BTFSS:		mnemonic = "BTFSS   ";


         OPTION:	mnemonic = "OPTION  ";
         SLEEP:		mnemonic = "SLEEP   ";
         CLRWDT:	mnemonic = "CLRWDT  ";
         TRIS: 		mnemonic = "TRIS    ";
         RETLW:		mnemonic = "RETLW   ";
         CALL:		mnemonic = "CALL    ";
         GOTO:		mnemonic = "GOTO    ";
         MOVLW:		mnemonic = "MOVLW   ";
         IORLW:		mnemonic = "IORLW   ";
         ANDLW:		mnemonic = "ANDLW   ";
         XORLW:		mnemonic = "XORLW   ";

         default:	mnemonic = "-XXXXXX-";
      endcase
   end
endtask

endmodule


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -