訊息
|
cpu0p0.3.zip
輸入程式:cpu0p.hex
00 1F 00 24 // 0000 LD R1, K1
00 2F 00 1C // 0004 LD R2, K0
00 3F 00 20 // 0008 LD R3, SUM
08 40 00 0A // 000C LDI R4, 10
13 22 10 00 // 0010 LOOP: ADD R2, R2, R1
13 33 20 00 // 0014 ADD R3, R3, R2
10 24 00 00 // 0018 CMP R2, R4
21 FF FF F0 // 001C JNE LOOP
2C 00 00 00 // 0020 RET
00 00 00 00 // 0024 K0: WORD 0
00 00 00 01 // 0028 K1: WORD 1
00 00 00 00 // 002C SUM: WORD 0
Verilog 程式
// 定義:寬度形態常數
`define INT32 2'b11 // 寬度 32 位元
`define INT24 2'b10 // 寬度 24 位元
`define INT16 2'b01 // 寬度 16 位元
`define BYTE 2'b00 // 寬度 8 位元
// 記憶體狀態
`define WAITING 2'b00 // 閒置中
`define READING 2'b01 // 讀取中
`define WRITING 2'b10 // 寫入中
// 記憶體讀寫
`define READ 1'b1 // 讀取
`define WRITE 1'b0 // 寫入
module ifetch(input clock, reset);
always @(posedge clock) begin
// $display("m_state=%d pc1=%x", m_state, pc1);
if (cpu0.m_state == `WAITING && cpu0.m_en == 0) begin
cpu0.m_rw = `READ; // 讀取模式:read
cpu0.m_en = 1; // 啟動讀取
cpu0.m_w1 = `INT32;
cpu0.pc = cpu0.pc + 4;
cpu0.mar = cpu0.pc;
$display("%-4d:ifetch(abus=pc=%x)", $stime, cpu0.pc);
end
end
endmodule
module idecode(input clock, reset);
reg signed [11:0] cx12;
reg signed [15:0] cx16;
reg signed [23:0] cx24;
always @(posedge clock) begin
// if (cpu0.m_state == `WAITING && cpu0.m_en == 1) begin
cpu0.ir = cpu0.mdr; // 取得指令
cpu0.m_en = 0; // 讀取完畢
{cpu0.op,cpu0.a,cpu0.b,cpu0.c,cx12} = cpu0.ir;
cx24 = cpu0.ir[23:0];
cx16 = cpu0.ir[15:0];
cpu0.c5 = cpu0.ir[4:0];
cpu0.c12 = cx12; // 取出 cx12 並轉為 32 位元有號數 c12
cpu0.c16 = cx16; // 取出 cx16 並轉為 32 位元有號數 c16
cpu0.c24 = cx24; // 取出 cx24 並轉為 32 位元有號數 c24
$display("%-8d:idecode(mdr=%x ir=%x op=%x a=%x b=%x c=%x cx12=%x)", $stime, cpu0.mdr, cpu0.ir, cpu0.op, cpu0.a, cpu0.b, cpu0.c, cpu0.c12);
// end
end
endmodule
module cpu0(input clock, reset, input [1:0] m_state, output [31:0] pc, abus, dbus, output reg m_en, m_rw, output reg [1:0] m_w1);
reg signed [31:0] R [0:15];
reg [7:0] op;
reg [3:0] a, b, c;
reg [4:0] c5;
reg signed [31:0] c12, c16, c24, Ra, Rb, Rc, ipc; // ipc:instruction PC
reg [31:0] pc, ir, mar, mdr;
initial begin
pc = 0;
m_en = 0;
end
assign abus = mar;
always @(m_en, dbus) begin
if (m_en && m_rw==`READ && dbus !== 32'hZ)
mdr = dbus;
end
ifetch if1(clock, reset);
idecode id1(clock, reset);
// tick2 t2(.clock(clock), .reset(reset), .dbus(dbus), .ir(ir), .m_en(m_en));
// controller ctrl(.clock(clock), .reset(reset), .pc(pc), .abus(abus), .dbus(dbus), .ir(ir), .m_en(m_en), .m_rw(m_rw));
endmodule
module memory0(input clock, reset, m_en, m_rw, input [1:0] m_w1,
input [31:0] abus, inout [31:0] dbus, output [1:0] m_state);
reg [7:0] m [0:258];
reg [31:0] data;
reg m_state = `WAITING;
integer i;
initial begin
$readmemh("cpu0p.hex", m);
for (i=0; i < 255; i=i+4) begin
$display("%8x: %8x", i, {m[i], m[i+1], m[i+2], m[i+3]});
end
end
always @(abus or m_en or m_rw or m_state or dbus)
begin
// $display("%d:1 memory trigger(m_en=%b, m_rw=%b, m_state=%b, abus=%x)", $stime, m_en, m_rw, m_state, abus);
if (abus >=0 && abus <= 255) begin
// $display("%d:2 memory trigger(m_en=%b, m_rw=%b, m_state=%b)", $stime, m_en, m_rw, m_state);
if (m_en == 1) begin
if (m_rw == 0) begin // r_w==0:write
m_state = `WRITING;
#10;
data = dbus;
case (m_w1)
`BYTE: {m[abus]} = dbus[7:0];
`INT16: {m[abus], m[abus+1] } = dbus[15:0];
`INT24: {m[abus], m[abus+1], m[abus+2]} = dbus[24:0];
`INT32: {m[abus], m[abus+1], m[abus+2], m[abus+3]} = dbus;
endcase
$display("%-8d:write(abus=%x data=%x)", $stime, abus, data);
m_state = `WAITING;
end else begin// r_w==1:read
m_state = `READING;
#10;
case (m_w1)
`BYTE: data = {8'h00 , 8'h00, 8'h00, m[abus] };
`INT16: data = {8'h00 , 8'h00, m[abus], m[abus+1] };
`INT24: data = {8'h00 , m[abus], m[abus+1], m[abus+2] };
`INT32: data = {m[abus], m[abus+1], m[abus+2], m[abus+3]};
endcase
$display("%-8d:read(abus=%x data=%x)", $stime, abus, data);
m_state = `WAITING;
end
end else // m_en==0
data = 32'hZZZZZZZZ;
end else // a > 255
data = 32'hZZZZZZZZ;
end
assign dbus = data;
endmodule
module main;
reg clock, reset;
wire [31:0] abus, dbus, pc;
wire m_en, m_rw;
wire [1:0] m_w1, m_state;
cpu0 cpu(.clock(clock), .reset(reset), .m_state(m_state), .pc(pc), .abus(abus), .dbus(dbus), .m_en(m_en), .m_rw(m_rw), .m_w1(m_w1));
memory0 mem(.clock(clock), .reset(reset), .m_en(m_en), .m_rw(m_rw), .m_state(m_state), .m_w1(m_w1), .abus(abus), .dbus(dbus));
initial
begin
clock = 0;
reset = 1;
#10 reset=0;
#1000 $finish;
end
always #50 begin
clock=clock+1;
// $monitor("%4dns pc=%x", $stime, pc);
end
endmodule
執行結果
D:\oc\pipepc>iverilog cpu0p.v -o cpu0p
D:\oc\pipepc>vvp cpu0p
WARNING: cpu0p.v:81: $readmemh(cpu0p.hex): Not enough words in the file for the
requested range [0:258].
00000000: 001f0024
00000004: 002f001c
00000008: 003f0020
0000000c: 0840000a
00000010: 13221000
00000014: 13332000
00000018: 10240000
0000001c: 21fffff0
00000020: 2c000000
00000024: 00000000
00000028: 00000001
0000002c: 00000000
00000030: xxxxxxxx
00000034: xxxxxxxx
00000038: xxxxxxxx
0000003c: xxxxxxxx
00000040: xxxxxxxx
00000044: xxxxxxxx
00000048: xxxxxxxx
0000004c: xxxxxxxx
00000050: xxxxxxxx
00000054: xxxxxxxx
00000058: xxxxxxxx
0000005c: xxxxxxxx
00000060: xxxxxxxx
00000064: xxxxxxxx
00000068: xxxxxxxx
0000006c: xxxxxxxx
00000070: xxxxxxxx
00000074: xxxxxxxx
00000078: xxxxxxxx
0000007c: xxxxxxxx
00000080: xxxxxxxx
00000084: xxxxxxxx
00000088: xxxxxxxx
0000008c: xxxxxxxx
00000090: xxxxxxxx
00000094: xxxxxxxx
00000098: xxxxxxxx
0000009c: xxxxxxxx
000000a0: xxxxxxxx
000000a4: xxxxxxxx
000000a8: xxxxxxxx
000000ac: xxxxxxxx
000000b0: xxxxxxxx
000000b4: xxxxxxxx
000000b8: xxxxxxxx
000000bc: xxxxxxxx
000000c0: xxxxxxxx
000000c4: xxxxxxxx
000000c8: xxxxxxxx
000000cc: xxxxxxxx
000000d0: xxxxxxxx
000000d4: xxxxxxxx
000000d8: xxxxxxxx
000000dc: xxxxxxxx
000000e0: xxxxxxxx
000000e4: xxxxxxxx
000000e8: xxxxxxxx
000000ec: xxxxxxxx
000000f0: xxxxxxxx
000000f4: xxxxxxxx
000000f8: xxxxxxxx
000000fc: xxxxxxxx
50 :idecode(mdr=xxxxxxxx ir=xxxxxxxx op=xx a=x b=x c=x cx12=xxxxxxxx)
50 :ifetch(abus=pc=00000004)
60 :read(abus=00000004 data=002f001c)
150 :idecode(mdr=002f001c ir=002f001c op=00 a=2 b=f c=0 cx12=0000001c)
250 :idecode(mdr=002f001c ir=002f001c op=00 a=2 b=f c=0 cx12=0000001c)
250 :ifetch(abus=pc=00000008)
260 :read(abus=00000008 data=003f0020)
350 :idecode(mdr=003f0020 ir=003f0020 op=00 a=3 b=f c=0 cx12=00000020)
450 :idecode(mdr=003f0020 ir=003f0020 op=00 a=3 b=f c=0 cx12=00000020)
450 :ifetch(abus=pc=0000000c)
460 :read(abus=0000000c data=0840000a)
550 :idecode(mdr=0840000a ir=0840000a op=08 a=4 b=0 c=0 cx12=0000000a)
650 :idecode(mdr=0840000a ir=0840000a op=08 a=4 b=0 c=0 cx12=0000000a)
650 :ifetch(abus=pc=00000010)
660 :read(abus=00000010 data=13221000)
750 :idecode(mdr=13221000 ir=13221000 op=13 a=2 b=2 c=1 cx12=00000000)
850 :idecode(mdr=13221000 ir=13221000 op=13 a=2 b=2 c=1 cx12=00000000)
850 :ifetch(abus=pc=00000014)
860 :read(abus=00000014 data=13332000)
950 :idecode(mdr=13332000 ir=13332000 op=13 a=3 b=3 c=2 cx12=00000000)
D:\oc\pipepc>
參考文獻
- Hardware pipelining example, Written by Yann Sionneau, Tuesday, 01 November 2011 11:24
Facebook
|
Post preview:
Close preview