(System)从任意位置切出的Verilog位



我想通过从任意位置切割一位,使输出总线比输入短1位,如下所示:

module jdoodle;
    integer i;
    reg [8:0] in;
    reg [7:0] out;
    reg [3:0] idx;
    
    always @* 
    begin
        case(idx)
            0: out = in[8:1];
            1: out = {in[8:2], in[0]};
            2: out = {in[8:3], in[1:0]};
            3: out = {in[8:4], in[2:0]};
            4: out = {in[8:5], in[3:0]};
            5: out = {in[8:6], in[4:0]};
            6: out = {in[8:7], in[5:0]};
            7: out = {in[8], in[6:0]};
            default: out = in[7:0];
        endcase
    end
    initial begin
        in = 9'b010101010;
        for (i = 0; i < 9; i++)
        begin
            idx = i; #10;
            $display ("%x - %08b", idx, out);
        end
        $finish;
    end
endmodule

我找到了一种写在一行中的方法:

module jdoodle;
    integer i;
    reg [8:0] in;
    reg [3:0] idx;
    wire [7:0] out;
    assign out = ((in >> 1) & (16'h00ff << idx)) | (in & (16'hff00 >> (16-idx)));
    initial begin
        in = 9'b010101010;
        for (i = 0; i < 9; i++)
        begin
            idx = i; #10;
            $display ("%x - %08b", idx, out);
        end
        $finish;
    end
endmodule

但它的可读性不如第一个,但第一个对更大的公交车来说相当糟糕。有更优雅的方法吗?还有标准的verilog库,比如std for c++,包含像任意旋转这样的通用模块吗?

感谢

编辑:这是预期的输出:

0 - 01010101
1 - 01010100
2 - 01010110
3 - 01010010
4 - 01011010
5 - 01001010
6 - 01101010
7 - 00101010
8 - 10101010

您可以使用循环处理每个位:

module jdoodle #(parameter INW = 'd9)
 (
  input [INW-1:0] in,
  output[INW-2:0] out,
  input [$clog2(INW)-1:0] idx
 );    
  always_comb begin
      for(int i = 0; i<INW; i++) begin
          if      (i < idx) out[i]   = in[i];
          else if (i > idx) out[i-1] = in[i];
          // do nothing if i == idx
      end
  end
endmodule

最新更新