Is it possible to have a Chisel "is" condition which behaves similar to a Verilog "default" case in a Chisel "switch" statement? This is required to prevent latches being inferred for combinatorial outputs from an FSM.
Verilog Example:
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 allowed this type of behavior as a default value could be assigned to out1 and out2 in the switch statement outside of an "is" condition.
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 doesn't support this default assignment syntax like Chisel2. A build error gets flagged:
◾exception during macro expansion: java.lang.Exception: Cannot include blocks that do not begin with is() in switch. at chisel3.util.switch
Chisel3 doesn't appear to have any method to prevent a latch from being inferred on the out1 and out2 outputs. I understand that out1 and out2 assignments can be moved outside of the switch statement and handled using a conditional assignment. However, from a code visibility standpoint it's clearer to handle the assignments within the case statement for large FSMs with dozens of states and combinatorial outputs.
You can add bracket deliberately to identify some code should be read together. Something like:
{ // 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
}
}
}
I believe Chisel will never generate latches. The first assignment takes effect if no later assignment change is enabled.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With