Could we have any syntax where case statement is scalable? Let me explain with an example: Mux
If there were only 2 select lines
always @(A[1:0]) begin
case (A[1:0])
2'b00 : select = 4'b1110;
2'b01 : select = 4'b1101;
2'b10 : select = 4'b1011;
2'b11 : select = 4'b0111;
endcase
end
For 3 select lines
always @(A[2:0]) begin
case (A[2:0])
3'b000 : select = 8'b1111_1110;
3'b001 : select = 8'b1111_1101;
3'b010 : select = 8'b1111_1011;
3'b011 : select = 8'b1111_0111;
3'b100 : select = 8'b1110_1111;
3'b101 : select = 8'b1101_1111;
3'b110 : select = 8'b1011_1111;
3'b111 : select = 8'b0111_1111;
endcase
end
My questions:
Is there a generic way of writing code that could address a mux with any number of select lines? 2,3,4...
Is there any other way of achieving this using syntax other than case statement?
Any feedback is welcome. regards
If it is the walking 0's pattern that your after how about:
localparam SHIFT_W = 3;
localparam OUT_W = 2**SHIFT_W;
reg [SHIFT_W-1:0] shift;
reg [OUT_W-1:0] out;
always_comb begin
out = ~(OUT_W'(1'b1 << shift));
end
As suggested by nguthrie. Shift to create a walking 1, then invert to create a walking 0.
My original suggestion (which was a bit verbose) using SystemVerilog to directly create a walking 0:
localparam SHIFT_W = 3;
localparam OUT_W = 2**SHIFT_W;
reg [SHIFT_W-1:0] shift;
reg [OUT_W-1:0] out;
always_comb begin
out = OUT_W'( $signed{ 1'b1, 1'b0, {OUT_W{1'b1}} }) >>> (OUT_W-shift) );
end
WIDTH`()
Casts to the correct width to stop LHS RHS width mismatch warnings.
$signed()
Casts to a signed number to allow >>>
to shift by sign extending. This could also be written as:
out = OUT_W'( { {OUT_W{1'b1}}, 1'b0, {OUT_W{1'b1}} } >> (OUT_W-shift) );
For Verilog-2001, you will just get LHS RHS width mismatch warnings:
out = { {OUT_W{1'b1}}, 1'b0, {OUT_W{1'b1}} } >> (OUT_W-shift);
Which has removed the need to sign extend during shift.