訊息
|
輸入指令檔:cpu0s.hex
00 DF 00 9A // 0 LD R13, StackPtr
30 E0 00 00 // 4 PUSH R14
08 40 00 04 // 8 LDI R4, 4
08 50 00 05 // c LDI R5, 5
12 65 00 00 // 10 MOV R6, R5
13 75 40 00 // 14 ADD R7, R5, R4
14 85 40 00 // 18 SUB R8, R5, R4
15 85 40 00 // 1c MUL R8, R5, R4
16 85 40 00 // 20 DIV R8, R5, R4
18 85 40 00 // 24 AND R8, R5, R4
19 85 40 00 // 28 OR R8, R5, R4
1A 85 40 00 // 2c XOR R8, R5, R4
1E 85 00 03 // 30 SHL R8, R5, 3
1F 85 00 02 // 34 SHR R8, R5, 2
10 45 00 00 // 38 CMP R4, R5
20 00 00 18 // 3c JEQ L1
23 00 00 14 // 40 JGT L1
25 00 00 10 // 44 JGE L1
22 00 00 0C // 48 JLT L1
24 00 00 08 // 4c JLE L1
21 00 00 04 // 50 JNE L1
26 00 00 00 // 54 JMP L1
08 10 00 0A // 58 L1: LDI R1, 10
2B 00 00 08 // 5c CALL SUM
31 E0 00 00 // 60 POP R14
2C 00 00 00 // 64 RET
// 68 SUM:
30 E0 00 00 // 68 PUSH R14
12 30 00 00 // 6c MOV R3, R0
02 4F 00 24 // 70 LDB R4, k1
08 20 00 00 // 74 LDI R2, 0
// 78 LOOP:
13 22 30 00 // 78 ADD R2, R2, R3
13 33 40 00 // 7c ADD R3, R3, R4
10 31 00 00 // 80 CMP R3, R1
24 FF FF F0 // 84 JLE LOOP
01 2F 00 0D // 88 ST R2, s
03 3F 00 0D // 8c STB R3, i
31 E0 00 00 // 90 POP R14
2C 00 00 00 // 94 RET
01 // 98 k1: BYTE 1
00 00 00 00 // 99 s: WORD 0
00 // 9d i: BYTE 0
00 00 00 B6 // 9e StackPtr: WORD StackEnd
00 00 00 00 // a2 Stack: RESB 20
00 00 00 00
00 00 00 00
00 00 00 00
00 00 00 00
// b6 StackEnd:
以上機器碼的原始組合語言如下:
// LDR, STR, LBR, SBR => 未測試到
LD R13, StackPtr
PUSH R14
LDI R4, 4
LDI R5, 5
MOV R6, R5
ADD R7, R5, R4
SUB R8, R5, R4
MUL R8, R5, R4
DIV R8, R5, R4
AND R8, R5, R4
OR R8, R5, R4
XOR R8, R5, R4
SHL R8, R5, 3
SHR R8, R5, 2
CMP R4, R5
JEQ L1
JGT L1
JGE L1
JLT L1
JLE L1
JNE L1
JMP L1
L1: LDI R1, 10
CALL SUM
POP R14
RET
// SUM = R2 = sum(0..R1)
SUM:
PUSH R14
MOV R3, R0 // R3 = i = 0
LDB R4, k1 // R4 = 1
LDI R2, 0 // SUM = R2 = 0
LOOP:
ADD R2, R2, R3 // SUM = SUM + i
ADD R3, R3, R4 // i = i + 1
CMP R3, R1 // if (i < R1)
JLE LOOP // goto LOOP
ST R2, s
STB R3, i
POP R14
RET // return
k1: BYTE 1 // char K1=1
s: WORD 0 // int s
i: BYTE 0 // char i=1
StackPtr: WORD StackEnd
Stack: RESB 20
StackEnd:
Verilog 程式:cpu0s3.v
// 寬度形態常數
`define INT32 2'b11 // 寬度 32 位元
`define INT24 2'b10 // 寬度 24 位元
`define INT16 2'b01 // 寬度 16 位元
`define BYTE 2'b00 // 寬度 8 位元
// 參考文獻:http://ccckmit.wikidot.com/ocs:cpu0
module cpu0(input clock, reset, output reg [2:0] tick,
output reg [31:0] ir, pc, mar, mdr, inout [31:0] 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 signed [11:0] cx12;
reg signed [15:0] cx16;
reg signed [23:0] cx24;
reg [4:0] c5;
reg signed [31:0] c12, c16, c24, Ra, Rb, Rc, ipc; // ipc:instruction PC
// 暫存器簡稱
`define PC R[15] // 程式計數器
`define LR R[14] // 連結暫存器
`define SP R[13] // 堆疊暫存器
`define SW R[12] // 狀態暫存器
// 狀態暫存器旗標位元
`define N `SW[31] // 負號旗標
`define Z `SW[30] // 零旗標
`define C `SW[29] // 進位旗標
`define V `SW[28] // 溢位旗標
`define I `SW[7] // 硬體中斷許可
`define T `SW[6] // 軟體中斷許可
`define M `SW[0] // 模式位元
// 指令編碼表
parameter [7:0] LD=8'h00,ST=8'h01,LDB=8'h02,STB=8'h03,LDR=8'h04,STR=8'h05,
LBR=8'h06,SBR=8'h07,LDI=8'h08,CMP=8'h10,MOV=8'h12,ADD=8'h13,SUB=8'h14,
MUL=8'h15,DIV=8'h16,AND=8'h18,OR=8'h19,XOR=8'h1A,ROL=8'h1C,ROR=8'h1D,
SHL=8'h1E,SHR=8'h1F,JEQ=8'h20,JNE=8'h21,JLT=8'h22,JGT=8'h23,JLE=8'h24,
JGE=8'h25,JMP=8'h26,SWI=8'h2A,CALL=8'h2B,RET=8'h2C,IRET=8'h2D,
PUSH=8'h30,POP=8'h31,PUSHB=8'h32,POPB=8'h33;
task memReadStart(input [31:0] addr, input [1:0] w1); begin // 讀取記憶體 Word
mar = addr; // read(m[addr])
m_rw = 1; // 讀取模式:read
m_en = 1; // 啟動讀取
m_w1 = w1;
end endtask
task memReadEnd(output [31:0] data); begin // 讀取記憶體完成,取得資料
mdr = dbus; // 取得記憶體傳回的 dbus = m[addr]
data = mdr; // 傳回資料
m_en = 0; // 讀取完畢
end endtask
// 寫入記憶體 -- addr:寫入位址, data:寫入資料
task memWriteStart(input [31:0] addr, input [31:0] data, input [1:0] w1); begin
mar = addr; // write(m[addr], data)
mdr = data;
m_rw = 0; // 寫入模式:write
m_en = 1; // 啟動寫入
m_w1 = w1;
end endtask
task memWriteEnd; begin // 寫入記憶體完成
m_en = 0; // 寫入完畢
end endtask
task regSet(input [3:0] i, input [31:0] data); begin
if (i!=0) R[i] = data;
end endtask
always @(posedge clock) begin
if (reset) begin
`PC = 0;
tick = 0;
R[0] = 0;
`SW = 0;
`LR = -1;
end
else begin
tick = tick+1;
m_en = 0;
case (tick)
1: begin // Tick 1 : 指令擷取,將 PC 丟到位址匯流排上,memory.read(m[PC])
memReadStart(`PC, `INT32);
ipc = `PC;
`PC = `PC+4;
end
2: begin // Tick 2 : 指令解碼,ir = m[PC]
memReadEnd(ir); // IR = dbus = m[PC]
{op,a,b,c,cx12} = ir;
cx24 = ir[23:0];
cx16 = ir[15:0];
c5 = ir[4:0];
c12 = cx12; // 取出 cx12 並轉為 32 位元有號數 c12
c16 = cx16; // 取出 cx16 並轉為 32 位元有號數 c16
c24 = cx24; // 取出 cx24 並轉為 32 位元有號數 c24
Ra = R[a];
Rb = R[b];
Rc = R[c];
end
3: begin // Tick 3 : 指令執行
case (op)
// 載入儲存指令
LD: memReadStart(Rb+c16, `INT32); // 載入word; LD Ra, [Rb+Cx]; Ra<=[Rb+ Cx]
ST: memWriteStart(Rb+c16, Ra, `INT32); // 儲存word; ST Ra, [Rb+ Cx]; Ra=>[Rb+ Cx]
LDB: memReadStart(Rb+c16, `BYTE); // 載入byte; LDB Ra, [Rb+ Cx]; Ra<=(byte)[Rb+ Cx]
STB: memWriteStart(Rb+c16, Ra, `BYTE); // 儲存byte; STB Ra, [Rb+ Cx]; Ra=>(byte)[Rb+ Cx]
LDR: memReadStart(Rb+Rc, `INT32); // LD的Rc版; LDR Ra, [Rb+Rc]; Ra<=[Rb+ Rc]
STR: memWriteStart(Rb+Rc, Ra, `INT32); // ST的Rc版; STR Ra, [Rb+Rc]; Ra=>[Rb+ Rc]
LBR: memReadStart(Rb+Rc, `BYTE); // LDB的Rc版; LBR Ra, [Rb+Rc]; Ra<=(byte)[Rb+ Rc]
SBR: memWriteStart(Rb+Rc, Ra, `BYTE); // STB的Rc版; SBR Ra, [Rb+Rc]; Ra=>(byte)[Rb+ Rc]
LDI: R[a] = Rb+c16; // 立即載入; LDI Ra, Rb+Cx; Ra<=Rb + Cx
// 運算指令
CMP: begin `N=(Ra-Rb<0);`Z=(Ra-Rb==0); end // 比較; CMP Ra, Rb; SW=(Ra >=< Rb)
MOV: regSet(a, Rb); // 移動; MOV Ra, Rb; Ra<=Rb
ADD: regSet(a, Rb+Rc); // 加法; ADD Ra, Rb, Rc; Ra<=Rb+Rc
SUB: regSet(a, Rb-Rc); // 減法; SUB Ra, Rb, Rc; Ra<=Rb-Rc
MUL: regSet(a, Rb*Rc); // 乘法; MUL Ra, Rb, Rc; Ra<=Rb*Rc
DIV: regSet(a, Rb/Rc); // 除法; DIV Ra, Rb, Rc; Ra<=Rb/Rc
AND: regSet(a, Rb&Rc); // 位元 AND; AND Ra, Rb, Rc; Ra<=Rb and Rc
OR: regSet(a, Rb|Rc); // 位元 OR; OR Ra, Rb, Rc; Ra<=Rb or Rc
XOR: regSet(a, Rb^Rc); // 位元 XOR; XOR Ra, Rb, Rc; Ra<=Rb xor Rc
SHL: regSet(a, Rb<<c5); // 向左移位; SHL Ra, Rb, Cx; Ra<=Rb << Cx
SHR: regSet(a, Rb>>c5); // 向右移位; SHR Ra, Rb, Cx; Ra<=Rb >> Cx
// 跳躍指令
JEQ: if (`Z) `PC=`PC+c24; // 跳躍 (相等); JEQ Cx; if SW(=) PC PC+Cx
JNE: if (!`Z) `PC=`PC+c24; // 跳躍 (不相等); JNE Cx; if SW(!=) PC PC+Cx
JLT: if (`N&&!`Z)`PC=`PC+c24; // 跳躍 ( < ); JLT Cx; if SW(<) PC PC+Cx
JGT: if (!`N&&`Z) `PC=`PC+c24; // 跳躍 ( > ); JGT Cx; if SW(>) PC PC+Cx
JLE: if (`N || `Z) `PC=`PC+c24; // 跳躍 ( <= ); JLE Cx; if SW(<=) PC PC+Cx
JGE: if (!`N || `Z) `PC=`PC+c24; // 跳躍 ( >= ); JGE Cx; if SW(>=) PC PC+Cx
JMP: `PC = `PC+c24; // 跳躍 (無條件); JMP Cx; PC <= PC+Cx
SWI: begin `LR=`PC;`PC= c24; `I = 1'b1; end // 軟中斷; SWI Cx; LR <= PC; PC <= Cx; INT<=1
CALL:begin `LR=`PC;`PC=`PC + c24; end // 跳到副程式; CALL Cx; LR<=PC; PC<=PC+Cx
RET: begin `PC=`LR; end // 返回; RET; PC <= LR
IRET:begin `PC=`LR;`I = 1'b0; end // 中斷返回; IRET; PC <= LR; INT<=0
// 堆疊指令
PUSH:begin `SP = `SP-4; memWriteStart(`SP, Ra, `INT32); end // 推入 word; PUSH Ra; SP-=4;[SP]<=Ra;
POP: begin memReadStart(`SP, `INT32); `SP = `SP + 4; end // 彈出 word; POP Ra; Ra=[SP];SP+=4;
PUSHB:begin `SP = `SP-1; memWriteStart(`SP, Ra, `BYTE); end // 推入 byte; PUSHB Ra; SP--;[SP]<=Ra;(byte)
POPB:begin memReadStart(`SP, `BYTE); `SP = `SP+1; end // 彈出 byte; POPB Ra; Ra<=[SP];SP++;(byte)
endcase
end
4: begin // 讀取寫入指令完成,關閉記憶體
case (op)
LD, LDB, LDR, LBR, POP, POPB : memReadEnd(R[a]); // 讀取記憶體完成
ST, STB, STR, SBR, PUSH, PUSHB: memWriteEnd(); // 寫入記憶體完成
endcase
$display("%4dns %8x : %8x R[%02d]=%-8x=%-d SW=%8x", $stime, ipc, ir, a, R[a], R[a], `SW);
if (op==RET && `PC < 0) begin
$display("RET to PC < 0, finished!");
$finish;
end
tick = 0;
end
endcase
end
pc = `PC;
end
endmodule
module memory0(input clock, reset, en, rw, input [1:0] m_w1,
input [31:0] abus, dbus_in, output [31:0] dbus_out);
reg [7:0] m [0:258];
reg [31:0] data;
integer i;
initial begin
$readmemh("cpu0s.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 @(clock or abus or en or rw or dbus_in)
begin
if (abus >=0 && abus <= 255) begin
if (en == 1 && rw == 0) begin // r_w==0:write
data = dbus_in;
case (m_w1)
`BYTE: {m[abus]} = dbus_in[7:0];
`INT16: {m[abus], m[abus+1] } = dbus_in[15:0];
`INT24: {m[abus], m[abus+1], m[abus+2]} = dbus_in[24:0];
`INT32: {m[abus], m[abus+1], m[abus+2], m[abus+3]} = dbus_in;
endcase
end else if (en == 1 && rw == 1) begin// r_w==1:read
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
end else
data = 32'hZZZZZZZZ;
end else
data = 32'hZZZZZZZZ;
end
assign dbus_out = data;
endmodule
module main;
reg clock, reset;
wire [2:0] tick;
wire [31:0] pc, ir, mar, mdr, dbus;
wire m_en, m_rw;
wire [1:0] m_w1;
cpu0 cpu(.clock(clock), .reset(reset), .pc(pc), .tick(tick), .ir(ir),
.mar(mar), .mdr(mdr), .dbus(dbus), .m_en(m_en), .m_rw(m_rw), .m_w1(m_w1));
memory0 mem(.clock(clock), .reset(reset), .en(m_en), .rw(m_rw), .m_w1(m_w1),
.abus(mar), .dbus_in(mdr), .dbus_out(dbus));
initial
begin
clock = 0;
reset = 1;
#20 reset = 0;
#10000 $finish;
end
always #10 clock=clock+1;
endmodule
執行結果
D:\oc\cpu0>iverilog cpu0s3.v -o cpu0s3
D:\oc\cpu0>vvp cpu0s3
WARNING: cpu0s3.v:169: $readmemh(cpu0s.hex): Not enough words in the file for th
e requested range [0:258].
00000000: 00df009a
00000004: 30e00000
00000008: 08400004
0000000c: 08500005
00000010: 12650000
00000014: 13754000
00000018: 14854000
0000001c: 15854000
00000020: 16854000
00000024: 18854000
00000028: 19854000
0000002c: 1a854000
00000030: 1e850003
00000034: 1f850002
00000038: 10450000
0000003c: 20000018
00000040: 23000014
00000044: 25000010
00000048: 2200000c
0000004c: 24000008
00000050: 21000004
00000054: 26000000
00000058: 0810000a
0000005c: 2b000008
00000060: 31e00000
00000064: 2c000000
00000068: 30e00000
0000006c: 12300000
00000070: 024f0024
00000074: 08200000
00000078: 13223000
0000007c: 13334000
00000080: 10310000
00000084: 24fffff0
00000088: 012f000d
0000008c: 033f000d
00000090: 31e00000
00000094: 2c000000
00000098: 01000000
0000009c: 00000000
000000a0: 00b60000
000000a4: 00000000
000000a8: 00000000
000000ac: 00000000
000000b0: 00000000
000000b4: 0000xxxx
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
90ns 00000000 : 00df009a R[13]=000000b6=182 SW=00000000
170ns 00000004 : 30e00000 R[14]=ffffffff=-1 SW=00000000
250ns 00000008 : 08400004 R[04]=00000004=4 SW=00000000
330ns 0000000c : 08500005 R[05]=00000005=5 SW=00000000
410ns 00000010 : 12650000 R[06]=00000005=5 SW=00000000
490ns 00000014 : 13754000 R[07]=00000009=9 SW=00000000
570ns 00000018 : 14854000 R[08]=00000001=1 SW=00000000
650ns 0000001c : 15854000 R[08]=00000014=20 SW=00000000
730ns 00000020 : 16854000 R[08]=00000001=1 SW=00000000
810ns 00000024 : 18854000 R[08]=00000004=4 SW=00000000
890ns 00000028 : 19854000 R[08]=00000005=5 SW=00000000
970ns 0000002c : 1a854000 R[08]=00000001=1 SW=00000000
1050ns 00000030 : 1e850003 R[08]=00000028=40 SW=00000000
1130ns 00000034 : 1f850002 R[08]=00000001=1 SW=00000000
1210ns 00000038 : 10450000 R[04]=00000004=4 SW=80000000
1290ns 0000003c : 20000018 R[00]=00000000=0 SW=80000000
1370ns 00000040 : 23000014 R[00]=00000000=0 SW=80000000
1450ns 00000044 : 25000010 R[00]=00000000=0 SW=80000000
1530ns 00000048 : 2200000c R[00]=00000000=0 SW=80000000
1610ns 00000058 : 0810000a R[01]=0000000a=10 SW=80000000
1690ns 0000005c : 2b000008 R[00]=00000000=0 SW=80000000
1770ns 00000068 : 30e00000 R[14]=00000060=96 SW=80000000
1850ns 0000006c : 12300000 R[03]=00000000=0 SW=80000000
1930ns 00000070 : 024f0024 R[04]=00000001=1 SW=80000000
2010ns 00000074 : 08200000 R[02]=00000000=0 SW=80000000
2090ns 00000078 : 13223000 R[02]=00000000=0 SW=80000000
2170ns 0000007c : 13334000 R[03]=00000001=1 SW=80000000
2250ns 00000080 : 10310000 R[03]=00000001=1 SW=80000000
2330ns 00000084 : 24fffff0 R[15]=00000078=120 SW=80000000
2410ns 00000078 : 13223000 R[02]=00000001=1 SW=80000000
2490ns 0000007c : 13334000 R[03]=00000002=2 SW=80000000
2570ns 00000080 : 10310000 R[03]=00000002=2 SW=80000000
2650ns 00000084 : 24fffff0 R[15]=00000078=120 SW=80000000
2730ns 00000078 : 13223000 R[02]=00000003=3 SW=80000000
2810ns 0000007c : 13334000 R[03]=00000003=3 SW=80000000
2890ns 00000080 : 10310000 R[03]=00000003=3 SW=80000000
2970ns 00000084 : 24fffff0 R[15]=00000078=120 SW=80000000
3050ns 00000078 : 13223000 R[02]=00000006=6 SW=80000000
3130ns 0000007c : 13334000 R[03]=00000004=4 SW=80000000
3210ns 00000080 : 10310000 R[03]=00000004=4 SW=80000000
3290ns 00000084 : 24fffff0 R[15]=00000078=120 SW=80000000
3370ns 00000078 : 13223000 R[02]=0000000a=10 SW=80000000
3450ns 0000007c : 13334000 R[03]=00000005=5 SW=80000000
3530ns 00000080 : 10310000 R[03]=00000005=5 SW=80000000
3610ns 00000084 : 24fffff0 R[15]=00000078=120 SW=80000000
3690ns 00000078 : 13223000 R[02]=0000000f=15 SW=80000000
3770ns 0000007c : 13334000 R[03]=00000006=6 SW=80000000
3850ns 00000080 : 10310000 R[03]=00000006=6 SW=80000000
3930ns 00000084 : 24fffff0 R[15]=00000078=120 SW=80000000
4010ns 00000078 : 13223000 R[02]=00000015=21 SW=80000000
4090ns 0000007c : 13334000 R[03]=00000007=7 SW=80000000
4170ns 00000080 : 10310000 R[03]=00000007=7 SW=80000000
4250ns 00000084 : 24fffff0 R[15]=00000078=120 SW=80000000
4330ns 00000078 : 13223000 R[02]=0000001c=28 SW=80000000
4410ns 0000007c : 13334000 R[03]=00000008=8 SW=80000000
4490ns 00000080 : 10310000 R[03]=00000008=8 SW=80000000
4570ns 00000084 : 24fffff0 R[15]=00000078=120 SW=80000000
4650ns 00000078 : 13223000 R[02]=00000024=36 SW=80000000
4730ns 0000007c : 13334000 R[03]=00000009=9 SW=80000000
4810ns 00000080 : 10310000 R[03]=00000009=9 SW=80000000
4890ns 00000084 : 24fffff0 R[15]=00000078=120 SW=80000000
4970ns 00000078 : 13223000 R[02]=0000002d=45 SW=80000000
5050ns 0000007c : 13334000 R[03]=0000000a=10 SW=80000000
5130ns 00000080 : 10310000 R[03]=0000000a=10 SW=40000000
5210ns 00000084 : 24fffff0 R[15]=00000078=120 SW=40000000
5290ns 00000078 : 13223000 R[02]=00000037=55 SW=40000000
5370ns 0000007c : 13334000 R[03]=0000000b=11 SW=40000000
5450ns 00000080 : 10310000 R[03]=0000000b=11 SW=00000000
5530ns 00000084 : 24fffff0 R[15]=00000088=136 SW=00000000
5610ns 00000088 : 012f000d R[02]=00000037=55 SW=00000000
5690ns 0000008c : 033f000d R[03]=0000000b=11 SW=00000000
5770ns 00000090 : 31e00000 R[14]=00000060=96 SW=00000000
5850ns 00000094 : 2c000000 R[00]=00000000=0 SW=00000000
5930ns 00000060 : 31e00000 R[14]=ffffffff=-1 SW=00000000
6010ns 00000064 : 2c000000 R[00]=00000000=0 SW=00000000
RET to PC < 0, finished!
Facebook
|
Post preview:
Close preview