我正在为 MIPS 编写 ALU。
我曾经把它写成顺序逻辑(或总是块?我不知道为什么但c
必须是reg
所以我猜它是顺序逻辑?)
好像是组合逻辑
always @* begin
case (op)
4'b0000: c = mux_a + mux_b;
4'b0001: c = mux_a - mux_b;
4'b0010: c = mux_b << mux_a[4:0];
4'b0011: c = mux_b >> mux_a[4:0];
4'b0100: c = $signed(mux_b) >>> mux_a[4:0];
4'b0101: c = mux_a & mux_b;
4'b0110: c = mux_a | mux_b;
4'b0111: c = mux_a ^ mux_b;
4'b1000: c = ~(mux_a | mux_b);
4'b1001: c = (mux_a < mux_b) ? 32'b1 : 32'b0; // sltu
4'b1010: c = ($signed(mux_a) < $signed(mux_b)) ? 32'b1 : 32'b0; // slt
4'b1011: c = mux_a + mux_b - 4;
default: c = 0;
endcase
end
而且效果很好,4'b0100: c = $signed(mux_b) >>> mux_a[4:0]
可以得到正确的输出。但是由于某些原因,我决定使用组合逻辑条件表达式。
assign c = (op == 4'b0000) ? (mux_a + mux_b) :
(op == 4'b0001) ? (mux_a - mux_b) :
(op == 4'b0010) ? (mux_b << mux_a[4:0]) :
(op == 4'b0011) ? (mux_b >> mux_a[4:0]) :
(op == 4'b0100) ? ($signed(mux_b) >>> mux_a[4:0]) :
(op == 4'b0101) ? (mux_a & mux_b) :
(op == 4'b0110) ? (mux_a | mux_b) :
(op == 4'b0111) ? (mux_a ^ mux_b) :
(op == 4'b1000) ? (~(mux_a | mux_b)) :
(op == 4'b1001) ? ((mux_a < mux_b) ? 32'b1 : 32'b0) :
(op == 4'b1010) ? (($signed(mux_a) < $signed(mux_b)) ? 32'b1 : 32'b0) :
(op == 4'b1011) ? (mux_a + mux_b - 4) :
0;
这几乎是一样的,除了c
是一个wire
。
我运行这段代码,它告诉我,4294967280 (FFFFFFF0) >>> 8 = 33554431 (1FFFFFF) 这太荒谬了。
PC= 388, Fetched 00000000000100011001101000000011.
Decoder done. alu=4294967280.
ALUOP=0100 ALUMASK=10 Calc Result= 33554431
rs= 0 rt=4294967280
aluflag = 0000
Written(0000) 01ffffff to RegAddr:19
但如果我(op == 4'b0100) ? ({ {31{mux_b[32]}}, mux_b} >> mux_a[4:0]) :
改用,我可以得到正确的结果。
谁能告诉我原因?以下是这些变量的定义方式(使用 33 位作为溢出标志)
input [31:0] a;
input [31:0] b;
input [31:0] imm1;
input [31:0] imm0;
input [3:0] op;
input [1:0] mask;
output [31:0] result;
output [3:0] flags;
wire [31:0] _mux_a;
wire [31:0] _mux_b;
wire [32:0] mux_a;
wire [32:0] mux_b;
wire [32:0] c;
assign _mux_a = mask[1] ? imm1 : a;
assign _mux_b = mask[0] ? imm0 : b;
assign mux_a = {_mux_a[31], _mux_a};
assign mux_b = {_mux_b[31], _mux_b};
assign result = c[31:0];
//zf of uf
assign flags = {c[31], result == 0, c[32:31] == 2'b01, c[32:31] == 2'b10};