📄 pic.v
字号:
r80 = 0;
r94 = 0;
// Bank #3
r112 = 0;
r126 = 0;
end
endtask
`endif
// synopsys translate_on
endmodule
//
// SYNTHETIC PIC 2.0 4/23/98
//
// This is a synthesizable Microchip 16C57 compatible
// microcontroller. This core is not intended as a high fidelity model of
// the PIC, but simply a way to offer a simple processor core to people
// familiar with the PIC who also have PIC tools.
//
// pictest.v - top-level testbench (NOT SYNTHESIZABLE)
// piccpu.v - top-level synthesizable module
// picregs.v - register file instantiated under piccpu
// picalu.v - ALU instantiated under piccpu
// picidec.v - Instruction Decoder instantiated under piccpu
// hex2rom.c - C program used to translate MPLAB's INTEL HEX output
// into the Verilog $readmemh compatible file
// test*.asm - (note the wildcard..) Several test programs used
// to help debug the verilog. I used MPLAB and the simulator
// to develop these programs and get the expected results.
// Then, I ran them on Verilog-XL where they appeared to
// match.
//
// Copyright, Tom Coonan, '97.
// Use freely, but not for resale as is. You may use this in your
// own projects as desired. Just don't try to sell it as is!
//
//
`timescale 1ns / 10ps
module pictest;
// Select which test to run HERE..
parameter TEST_NUMBER = 9;
// *** Testing variables
// Debug flags.
integer dbg_showporta; // Are set in an 'initial' for default values,
integer dbg_showportb; // override in specific tests...
integer dbg_showportc; // Setting to 1 will cause variable to be displayed.
integer dbg_showinst;
integer dbg_showrom;
integer dbg_showw;
integer dbg_showpc;
// cycles counter variables
integer dbg_showcycles; // Set to 1 to see cycles
integer dbg_limitcycles;// Set to one to enable maxcycles check
integer dbg_maxcycles; // Limit simulation to some number of cycles.
integer cycles; // Cycles counter.
// *** Interface to the PICCPU
reg clk;
reg reset;
reg [7:0] porta;
wire [7:0] portb;
wire [7:0] portc;
reg [11:0] rom[0:511];
wire [8:0] romaddr;
reg [11:0] romdata;
// ROM Interface
always @(romaddr) begin
romdata = rom[romaddr];
end
reg [7:0] last_debugw;
reg [8:0] last_debugpc;
reg [11:0] last_debuginst;
reg [7:0] last_debugstatus;
wire [7:0] debugw;
wire [8:0] debugpc;
wire [11:0] debuginst;
wire [7:0] debugstatus;
// Instantiate one PICCPU to be tested.
piccpu piccpu_inst (
.clk (clk),
.reset (reset),
.paddr (romaddr),
.pdata (romdata),
.portain (porta),
.portbout (portb),
.portcout (portc),
.debugw (debugw),
.debugpc (debugpc),
.debuginst (debuginst),
.debugstatus (debugstatus)
);
// Capture some data
initial begin
$dumpfile ("pic.vcd");
$dumpvars (0, pictest);
end
// Reset
initial begin
reset = 1;
#200;
reset = 0;
end
// Drive the clock input
initial begin
clk = 0;
forever begin
#50 clk = 1;
#50 clk = 0;
end
end
// Debug defaults. Override in individual test tasks.
//
initial begin
dbg_showporta = 0;
dbg_showportb = 0;
dbg_showportc = 0;
dbg_showinst = 0;
dbg_showrom = 0;
dbg_showw = 0;
dbg_showpc = 0;
dbg_showcycles = 0;
dbg_limitcycles = 1;
dbg_maxcycles = 50000;
end
// Call the appropriate test task based on the TEST_NUMBER parameter set at top.
//
initial begin
case (TEST_NUMBER)
1: test1;
2: test2;
3: test3;
4: test4;
5: test5;
6: test6;
7: test7;
8: test8;
9: test9;
default:
begin
$display ("ERROR: Unknown Test Number: %0d", TEST_NUMBER);
$finish;
end
endcase
end
task test1;
begin
$display ("SYNTHETIC PIC 2.0. This is TEST #1");
#1;
// Only Watch Port B
dbg_showportb = 1;
dbg_showcycles = 1;
$readmemh ("TEST1.ROM", rom);
dbg_limitcycles = 1;
dbg_maxcycles = 500;
end
endtask
task test2;
begin
$display ("SYNTHETIC PIC 2.0. This is TEST #2");
#1;
// Only Watch Port B
dbg_showportb = 1;
$readmemh ("TEST2.ROM", rom);
dbg_limitcycles = 1;
dbg_maxcycles = 500;
end
endtask
task test3;
begin
$display ("SYNTHETIC PIC 2.0. This is TEST #3");
#1;
// Only Watch Port B
dbg_showportb = 1;
$readmemh ("TEST3.ROM", rom);
dbg_limitcycles = 1;
dbg_maxcycles = 500;
end
endtask
task test4;
begin
$display ("SYNTHETIC PIC 2.0. This is TEST #4");
#1;
// Only Watch Port B
dbg_showportb = 1;
$readmemh ("TEST4.ROM", rom);
dbg_limitcycles = 1;
dbg_maxcycles = 500;
end
endtask
task test5;
begin
$display ("SYNTHETIC PIC 2.0. This is TEST #5");
#1;
// Only Watch Port B
dbg_showportb = 1;
$readmemh ("TEST5.ROM", rom);
dbg_limitcycles = 1;
dbg_maxcycles = 500;
end
endtask
task test6;
begin
$display ("SYNTHETIC PIC 2.0. This is TEST #6");
#1;
// Watch Port B and C
dbg_showportb = 1;
dbg_showportc = 1;
dbg_limitcycles = 0;
$readmemh ("TEST6.ROM", rom);
#200;
repeat (20) begin
porta = $random;
#10000;
end
$finish;
end
endtask
task test7;
begin
$display ("SYNTHETIC PIC 2.0. This is TEST #7");
#1;
// Only Watch Port B
dbg_showportb = 1;
$readmemh ("TEST7.ROM", rom);
dbg_limitcycles = 1;
dbg_maxcycles = 500;
end
endtask
task test8;
begin
$display ("SYNTHETIC PIC 2.0. This is TEST #8");
#1;
// Watch All ports
dbg_showporta = 1;
dbg_showportb = 1;
dbg_showportc = 1;
$readmemh ("TEST8.ROM", rom);
dbg_limitcycles = 1;
dbg_maxcycles = 500;
end
endtask
task test9;
begin
$display ("SYNTHETIC PIC 2.0. This is TEST #9");
#1;
// Watch All ports
dbg_showportb = 1;
dbg_showportc = 1;
$readmemh ("TEST9.ROM", rom);
dbg_limitcycles = 1;
dbg_maxcycles = 2000;
end
endtask
// ******** END Of TEST TASKS
// Cycles counter
//
initial begin
cycles = 0;
#1;
// Don't start counting until after reset.
@(negedge reset);
forever begin
@(posedge clk);
cycles = cycles + 1;
if ((cycles % 256) == 0) begin
if (dbg_showcycles) begin
$display ("#Cycles = %0d", cycles);
end
end
if (dbg_limitcycles) begin
if (cycles > dbg_maxcycles) begin
$display ("Maximum cycles (%0d) Exceeded. Halting simulation.", dbg_maxcycles);
$finish;
end
end
end
end
always @(romaddr) begin
if (dbg_showrom)
$display ("ROM Address = %h, Data = %h", romaddr, romdata);
end
always @(porta) begin
if (dbg_showporta)
$display ("porta changes to: %h", porta);
end
always @(portb) begin
if (dbg_showportb)
$display ("portb changes to: %h", portb);
end
always @(portc) begin
if (dbg_showportc)
$display ("portc changes to: %h", portc);
end
initial begin
if (dbg_showw) begin
forever begin
@(negedge clk);
if (debugw != last_debugw) begin
$display ("W = %0h", debugw);
end
last_debugw = debugw;
end
end
end
initial begin
if (dbg_showpc) begin
forever begin
@(negedge clk);
$display ("PC = %0h", debugpc);
end
end
end
reg [11:0] last_pc;
always @(posedge clk) begin
last_pc = debugpc;
end
initial begin
if (dbg_showinst) begin
forever begin
@(negedge clk);
if (debuginst[11:0] == 12'b0000_0000_0000) begin
$display ("%h NOP", last_pc);
end
else if (debuginst[11:5] == 7'b0000_001) begin
$display ("%h MOVWF f=0x%0h", last_pc, debuginst[4:0]);
end
else if (debuginst == 12'b0000_0100_0000) begin
$display ("%h CLRW", last_pc);
end
else if (debuginst[11:5] == 7'b0000_011) begin
$display ("%h CLRF f=0x%0h", last_pc, debuginst[4:0]);
end
else if (debuginst[11:6] == 7'b0000_10) begin
if (piccpu_inst.d == 0) $display ("%h SUBWF f=0x%0h, W", last_pc, debuginst[4:0]);
else $display ("%h SUBWF f=0x%0h, f", last_pc, debuginst[4:0]);
end
else if (debuginst[11:6] == 7'b0000_11) begin
if (piccpu_inst.d == 0) $display ("%h DECF f=0x%0h, W", last_pc, debuginst[4:0]);
else $display ("%h DECF f=0x%0h, f", last_pc, debuginst[4:0]);
end
else if (debuginst[11:6] == 7'b0001_00) begin
if (piccpu_inst.d == 0) $display ("%h IORWF f=0x%0h, W", last_pc, debuginst[4:0]);
else $display ("%h IORWF f=0x%0h, f", last_pc, debuginst[4:0]);
end
else if (debuginst[11:6] == 7'b0001_01) begin
if (piccpu_inst.d == 0) $display ("%h ANDWF f=0x%0h, W", last_pc, debuginst[4:0]);
else $display ("%h ANDWF f=0x%0h, f", last_pc, debuginst[4:0]);
end
else if (debuginst[11:6] == 7'b0001_10) begin
if (piccpu_inst.d == 0) $display ("XORWF f=0x%0h, W", last_pc, debuginst[4:0]);
else $display ("%h XORWF f=0x%0h, f", last_pc, debuginst[4:0]);
end
else if (debuginst[11:6] == 7'b0001_11) begin
if (piccpu_inst.d == 0) $display ("%h ADDWF f=0x%0h, W", last_pc, debuginst[4:0]);
else $display ("%h ADDWF f=0x%0h, f", last_pc, debuginst[4:0]);
end
else if (debuginst[11:6] == 7'b0010_00) begin
if (piccpu_inst.d == 0) $display ("%h MOVF f=0x%0h, W", last_pc, debuginst[4:0]);
else $display ("%h MOVF f=0x%0h, f", last_pc, debuginst[4:0]);
end
else if (debuginst[11:6] == 7'b0010_01) begin
if (piccpu_inst.d == 0) $display ("%h COMF f=0x%0h, W", last_pc, debuginst[4:0]);
else $display ("%h COMF f=0x%0h, f", last_pc, debuginst[4:0]);
end
else if (debuginst[11:6] == 7'b0010_10) begin
if (piccpu_inst.d == 0) $display ("%h INCF f=0x%0h,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -