lowspacetop
lowspacetop

Reputation: 79

Bidirectional shifting using multiplexers

Edit:Only by the screenshots(http://prntscr.com/lv3uqw http://prntscr.com/lv3yhf) and my code below you can still understand my goal here just incase you dont want to read the text.

I am trying to write a verilog code for a universal shift register. My original register was working properly(the one without the LR_bar signal). But on this one i have no idea how i can make this conection(mux with ff) happen http://prntscr.com/lv3uqw and http://prntscr.com/lv3yhf.I had a suggestion that the for loop should start from -1 but i still cant find a solution. I would also like to avoid the h signal if possible(maybe we also use the w there). So basicly when LR_bar=1 i want the shift register to shift left and when =0 to shift right.

Tip for the screenshot: ser in l_sh stands for serial input for left shifting

(Also found that on a Mano Morris 3rd edition(6th is more detailed) book (Computer Design Fundamentals) which is, to a point , a little close to what i want. But i want 2to1 multiplexers . But the 2 first screenshots is what i want to achieve. http://prntscr.com/lvb5bt http://prntscr.com/lvb65f )

I think i describe it well...can someone solve this?

MY NEW CODE(below) AND TEST AFTER SOME VALUES......http://prntscr.com/lvhk63

I TRIED TO MIMIC THAT(http://prntscr.com/lvgx31 http://prntscr.com/lvgxgw http://prntscr.com/lvgxkw) BUT ONLY FOR THE SERIAL INPUT PART(MSB,LSB). PLEASE TELL ME WHERE IM WRONG. THANKS

the output should be the state of the register

-----------------------------------------------------------
module lr_shreg_n(in, out, clk, rst, LR_bar);
parameter n=4;

input in, rst, clk, LR_bar;
output [n-1:0] out;
wire [n+1:0] w;
wire [n-1:0] mux_out;
genvar i;

assign w[0]=in;
assign w[n+1]=in;

generate
  for(i=0;i<n;i=i+1)
     begin             
    mux2to1 MUX(.in({w[i],w[i+2]}),.sel(LR_bar),.out(mux_out[i]));
    dff ff1(.d(mux_out[i]), .q(w[i+1]), .clk(clk), 
        .rst(rst)); 
     end
endgenerate

assign out=w[n:1];

endmodule
------------------------------------------------------------ 

JUST AN ATTEMPT NOTHING TO LOOK 
module lr_shreg_n(in, out, clk, rst, LR_bar);
parameter n=4;

input in, rst, clk, LR_bar;
output [n-1:0] out;
wire [n+1:0] w;
wire mux_out;
genvar i;

assign w[0]=in;
assign w[n+1]=in;

generate
  for(i=-1;i<n-1;i=i+1)
     begin             
    mux2to1 MUX(.in({w[i+1],w[3+i]}),.sel(LR_bar),.out(mux_out));
    dff ff1(.d(mux_out), .q(out[i+1]), .clk(clk), 
        .rst(rst)); 
     end
endgenerate


------------------------------------------------------------  
module dff (d, q, clk, rst); 

input d, clk, rst;  
output reg q;      

always @ (posedge clk) begin : dff_block   
    if (rst==1'b1)     
      q = 1'b0;     
    else       
      q = d;   
  end 

endmodule 

module mux2to1(in, sel, out) ;

input [1:0] in;
input sel;
output reg out;

always @(*) 
 case(sel)
  1'b0: out=in[0];
  1'b1: out=in[1];
 endcase

endmodule

module shreg_n(in, out, clk, rst);
parameter n=4;

input in, rst, clk;
output [n-1:0] out;
wire [n:0] w;
genvar i;

assign w[0]=in;

generate
  for(i=0;i<n;i=i+1)
    dff ff1(.d(w[i]), .q(w[i+1]), .clk(clk), 
        .rst(rst));
endgenerate

assign out=w[n:1];
//assign out=w[n];
endmodule

Upvotes: 1

Views: 1321

Answers (1)

Serge
Serge

Reputation: 12354

Blocking assignments might work in your specific case. As a matter of clean coding style and preventing any issues in the future, always use <= for all output assignments in flops (and latches).

Now, let's see what you want to do:

 w = out; // to keep the immediate values and avoid ordering issues

 for left shift:  w[3] -> x, w[2] -> out[3], w[1] -> out[2], w[0] -> out[1] , in -> out[0]
 for right shift: w[0] -> x, w[1] -> out[0], w[2] -> out[1], w[3] -> out[2], in -> out[3]

so, with a mux, say for out[2]i == 2, you would need a mux which does this:

 - w[1] -
         -> out[2]
 - w[3] -

 mux2to1 (.in({out[i+1], out[i-1]}),  .sel(LR_sel), .out(out[i])); 

you also need to take care of special cases [0] with left shift and [n-1] with the right shift. For simplicity, you can use if statement in the generate block to handle it.

if (i == 0)
  mux2to1 MUX0(.in({in, w[1]}), .sel(LR_bar), .out(tmp[0]));
else if (i == n-1)
  mux2to1 MUXN(.in({w[n-2], in}), .sel(LR_bar), .out(tmp[n-1]));

.out(out[i])); else mux2to1 (.in({out[i-1], out[i+1]}), .sel(LR_sel), .out(out[i]));

Basically it creates yet another mux for those special cases, so that you have more of them.

As for the flop, there are at least 2 ways to approach it. You can flop results before or after the mux.

for the flopping before the mux (which i assumed in the above explanation), you just do

always @(posedge clk)
   if (rst)
      w <= 4'b0;
   else
      w <= out;

to do it after the mux, you would need to switch out and w and then flop w into out. You can do a bit-by-bit flop as you did, but it makes the program more crowded in my opinion. Also it causes verilog to generate multiple one-bit flops which might affect simulation performance.

Another approach for shift registers with the flop is to something like the following:

always @(posegde clk) begi
   if (rst)
      out <= 4'b0;
   else if (LR_bar) begin
       out <= {out[2:0], in}; 
   end
   else begin
       out <= {in, out[3:1]}; 
   end
end

The above simplifies the code significantly. BTW, you would have an issue if you use blocking assignments there.

Edit 1

I modified your code to a workable condition down here based on my comments. you need a register w to keep the shift register value. You need the tmp to connect the mux with the flop. w is the output of the flop.

module uni_shreg_n(in, out, clk, rst, LR_bar);
  parameter n=4;

  input in, rst, clk, LR_bar;
  output [n-1:0] out;

  reg [n-1:0] w; // keep the value of the register shift
  wire [n-1:0] tmp;
  genvar i; 

  mux2to1 MUX0(.in({in,w[1]}), .sel(LR_bar), .out(tmp[0]));
  mux2to1 MUXN(.in({w[n-2], in}), .sel(LR_bar), .out(tmp[n-1]));

  generate
  for(i=0;i<n;i=i+1) begin  
    if (i > 0 && i < n-1) begin: loop
      mux2to1 MUX(.in({w[i-1], w[i+1]}), .sel(LR_bar), .out(tmp[i]));
    end
    dff ff1(.d(tmp[i]), .q(w[i]), .clk(clk),  .rst(rst));
   end
   endgenerate

   assign out = w; 

endmodule

Upvotes: 1

Related Questions