📄 cpu_test.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 + -