Verilog Barrel Shifter

前端 未结 2 621
清酒与你
清酒与你 2020-12-10 16:54

I want to create a 64-bit barrel shifter in verilog (rotate right for now). I want to know if there is a way to do it without writing a 65 part case statement? Is there a wa

相关标签:
2条回答
  • 2020-12-10 17:32

    I've simplified some of the rules for clarity, but here are the details.

    In the statement

    Y = {S[i - 1:0], S[63:i]};
    

    you have a concatenation of two signals, each with a constant part select. A constant part select is of the form

    identifier [ constant_expression : constant_expression ]

    but your code uses a variable for the first expression. As you saw this isn't allowed, but you are correct in that there are ways to avoid typing a large case statement. What you can use instead is an indexed part select. These are of the form

    identifier [ expression +: constant_expression ]

    identifier [ expression -: constant_expression ]

    These constructs enforce that the width of the resulting signal is constant, regardless of the variable on the left side.

    wire [HIGH_BIT:LOW_BIT] signalAdd,signaSub;
    signalAdd[some_expression +: some_range];
    signalSub[some_expression -: some_range];
    //Resolves to
    signalAdd[some_expression + (some_range - 1) : some_expression];
    signalSub[some_expression                    : some_expression - (some_range - 1)];
    
    //The location of the high value depends on how the signal was declared:
    wire [15: 0] a_vect;
    wire [0 :15] b_vect;
    a_vect[0 +: 8] // a_vect[7 : 0]
    b_vect[0 +: 8] // b_vect[0 : 7]
    

    Rather than trying to build one signal out of two part selects, you can simply extend the input signal to 128 bits, and use a variable part select from that.

    wire [63:0] data_in,data_out;
    wire [127:0] data_in_double;
    wire [5:0] select;
    
    //Concatenate the input signal
    assign data_in_double = {data_in,data_in};
    
    //The same as signal[select + 63 : select]
    assign data_out = data_in_double[select+63-:64];
    

    Another approach you could use is generate loops. This is a more general approach to replicating code based on a variable. It is much less efficient since it creates 4096 signals.

    wire [63:0] data_in,data_out;
    wire [127:0] data_in_double;
    wire [5:0] select;
    wire [63:0] array [0:63];
    genver i;
    
    //Concatenate the input signal
    assign data_in_double = {data_in,data_in};
    for(i=0;i<64;i=i+1)
      begin : generate_loop
      //Allowed since i is constant when the loop is unrolled
      assign array[i] = data_in_double[63+i:i];
      /*
      Unrolls to 
      assign array[0] = data_in_double[63:0];
      assign array[1] = data_in_double[64:1];
      assign array[2] = data_in_double[65:2];
      ...
      assign array[63] = data_in_double[127:64];
      */
      end
    
    //Select the shifted value
    assign data_out = array[select];
    
    0 讨论(0)
  • 2020-12-10 17:39

    The best way I found to do this is finding a pattern. When you want to rotate left an 8 bit signal 1 position (8'b00001111 << 1) the result is = 8'b00011110) also when you want to rotate left 9 positions (8'b00001111 << 9) the result is the same = 8'b00011110, and also rotating 17 positions, this reduce your possibilities to next table:

    so if you look, the tree first bits of all numbers on table equivalent to rotate 1 position (1,9,17,25...249) are equal to 001 (1)

    the tree first bits of all numbers on table equivalent to rotate 6 positions (6,14,22,30...254) are equal to 110 (6)

    so you can apply a mask (8'b00000111) to determine the correct shifting number by making zero all other bits:

    reg_out_temp <= reg_in_1 << (reg_in_2 & 8'h07);

    reg_out_temp shall be the double of reg_in_1, in this case reg_out_temp shall be 16 bit and reg_in_1 8 bit, so you can get the carried bits to the other byte when you shift the data so you can combine them using an OR expression:

    reg_out <= reg_out_temp[15:8] | reg_out_temp[7:0];

    so by two clock cycles you have the result. For a 16 bit rotation, your mask shall be 8'b00011111 (8'h1F) because your shifts goes from 0 to 16, and your temporary register shall be of 32 bits.

    0 讨论(0)
提交回复
热议问题