How can i make my verilog shifter more general?

不想你离开。 提交于 2020-01-04 02:19:06

问题


Here i have a shifter but as of rite now it only works for up to 3 bits. I've been looking and i can't find out how to make it work for up to 8 bits.

module shifter(a,b,out);
input [7:0] a, b;
output [7:0] out;
wire [7:0] out1, out2, out3;

mux_8b_2to1 first(a[7:0], {a[3:0],a[7:4]}, b[2], out1);
mux_8b_2to1 second(out1[7:0], {out1[5:0],out1[7:6]}, b[1], out2);
mux_8b_2to1 third(out2[7:0], {out2[6:0],out2[7]}, b[0], out);
endmodule

回答1:


What you have is a Barrel Shifter. Two ways to make it more generic are make it a functional model (still synthesis-able) or structural model with a generate block. Both approaches follow IEEE Std 1364-2001 (aka Verilog-2001).

The functional generic approach for a barrel shifter only needs a down-shifter. The general function is out = {in,in} >> (WIDTH-shift) where leftover bits can be ignored. To protect for double-roll (i.e. shift > WIDTH ), use the mod operator on the shift (WIDTH-(shift%WIDTH)).

module barrel_shifter_functional #( parameter CTRL=3, parameter WIDTH=CTRL**2 )
 ( input wire [WIDTH-1:0] in,
   input wire [ CTRL-1:0] shift,
  output wire [WIDTH-1:0] out );
assign out = {2{in}} >> (WIDTH-(shift%WIDTH));
endmodule

The structural generic approach for a barrel shifter needs a generate block. The for loop in the generate block will unravel at compile time, not run time like a for loop like in an always block. To keep it generic also have have the 2-to-1 mux have a parametrized width. FYI, you can use the generate block with functional code too, for example comment out the mux_2to1 instantiation and uncomment the assign statement below it. Learn more about the generate block by reading IEEE Std 1800-2012 § 27. Generate constructs.

module barrel_shifter_structeral #( parameter CTRL=3, parameter WIDTH=CTRL**2 )
 ( input wire [WIDTH-1:0] in,
   input wire [ CTRL-1:0] shift,
  output wire [WIDTH-1:0] out );
wire [WIDTH-1:0] tmp [CTRL:0];
assign tmp[CTRL] = in;
assign out = tmp[0];
genvar i;
generate
  for (i = 0; i < CTRL; i = i + 1) begin : mux
    mux_2to1 #(.WIDTH(WIDTH)) g(
      .in0(tmp[i+1]),
      .in1({tmp[i+1][WIDTH-(2**i)-1:0],tmp[i+1][WIDTH-1:WIDTH-(2**i)]}),
      .sel(shift[i]),
      .out(tmp[i]) );
    // assign tmp[i] = shift[i] ? {tmp[i+1][WIDTH-(2**i)-1:0],tmp[i+1][WIDTH-1:WIDTH-(2**i)]} : tmp[i+1];
  end : mux
endgenerate
endmodule

module mux_2to1 #( parameter WIDTH=8 )
 ( input wire [WIDTH-1:0] in0, in1,
   input wire             sel,
  output wire [WIDTH-1:0] out );
assign out = sel ? in1 : in0;
endmodule

Both examples are functionally equivalent and synthesize provided CTRL is less than or equal to the ceiling of log2(WIDTH). Synthesis will likely give different results. The generate method will exclusively use 2-to-1 muxes while the pure functional method will depend on the quality of the optimizer.

Working example @ http://www.edaplayground.com/s/6/500




回答2:


I've used the >> and << operators to generate a synthetizable design using ISEWebPack, as this:

module shifter(
    input wire [7:0] a,
    input wire [7:0] b,
    input wire leftright,  // 0=shift right, 1=shift left
    output reg [7:0] out
    );

    always @* begin
      if (leftright==0)
         out = a>>b;
      else
         out = a<<b;
    end
endmodule

This way, the symthesis tool will know that you want to implement a shifter and can use its own macros to best synthetize it:

Synthesizing Unit <shifter>.
    Related source file is "shifter.v".
    Found 8-bit shifter logical right for signal <out$shift0002> created at line 30.
    Found 8-bit shifter logical left for signal <out$shift0003> created at line 32.


来源:https://stackoverflow.com/questions/20357390/how-can-i-make-my-verilog-shifter-more-general

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!