编辑:只有通过屏幕快照(http://prntscr.com/lv3uqw http://prntscr.com/lv3yhf)和下面的代码,您仍然可以在这里理解我的目标,以防万一您不想阅读文本。
我正在尝试为通用移位寄存器编写Verilog代码。我的原始寄存器运行正常(没有LR_bar signal
的寄存器)。但是在这一点上,我不知道如何使这种连接(带有ff的多路复用器)发生http://prntscr.com/lv3uqw和http://prntscr.com/lv3yhf.I有一个建议,for循环应该从-1开始,但是我仍然找不到解决方案。如果可能的话,我也想避免使用h信号(也许我们在那里也使用w)。因此,基本上,LR_bar=1
时我要将移位寄存器移至shift left
,而=0
时则要将移位寄存器移到shift right
。
屏幕截图提示:l_sh中的ser表示左移的串行输入
(还发现在Mano Morris第三版(更详细的第六版))上(计算机设计基础)这本书有点接近我想要的。但是我想要2to1多路复用器。但是第2个屏幕截图是我想要实现的。 http://prntscr.com/lvb5bt http://prntscr.com/lvb65f)
我认为我描述得很好...有人可以解决这个问题吗?
输出应该是寄存器的状态
-----------------------------------------------------------
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
答案 0 :(得分:1)
在您的特定情况下,阻止分配可能有效。为了保持简洁的编码风格并防止将来出现任何问题,请始终对触发器(和锁存器)中的所有输出分配使用<=
。
现在,让我们看看您想做什么:
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]
因此,使用多路复用器,例如out [2] i == 2
,您将需要一个执行以下操作的多路复用器:
- w[1] -
-> out[2]
- w[3] -
mux2to1 (.in({out[i+1], out[i-1]}), .sel(LR_sel), .out(out[i]));
您还需要注意特殊情况:左移为[0],右移为[n-1]。为简单起见,
您可以在generate块中使用if
语句来处理它。
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])); 其他 mux2to1(.in({out [i-1],out [i + 1]}),.sel(LR_sel),.out(out [i]));
基本上,它为这些特殊情况创建了另一个多路复用器,以便您拥有更多的这种情况。
对于翻牌圈,至少有2种方法来处理它。您可以在多路复用器之前或之后翻转结果。
对于多路复用器之前的扑通(我在上面的解释中假设),您只需
always @(posedge clk)
if (rst)
w <= 4'b0;
else
w <= out;
要在多路复用器之后执行此操作,您需要切换out
和w
,然后将w
滑入out
。您可以像以前一样一点一点地完成翻牌操作,但是在我看来,这会使程序更加拥挤。同样,它会导致Verilog生成多个一位触发,这可能会影响仿真性能。
在触发器中使用移位寄存器的另一种方法是:
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
上面的代码大大简化了代码。顺便说一句,如果在那里使用阻止分配,则会遇到问题。
编辑1
我根据自己的评论将代码修改为可行的条件。
您需要一个寄存器w
来保留移位寄存器的值。您需要tmp
来将 mux 与 flop 连接起来。 w
是翻牌圈的输出。
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