Search code examples
indexingverilogvariable-assignmentassign

Index register with different widths


Is there a way to index a multibit register with the same offset but variable width? I want to do this:

module foo (input [1:0] data_bits);
always @ (posedge clk) begin
case (data_bits)
    2'b11:
        assign wire_data_out = {3(1'b0), data_received[7:3]};
    2'b10:
        assign wire_data_out = {2(1'b0), data_received[7:2]};
    2'b01:
        assign wire_data_out = {(1'b0), data_received[7:1]};
    2'b00:
        assign wire_data_out = data_received;
endcase
end

Searching for an answer I found Indexed Part Select operator "+: or -:", but it requires fixed width, which doesn't fit my needs. Is there a simpler way to write the code above?


Solution

  • always @ (posedge clk)
       wire_data_out <= data_received>>data_bits;
    

    By the way:

    1. you can't use assigns inside an always block.
    2. In a clocked section you should use non-blocking assignments.

    It is a single line as you requested. But I would not write my code that way. It requires that the reader is aware that Verilog will add zero bits to the top and lose the bottom bits. I would use the code as you have written (but then without the syntax errors :-):

    always @ (posedge clk) begin
       case (data_bits)
       2'b00: wire_data_out <=       data_received;
       2'b01: wire_data_out <= {1'b0,data_received[7:1]};
       2'b10: wire_data_out <= {2'b0,data_received[7:2]};
       2'b11: wire_data_out <= {3'b0,data_received[7:3]};
       endcase
    

    The end result will be exactly the same logic but the readability is better.