Shu*_*ang 1 verilog mips system-verilog
我理解在systemverilog中使用case语法时,我们需要完全描述所有组合或添加默认值以避免锁存.
这是我的示例代码,没有生成锁存器:
module test(
input logic[2:0] op,
output logic a,b,c
);
always_comb
begin
case(op)
0: {a,b,c} = {1'b1,1'b1,1'b0};
1: {a,b,c} = {1'b1,1'b0,1'b0};
2: {a,b,c} = {1'b0,1'b1,1'b0};
default: {a,b,c} = {1'b0,1'b0,1'b0};
endcase
end
endmodule
Run Code Online (Sandbox Code Playgroud)
正如我在开头所说,如果添加默认值,则不会生成锁存器.请查看第二个代码,这是一个ALU设计:
module ALU(
output logic[31:0] Result,
output logic Zero, Overflow, Negative, Carryout,
input logic [5:0]ALUOp_i,
input logic [31:0] ALU_A_i, ALU_B_i,
input logic [4:0] Shamt
);
logic [31:0] adder_b;
always_comb
begin
casez(ALUOp_i)
/*Add_trap*/ 0,1: {Carryout,Result} = {ALU_A_i[31],ALU_A_i} + {ALU_B_i[31],ALU_B_i};
/*Add_notrap*/
/*Subtrap*/ 2,3:
/*Sub_notrap*/ begin
adder_b = ALU_B_i ^ {32{1'b1}};
{Carryout,Result} = {ALU_A_i[31],ALU_A_i} + {adder_b[31],adder_b} + 1;
end
/*SLL*/ 8: Result = ALU_B_i << Shamt;
/*SLLV*/ 9: Result = ALU_B_i << ALU_A_i;
/*SRA*/ 10: Result = ALU_B_i >>> Shamt;
/*SRAV*/ 11: Result = ALU_B_i >>> ALU_A_i;
/*SRL*/ 12: Result = ALU_B_i >> Shamt;
/*SRLV*/ 13: Result = ALU_B_i >> ALU_A_i;
/*AND*/ 14: Result = ALU_A_i && ALU_B_i;
/*OR*/ 15: Result = ALU_A_i || ALU_B_i;
/*XOR*/ 16: Result = ALU_A_i ^^ ALU_B_i;
default:
begin
Result = 0;
Carryout = 0;
adder_b = 0;
end
endcase
end
endmodule
Run Code Online (Sandbox Code Playgroud)
上面的代码将生成锁存器,这是Quartus II给出的结果:
警告(10240):Verilog HDL总是在ALU.sv(16)构造警告:推断变量"Carryout"的锁存器,它通过always结构在一个或多个路径中保存其先前的值
警告(10240):Verilog HDL总是在ALU.sv(16)构造警告:推断变量"adder_b"的锁存器,它通过always结构在一个或多个路径中保存其先前的值
错误(10166):ALU.sv(16)处的SystemVerilog RTL编码错误:always_comb构造不推断纯粹的组合逻辑.
我在案例的最后添加了一个默认值,有人可以解释一下发生了什么吗?非常感谢.
这里干净简单的解决方案是Carryout在always_comb块的开头分配一个默认值.最后一次分配将获胜,因此任何未分配值的分支都Carryout将获得默认值.
下一个如何获胜的简单示例如下所示:
always_comb begin
Carryout = 1'b0;
if(some_condition) begin
Carryout = 1'b1;
end
end
Run Code Online (Sandbox Code Playgroud)
在上面的代码Carryout被赋值为0,然后if some_condition为true,它被重新赋值为1.如果some_condition为false,则它只保持"默认"值0.这一切都发生在同一时间步,所以没有瞬态输出上的故障.