0
votes

I want to design a variable shift register to shift to right as following:

module sr(N,int,out);

  input [2:0] N;
  input [7:0] in;
  output [7:0] out;

  assign out={N'b0,input[7,N]}

endmodule

but, unfortunately verilog doesn't allow this kind of writing. N should be constant. any idea on how to get shift iterations from input?

2
I think it's not allowed because it causes an exponential explosion in required amount of logic as the parameters get larger. Do you need this for the general case, or just for that particular small example? For a 3 bit N it would be easy to just write a switch statement. - Tim
@Tim - just because the logic is big, doesn't mean it shouldn't be allowed though :) - Martin Thompson
If I understand correctly, you want a barrel shifter: stackoverflow.com/questions/7543592/verilog-barrel-shifter - Martin Thompson
Your original code has a syntax error (input[7,0]) as well as a bunch of mismatched names. See my answer for corrections. - dwikle
yea this is a dummy code, just to show the concept. - Alex

2 Answers

5
votes

Verilog has a right shift operator so you can simply write:

assign out = in >> N;

The extra bits are automatically filled with zeros.

3
votes

If the sizes of in and out are really fixed at 8 bits, here is one simple way to do it:

module sr(N, in, out);

  input  [2:0] N;
  input  [7:0] in;
  output [7:0] out;

  assign out = (N == 7) ? {7'b0, in[7:7]} : 
               (N == 6) ? {6'b0, in[7:6]} : 
               (N == 5) ? {5'b0, in[7:5]} : 
               (N == 4) ? {4'b0, in[7:4]} : 
               (N == 3) ? {3'b0, in[7:3]} : 
               (N == 2) ? {2'b0, in[7:2]} : 
               (N == 1) ? {1'b0, in[7:1]} : 
                                 in[7:0];

endmodule

This could also be coded using a case statement inside an always block, like this:

  reg [7:0] out_reg;
  assign out = out_reg;

  always @(N or in) begin
    case (N)
      7 : out_reg <= {7'b0, in[7:7]};
      6 : out_reg <= {6'b0, in[7:6]};
      5 : out_reg <= {5'b0, in[7:5]};
      4 : out_reg <= {4'b0, in[7:4]};
      3 : out_reg <= {3'b0, in[7:3]};
      2 : out_reg <= {2'b0, in[7:2]};
      1 : out_reg <= {1'b0, in[7:1]};
      0 : out_reg <=        in[7:0];
    endcase
  end

If you don't want to write out all the values you can use a for loop. I'm not an expert on how the synthesis tools handle this but this (or something similar) should synthesize okay.

  always @(N or in) begin
    for (i = 0; i < 8; i = i + 1) begin
      if (i+N < 8) begin
        out_reg[i] <= in[i+N];
      end else begin
        out_reg[i] <= 1'b0;
      end
    end
  end

One advantage of coding it using a loop is it is less prone to cut-n-paste typos.

More importantly, if you want to make the module support generic bit-widths of the inputs and outputs, you can do so using a parameter on the module and a similar loop for the assignments.