使用多路复用器进行双向移位

时间:2018-12-15 13:17:28

标签: verilog

编辑:只有通过屏幕快照(http://prntscr.com/lv3uqw http://prntscr.com/lv3yhf)和下面的代码,您仍然可以在这里理解我的目标,以防万一您不想阅读文本。

我正在尝试为通用移位寄存器编写Verilog代码。我的原始寄存器运行正常(没有LR_bar signal的寄存器)。但是在这一点上,我不知道如何使这种连接(带有ff的多路复用器)发生http://prntscr.com/lv3uqwhttp://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

我认为我描述得很好...有人可以解决这个问题吗?

我的新代码(如下)和经过某些值后的测试……http://prntscr.com/lvhk63

我试图模仿(http://prntscr.com/lvgx31 http://prntscr.com/lvgxgw http://prntscr.com/lvgxkw)但仅用于串行输入部件(MSB,LSB)。请告诉我错误的地方。谢谢

输出应该是寄存器的状态

-----------------------------------------------------------
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

1 个答案:

答案 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;

要在多路复用器之后执行此操作,您需要切换outw,然后将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