一、設計思路
CPU是計算機的核心,因為它是計算機指令的處理單元。
計算機體系結構包含兩個方面,一個方面是指令集,一個方面是硬件實現。指令集是計算機被定義擁有的執行指令,計算機通過支持指令集的運行,來完成計算工作並為程序員編程服務。硬件實現則是具體的硬件去實現指令集,這個硬件實現的核心就是CPU的設計。
這里寫的CPU的設計是32位機器的CPU,指令和數據均為32位。支持指令為簡化mips指令集。
2、CPU的設計
CPU的設計包含數據通路的設計和控制器的設計。數據通路是執行指令必須的硬件(ALU、IM、DM、GRF等),控制器則是根據指令產生相應控制信號,來控制相應硬件以支持多條指令。
-
數據通路設計
CPU的功能是支持指令集,因此硬件設計是為了執行指令。
設計CPU的結構的方法:先選擇一條需要經過最多硬件的指令,來為它構建數據通路。再依據其他指令在已有數據通路上添加硬件或線路,直到數據通路支持所有指令。
-
控制器設計
在已有的數據通路基礎上,針對每一條指令,列出其所需要的控制信號,每一組控制信號對應一種指令的全部執行。將指令相應字段和部分計算結果作為控制器的輸入,控制信號作為輸出,依據上述映射關系(真值表)設計控制器。
二、實際操作
0、設計說明
CPU架構的設計是沒有很多約束的,基本要求就是能夠支持指令集,基於不同的考量可以有不同的設計。舉例來說:對於beq指令是否跳轉的判斷,可以借用ALU的減法計算,也可以直接增設CMP比較器得出,兩種方式都可以,因為功能正確。為了提高吞吐量,或者為了節省成本,會選擇一些特別的設計,這一點在流水線CPU 的設計上可以明顯地看出。
CPU具體設計的方法是我下面進行的幾步:列出所需指令,寫出功能模塊,連接模塊,構造控制器,全部連接起來。這些表格對最終代碼實現十分重要,因為代碼量較大,先從表格檢查起,再依據表格寫碼可以減少bug。
1、支持指令
列出支持指令並將其分類:
| str | ld | cal_r | cal_i | lui | b_type | j | jr | jal | jalr | shamt |
|---|---|---|---|---|---|---|---|---|---|---|
| sw | lw | addu | ori | beq | sll | |||||
| subu | slti | sra | ||||||||
| slt | addiu | srl | ||||||||
| sllv | ||||||||||
| srav | ||||||||||
| srlv |
2、功能模塊
先按照lw指令列出所需功能模塊(lw經過模塊最多),再依次檢查現有模塊是否支持其余指令,若不能支持,則添加相應模塊。
| module | input | output | 功能描述 |
|---|---|---|---|
| PC | D(端口名,下同) | Q | 指令計數器 |
| ADD4 | PC | PC4 | 加4運算 |
| IM | IA | IR | 指令存儲器 |
| RF | A1 | RD1 | 寄存器堆的讀出部分 |
| A2 | RD2 | ||
| EXT | I16 | EXTD | 選擇輸出SIMM,LIMM,UIMM |
| EXTOP | |||
| CMP | D1 | RES | 比較兩個數據的大小,以決定是否分支 |
| D2 | |||
| NPC | PC4 | NEXTPC | 計算BPC,JPC |
| I26 | |||
| NPCOP | |||
| ALU | A | AO | 執行不同計算 |
| B | |||
| SHAMT | |||
| ALUOP | |||
| DM | DA | RD | 數據存儲器,支持寫入字和讀出字 |
| WD | |||
| WM | |||
| RM | |||
| RF | A3 | 寄存器堆的寫入部分 | |
| WD3 | |||
| WR |
注:上表的SIMM表示將16位立即數作符號擴展成32位;UIMM則是無符號擴展;LIMM則是專門為lui指令設計的將低16位移至高16位,並擴展至32位。BPC則是將指令地址(PC)按照分支指令地址變換方式計算分支地址,JPC則是將指令地址(PC)按照跳轉指令地址變換方式計算跳轉地址。
3、數據通路
在上一步列出的所有功能模塊基礎上,考慮如何連接這些模塊。
需要分別列出所有指令的數據通路(即在功能模塊之間連線),並將其整合起來,得到最終的數據通路(完成功能模塊的連接)。
| module | input | LD | STR | CAL_R | CAL_I | LUI | B_TYPE | J | JR | JAL | JALR | SHAMT |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| PC | ||||||||||||
| ADD4 | PC | Q | Q | Q | Q | Q | Q | Q | Q | Q | Q | Q |
| IM | IA | Q | Q | Q | Q | Q | Q | Q | Q | Q | Q | Q |
| PC | D | PC4 | PC4 | PC4 | PC4 | PC4 | PC4 | PC4 | PC4 | PC4 | PC4 | PC4 |
| RF | A1 | IR[RS] | IR[RS] | IR[RS] | IR[RS] | IR[RS] | IR[RS] | IR[RS] | ||||
| A2 | IR[RT] | IR[RT] | IR[RT] | |||||||||
| EXT | I16 | IR[I16] | IR[I16] | IR[I16] | IR[I16] | |||||||
| CMP | D1 | RD1 | ||||||||||
| D2 | RD2 | |||||||||||
| NPC | PC4 | PC4 | PC4 | PC4 | ||||||||
| I26 | IR[I16] | IR[I26] | IR[I26] | |||||||||
| PC | D | NEXTPC | NEXTPC | RD1 | NEXTPC | RD1 | ||||||
| ALU | A | RD1 | RD1 | RD1 | RD1 | |||||||
| B | EXTD | EXTD | RD2 | EXTD | RD2 | |||||||
| SHAMT | IR[SH] | |||||||||||
| DM | DA | AO | AO | |||||||||
| WD | RD2 | |||||||||||
| RF | A3 | IR[RT] | IR[RD] | IR[RD] | IR[RT] | $31 | IR[RD] | IR[RD] | ||||
| WD3 | RD | AO | AO | EXTD | PC4 | PC4 | AO |
注:IR[RS]是說,IR端口數據(指令)的RS字段。
4、控制器設計
| INPUT | INPUT | OUTPUT | OUTPUT | OUTPUT | OUTPUT | OUTPUT | OUTPUT | OUTPUT | OUTPUT | OUTPUT | OUTPUT | OUTPUT | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| INSTRUCTION | OP | FUNCT | PCSEL | EXTOP | NPCOP | ALUCTRL | ALUOP | BSEL | WM | RM | A3SEL | WD3SEL | WR |
| LW | 100011 | X | 0 | 0 | X | 0 | 0(+) | 0 | 0(不寫) | 1(讀字) | 0 | 0 | 1 |
| SW | 101011 | X | 0 | 0 | X | 0 | 0(+) | 0 | 1(寫字) | 0 | X | X | 0 |
| ADD | 000000 | 100000 | 0 | X | X | 15 | FUNCT | 1 | 0 | 0 | 1 | 1 | 1 |
| ADDU | 000000 | 100001 | 0 | X | X | 15 | FUNCT | 1 | 0 | 0 | 1 | 1 | 1 |
| SUB | 000000 | 100010 | 0 | X | X | 15 | FUNCT | 1 | 0 | 0 | 1 | 1 | 1 |
| SUBU | 000000 | 100011 | 0 | X | X | 15 | FUNCT | 1 | 0 | 0 | 1 | 1 | 1 |
| SHAMT | 000000 | FUNCT | 0 | X | X | 15 | FUNCT | 1 | 0 | 0 | 1 | 1 | 1 |
| ORI | 001101 | X | 0 | 2 | X | 2 | 2 | 0 | 0 | 0 | 0 | 1 | 1 |
| SLTI | 001010 | X | 0 | 0 | X | 3 | 3 | 0 | 0 | 0 | 0 | 1 | 1 |
| ADDIU | 001001 | X | 0 | 0 | X | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
| LUI | 001111 | X | 0 | 1 | X | X | X | X | 0 | 0 | 0 | 2 | 1 |
| BEQ | 000100 | X | RES | X | 0 | X | X | X | 0 | 0 | X | X | 0 |
| J | 000010 | X | 1 | X | 1 | X | X | X | 0 | 0 | X | X | 0 |
| JR | 000000 | 001000 | 2 | X | X | X | X | X | 0 | 0 | X | X | 0 |
| JAL | 000011 | X | 1 | X | 1 | X | X | X | 0 | 0 | 2 | 3 | 1 |
| JALR | 000000 | 001001 | 2 | X | X | X | X | X | 0 | 0 | 1 | 3 | 1 |
| NOP | 000000 | 000000 | 0 | X | X | X | X | X | 0 | 0 | X | X | 0 |
-
控制信號說明
PCSEL:用於選擇下一個指令的地址是PC4,還是NPC,或者是[RS]寄存器里的地址。NPC是分支地址(BPC)或者跳轉地址(JPC),簡單來說就是非PC4的下一條指令可能地址。
EXTOP:EXT模塊內部有多個輸出,選擇適當擴展立即數作為最終輸出的信號。
NPCOP:選擇是BPC還是JPC。(其實這里可以把PC4一起作為NPC模塊的輸入,直接選出下一條指令地址)
ALUCTRL&ALUOP:這里ALU 的控制信號是二次譯碼,ALUCTRL用來區分是否是R型計算指令,若是,則通過FUNCT字段進行二次譯碼決定ALU的輸出結果(之所以二次譯碼只因為R型指令的OP字段全為0);若不是,則可通過指令的OP字段決定ALU的輸出結果。
BSEL:ALU的第二個操作數的選擇信號,對於addu指令,B端口輸入是寄存器堆的RT輸出,對於addi指令,B端口輸入是立即數的符號擴展結果,B端口的輸入來源不同,因此需要信號選擇。
WM:數據存儲器的寫入控制信號。
RM:數據存儲器的讀出控制信號。
A3SEL:寄存器堆的寫入寄存器編號的選擇信號,因為addu指令的寫入寄存器的編號由指令RD字段給出,lw指令和jalr指令的寫入寄存器編號由指令RT字段給出,而jr指令的寫入寄存器固定是$ra(31號寄存器),該端口數據的來源不同,需要信號來選擇。
WD3SEL:寄存器堆寫入數據的選擇信號,因為寫入的數據可以是DM中讀出的數據(lw),也可以是ALU計算得到的數據(addu),也可以是經移位擴展得到的數據(lui),還可以是指令的返回地址(jal,jalr),需要信號來選擇。
WR:寄存器堆的寫入控制信號。
-
再次說明
控制信號的設計的基本要求是能滿足所有指令在同一CPU 上正確執行,因此十分依靠CPU的硬件結構,不同的結構就有其特別的控制信號設計。控制信號的設計還需要盡可能的簡潔,否則控制電路會更加復雜,上面ALU的控制信號所采用的二次譯碼就是簡化的控制信號的電路設計。
三、代碼實現
Verilog語言編寫的單周期CPU
module MFPC( //PC的多選器
input [31:0] pc4,
input [31:0] nextpc,
input [31:0] rd1,
input [1:0] pcsel,
output [31:0] d
);
assign d
module PC( //PC
input clk,
input reset,
input enable,
input [31:0] d,
output [31:0] q
);
reg [31:0] pc;
initial begin
pc
module ADD4( //自增4模塊
input [31:0] pc,
output [31:0] pc4
);
assign pc4
module IM( //指令存儲器模塊
input [31:0] ia,
input reset,
input clk,
output [31:0] ir
);
parameter [31:0] num_instr
module MFA3( //A3端口數據選擇器
input [4:0] ir_rt,
input [4:0] ir_rd,
input [1:0] a3sel,
output [4:0] a3
);
assign a3
module MFWD3( //WD3端口數據選擇器
input [31:0] rd,
input [31:0] ao,
input [31:0] extd,
input [31:0] pc4,
input [2:0] wd3sel,
output [31:0] wd3
);
assign wd3
module EXT( //擴展模塊
input [15:0] i16,
input [1:0] extop,
output [31:0] extd
);
assign extd
module CMP( //比較器
input [31:0] d1,
input [31:0] d2,
output res
);
assign res
module NPC( //下一條指令生成模塊
input [31:0] pc4,
input [25:0] i26,
input npcop,
output [31:0] nextpc
);
assign nextpc = (npcop == 0)? $signed(pc4) + $signed({{14{i26[15]}},i26[15:0],2'b0}): {pc4[31:28],i26,2'b0};
endmodule
module ALU( //ALU模塊
input [31:0] a,
input [31:0] b,
input [4:0] shamt,
input [3:0] aluop,
output [31:0] ao
);
assign ao = (aluop == 0)? $signed(a) + $signed(b):
(aluop == 1)? $signed(a) - $signed(b):
(aluop == 2)? a | b:
(aluop == 3)? ($signed(a) < $signed(b)):
(aluop == 4)? (b << a[4:0]):
(aluop == 5)? $signed($signed(b) >>> a[4:0]):
(aluop == 6)? (b >> a[4:0]):
(aluop == 7)? (b << shamt):
(aluop == 8)? $signed($signed(b) >>> shamt):
(aluop == 9)? (b >> shamt):
32'b0;
endmodule
module MFB( //B端口選擇器
input [31:0] extd,
input [31:0] rd2,
input bsel,
output [31:0] b
);
assign b = (bsel == 0)? extd:
rd2;
endmodule
module RF( //寄存器堆模塊
input [4:0] a1,
input [4:0] a2,
input [4:0] a3,
input [31:0] wd3,
output [31:0] rd1,
output [31:0] rd2,
input reset,
input clk,
input wr
);
reg [31:0] rf [31:1];
integer i;
initial begin
for(i = 1 ;i < 32; i = i + 1) begin
rf[i] = 32'b0;
end
end
always@(posedge clk) begin
if(reset) begin
for(i = 1;i < 32;i = i + 1) begin
rf[i] = 32'b0;
end
end
else if(wr && a3 != 5'b0) begin
rf[a3] <= wd3;
end
end
assign rd1 = (a1 == 5'd0)? 32'b0:
rf[a1];
assign rd2 = (a2 == 5'd0)? 32'b0:
rf[a2];
endmodule
module DM( //數據存儲器模塊
input [31:0] da,
input [31:0] wd,
input [1:0] wm,
input [2:0] rm,
input clk,
input reset,
output [31:0] rd
);
parameter [31:0] num_data = 4096; // 1024words
reg [7:0] dm [num_data-1:0];
integer i;
wire [7:0] temp3,temp2,temp1,temp0;
initial begin
for(i = 0; i < num_data; i = i + 1)
dm[i] = 8'b0;
end
always@(posedge clk) begin
if(reset) begin
for(i = 0; i < num_data; i = i + 1)
dm[i] = 8'b0;
end
else if(wm != 0) begin
case(wm)
1: begin //sw
dm[da[11:0]] <= wd[7:0];
dm[da[11:0] + 12'd1] <= wd[15:8];
dm[da[11:0] + 12'd2] <= wd[23:16];
dm[da[11:0] + 12'd3] <= wd[31:24];
end
2: begin //sh
dm[da[11:0]] <= wd[7:0];
dm[da[11:0] + 12'd1] <= wd[15:8];
end
3: begin //sb
dm[da[11:0]] <= wd[7:0];
end
endcase
end
end
assign temp3 = dm[da[11:0] + 12'd3];
assign temp2 = dm[da[11:0] + 12'd2];
assign temp1 = dm[da[11:0] + 12'd1];
assign temp0 = dm[da[11:0]];
assign rd = (rm == 1)? {temp3,temp2,temp1,temp0}: //lw
(rm == 2)? {16'b0,temp1,temp0}: //lhu
(rm == 3)? {{16{temp1[7]}},temp1,temp0}: //lh
(rm == 4)? {24'b0,temp0}: //lbu
(rm == 5)? {{24{temp0[7]}},temp0}: //lb
0;
endmodule
module MAINDECODER( //主譯碼器模塊
input [5:0] op,
input [5:0] funct,
input [4:0] ir_rd,
input res,
output reg [1:0] pcsel,
output reg [1:0] extop,
output reg npcop,
output reg [3:0] aluctrl,
output reg bsel,
output reg [1:0] wm,
output reg [2:0] rm,
output reg [1:0] a3sel,
output reg [2:0] wd3sel,
output reg wr
);
always@(*) begin
case(op)
6'b0: begin
if(funct == 6'b001000) begin //jr
pcsel = 2'd2;
wm = 2'd0;
rm = 3'd0;
wr = 1'd0;
end
else if(funct == 6'b001001) begin //jalr
pcsel = 2'd2;
wm = 2'd0;
rm = 3'd0;
a3sel = 2'd1;
wd3sel = 3'd3;
wr = 1'd1;
end
else if(funct == 6'b0 && ir_rd == 5'b0) begin //nop
pcsel = 2'd0;
wm = 2'd0;
rm = 3'd0;
wr = 1'd0;
end
else begin //cal_r,shamt
pcsel = 2'd0;
aluctrl = 4'd15;
bsel = 1'd1;
wm = 2'd0;
rm = 3'd0;
a3sel = 2'd1;
wd3sel = 3'd1;
wr = 1'd1;
end
end
6'b100011: begin //lw
pcsel = 2'd0;
extop = 2'd0;
aluctrl = 4'd0;
bsel = 1'd0;
wm = 2'd0;
rm = 3'd1;
a3sel = 2'd0;
wd3sel = 3'd0;
wr = 1'd1;
end
6'b100101: begin //lhu
pcsel = 2'd0;
extop = 2'd0;
aluctrl = 4'd0;
bsel = 1'd0;
wm = 2'd0;
rm = 3'd2;
a3sel = 2'd0;
wd3sel = 3'd0;
wr = 1'd1;
end
6'b100001: begin //lh
pcsel = 2'd0;
extop = 2'd0;
aluctrl = 4'd0;
bsel = 1'd0;
wm = 2'd0;
rm = 3'd3;
a3sel = 2'd0;
wd3sel = 3'd0;
wr = 1'd1;
end
6'b100100: begin //lbu
pcsel = 2'd0;
extop = 2'd0;
aluctrl = 4'd0;
bsel = 1'd0;
wm = 2'd0;
rm = 3'd4;
a3sel = 2'd0;
wd3sel = 3'd0;
wr = 1'd1;
end
6'b100000: begin //lb
pcsel = 2'd0;
extop = 2'd0;
aluctrl = 4'd0;
bsel = 1'd0;
wm = 2'd0;
rm = 3'd5;
a3sel = 2'd0;
wd3sel = 3'd0;
wr = 1'd1;
end
6'b101011: begin //sw
pcsel = 2'd0;
extop = 2'd0;
aluctrl = 4'd0;
bsel = 1'd0;
wm = 2'd1;
rm = 3'd0;
wr = 1'd0;
end
6'b101001: begin //sh
pcsel = 2'd0;
extop = 2'd0;
aluctrl = 4'd0;
bsel = 1'd0;
wm = 2'd2;
rm = 3'd0;
wr = 1'd0;
end
6'b101000: begin //sb
pcsel = 2'd0;
extop = 2'd0;
aluctrl = 4'd0;
bsel = 1'd0;
wm = 2'd3;
rm = 3'd0;
wr = 1'd0;
end
6'b001111: begin //lui
pcsel = 2'd0;
extop = 2'd1;
wm = 2'd0;
rm = 3'd0;
a3sel = 2'd0;
wd3sel = 3'd2;
wr = 1'd1;
end
6'b000100: begin //beq
pcsel = (res == 0)? 2'd0: 2'd1;
npcop = 1'd0;
wm = 2'd0;
rm = 3'd0;
wr = 1'd0;
end
6'b000010: begin //j
pcsel = 2'd1;
npcop = 1'd1;
wm = 2'd0;
rm = 3'd0;
wr = 1'd0;
end
6'b000011: begin //jal
pcsel = 2'd1;
npcop = 1'd1;
wm = 2'd0;
rm = 3'd0;
a3sel = 2'd2;
wd3sel = 3'd3;
wr = 1'd1;
end
6'b001101: begin //ori
pcsel = 2'd0;
extop = 2'd2;
aluctrl = 4'd2;
bsel = 1'd0;
wm = 2'd0;
rm = 3'd0;
a3sel = 2'd0;
wd3sel = 3'd1;
wr = 1'd1;
end
6'b001010: begin //slti
pcsel = 2'd0;
extop = 2'd0;
aluctrl = 4'd3;
bsel = 1'd0;
wm = 2'd0;
rm = 3'd0;
a3sel = 2'd0;
wd3sel = 3'd1;
wr = 1'd1;
end
6'b001001: begin //addiu
pcsel = 2'd0;
extop = 2'd0;
aluctrl = 4'd0;
bsel = 1'd0;
wm = 2'd0;
rm = 3'd0;
a3sel = 2'd0;
wd3sel = 3'd1;
wr = 1'd1;
end
endcase
end
endmodule
module ALUDECODER( //ALU譯碼器模塊
input [3:0] aluctrl,
input [5:0] funct,
output reg [3:0] aluop
);
initial aluop = 0;
always@(*) begin
if(aluctrl != 4'd15) begin
aluop = aluctrl;
end
else begin
case(funct)
6'b100001: aluop = 0;//addu
6'b100011: aluop = 1;//subu
6'b101010: aluop = 3;//slt
6'b000100: aluop = 4;//sllv
6'b000111: aluop = 5;//srav
6'b000110: aluop = 6;//srlv
6'b000000: aluop = 7;//sll
6'b000011: aluop = 8;//sra
6'b000010: aluop = 9;//srl
endcase
end
end
endmodule
module DECODER( //譯碼器模塊
input [5:0] op,
input [5:0] funct,
input [4:0] ir_rd,
input res,
output [1:0] pcsel,
output [1:0] extop,
output npcop,
output [3:0] aluop,
output bsel,
output [1:0] wm,
output [2:0] rm,
output [1:0] a3sel,
output [2:0] wd3sel,
output wr
);
wire [3:0] aluctrl;
MAINDECODER maindecoder (
.op(op),
.funct(funct),
.res(res),
.ir_rd(ir_rd),
.pcsel(pcsel),
.extop(extop),
.npcop(npcop),
.aluctrl(aluctrl),
.bsel(bsel),
.wm(wm),
.rm(rm),
.a3sel(a3sel),
.wd3sel(wd3sel),
.wr(wr)
);
ALUDECODER aludecoder (
.aluctrl(aluctrl),
.funct(funct),
.aluop(aluop)
);
endmodule
`define rs 25:21
`define rt 20:16
`define rd 15:11
`define op 31:26
`define i16 15:0
`define sh 10:6
`define i26 25:0
`define funct 5:0
module mips( //CPU模塊
input clk,
input reset
);
parameter enable = 1'd1;
wire [31:0] d,q,pc4,ir,wd3,rd1,rd2,extd,nextpc,ao,b,rd;
wire [4:0] a3;
wire res;
wire [1:0] pcsel;
wire [1:0] extop;
wire npcop;
wire [3:0] aluop;
wire bsel;
wire [1:0] wm;
wire [2:0] rm;
wire [1:0] a3sel;
wire [2:0] wd3sel;
wire wr;
MFPC mfpc (
.pc4(pc4),
.nextpc(nextpc),
.rd1(rd1),
.pcsel(pcsel),
.d(d)
);
PC pc (
.clk(clk),
.reset(reset),
.enable(enable),
.d(d),
.q(q)
);
ADD4 add4 (
.pc(q),
.pc4(pc4)
);
IM im (
.ia(q),
.reset(reset),
.clk(clk),
.ir(ir)
);
MFA3 mfa3 (
.ir_rt(ir[`rt]),
.ir_rd(ir[`rd]),
.a3sel(a3sel),
.a3(a3)
);
MFWD3 mfwd3 (
.rd(rd),
.ao(ao),
.extd(extd),
.pc4(pc4),
.wd3sel(wd3sel),
.wd3(wd3)
);
EXT ext (
.i16(ir[`i16]),
.extop(extop),
.extd(extd)
);
CMP cmp (
.d1(rd1),
.d2(rd2),
.res(res)
);
NPC npc (
.pc4(pc4),
.i26(ir[`i26]),
.npcop(npcop),
.nextpc(nextpc)
);
ALU alu (
.a(rd1),
.b(b),
.shamt(ir[`sh]),
.aluop(aluop),
.ao(ao)
);
MFB mfb (
.extd(extd),
.rd2(rd2),
.bsel(bsel),
.b(b)
);
RF rf (
.a1(ir[`rs]),
.a2(ir[`rt]),
.a3(a3),
.wd3(wd3),
.rd1(rd1),
.rd2(rd2),
.reset(reset),
.clk(clk),
.wr(wr)
);
DM dm (
.da(ao),
.wd(rd2),
.wm(wm),
.rm(rm),
.clk(clk),
.reset(reset),
.rd(rd)
);
DECODER decoder (
.op(ir[`op]),
.funct(ir[`funct]),
.ir_rd(ir[`rd]),
.res(res),
.pcsel(pcsel),
.extop(extop),
.npcop(npcop),
.aluop(aluop),
.bsel(bsel),
.wm(wm),
.rm(rm),
.a3sel(a3sel),
.wd3sel(wd3sel),
.wr(wr)
);
always@(posedge clk) begin
if(reset == 0) begin
if(wr == 1'd1)
$display("@%h: $%d <= %h", q, a3, wd3);
if(wm != 2'd0)
$display("@%h: *%h <= %h", q, ao, rd2);
end
end
endmodule
注:此代碼僅供參考,僅支持所聲明指令。
四、筆者感受
