Reputation: 79
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?
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
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