是否可能有一个Chisel“is”条件,其行为类似于Chisel“switch”语句中的Verilog“默认”情况?这是为了防止锁存器被推断为来自FSM的组合输出。
Verilog示例:
module detector (clk, rstn, in1, in2, out1, out2);
input clk, rstn, in1, in2;
output reg out1, out2;
localparam [1:0] IDLE = 2'b01;
localparam [1:0] GOT_IN1 = 2'b10;
reg [1:0] state, nxtState;
always @ (posedge clk or negedge rstn) begin
if (!rstn) begin
state <= IDLE;
end else begin
state <= nxtState;
end
end
always @ (*) begin
case (state)
IDLE: begin
if (in1) begin
out1 = 1'b1;
out2 = 1'b0;
nxtState = GOT_IN1;
end else begin
out1 = 1'b0;
out2 = 1'b0;
nxtState = IDLE;
end
end
GOT_IN1: begin
if (in2) begin
out1 = 1'b0;
out2 = 1'b1;
nxtState = IDLE;
end else begin
out1 = 1'b0;
out2 = 1'b0;
nxtState = GOT_IN1;
end
end
default: begin
out1 = 1'b0;
out2 = 1'b0;
nxtState = IDLE;
end
endcase
end
endmodule
Chisel2允许这种行为,因为默认值可以在“is”条件之外的switch语句中分配给out1和out2。
switch (state) {
io.out1 := UInt(0)
io.out2 := UInt(0)
is (IDLE) {
when (io.in1 === UInt(1)) {
io.out1 := UInt(1)
io.out2 := UInt(0)
state := GOT_IN1
} .otherwise {
io.out1 := UInt(0)
io.out2 := UInt(0)
state := IDLE
}
}
is (GOT_IN1) {
when (io.in2 === UInt(1)) {
io.out1 := UInt(0)
io.out2 := UInt(1)
state := IDLE
} .otherwise {
io.out1 := UInt(0)
io.out2 := UInt(0)
state := GOT_IN1
}
}
}
Chisel3不支持像Chisel2这样的默认赋值语法。构建错误被标记:
◾exception during macro expansion: java.lang.Exception: Cannot include blocks that do not begin with is() in switch. at chisel3.util.switch
Chisel3似乎没有任何方法可以防止在out1和out2输出上推断出锁存器。我知道out1和out2赋值可以移到switch语句之外,并使用条件赋值进行处理。但是,从代码可见性的角度来看,处理具有数十个状态和组合输出的大型FSM的case语句中的赋值更为清晰。
答案 0 :(得分:3)
您可以故意添加括号以识别应该一起阅读的一些代码。 类似的东西:
{ // state machine block
io.out1 := UInt(0)
io.out2 := UInt(0)
when (state === IDLE) {
when (io.in1 === UInt(1)) {
io.out1 := UInt(1)
io.out2 := UInt(0)
state := GOT_IN1
} .otherwise {
io.out1 := UInt(0)
io.out2 := UInt(0)
state := IDLE
}
}
when (state === GOT_IN1) {
when (io.in2 === UInt(1)) {
io.out1 := UInt(0)
io.out2 := UInt(1)
state := IDLE
} .otherwise {
io.out1 := UInt(0)
io.out2 := UInt(0)
state := GOT_IN1
}
}
}
我相信Chisel永远不会生成锁存器。如果未启用后续分配更改,则第一个分配将生效。