【问题标题】:Bidirectional shifting using multiplexers使用多路复用器的双向移位
【发布时间】:2022-01-22 06:33:23
【问题描述】:

编辑:仅通过屏幕截图(http://prntscr.com/lv3uqwhttp://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 和当=0shift right 时。

截图提示:l_sh 中的 ser 代表左移的串行输入

(还发现在 Mano Morris 第 3 版(第 6 版更详细)书(计算机设计基础)上,在某种程度上,与我想要的有点接近。但我想要 2to1 多路复用器。但第 2 个截图是我想要实现的。 http://prntscr.com/lvb5bthttp://prntscr.com/lvb65f)

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

我的新代码(如下)和一些值之后的测试......http://prntscr.com/lvhk63

我试图模仿那个(http://prntscr.com/lvgx31http://prntscr.com/lvgxgwhttp://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

【问题讨论】:

  • @Serge 我看到了评论,我再次告诉你,这是我的第一篇关于这个的帖子,你链接到我的用户帖子甚至与我描述的不接近。
  • 我建议您查看另一个问题,因为您的代码片段实际上是从与另一个具有相同名称和错误的错误来源相同的错误来源中剪切并粘贴的。您乘以驱动线w 并且对阻塞分配的使用不正确,对生成块的使用效率低下。所以,先修复它们。在此之后,如果您仍然有问题,请添加“mux2one”的代码。谈论其余的没有意义,因为您的代码首先是错误的。
  • @Serge 这就是我寻求帮助的原因。我不知道如何在那里添加我的信号。我将添加代码,等待
  • @Serge 我还会附上我原来的移位寄存器代码。因为我的工作正常并且没有阻塞分配......
  • 根据我的第一个截图,多路复用器的输出应该是我认为可以完成的翻转翻转的输入。但是当我们需要相同的信号时,触发器的输出怎么能成为多路复用器的输入呢?

标签: verilog


【解决方案1】:

阻止分配可能适用于您的特定情况。为了保持简洁的编码风格并防止将来出现任何问题,请始终将&lt;= 用于触发器(和锁存器)中的所有输出分配。

现在,让我们看看你想做什么:

 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]));

基本上,它会为这些特殊情况创建另一个多路复用器,以便您拥有更多。

至于翻牌,至少有两种方法可以接近它。您可以在多路复用器之前或之后翻转结果。

对于多路复用器之前的失败(我在上面的解释中假设),你只需这样做

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

我根据我的 cmets 在此处将您的代码修改为可行的条件。 你需要一个寄存器w 来保存移位寄存器的值。您需要tmpmuxflop 连接起来。 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

【讨论】:

  • 我希望我的寄存器处于结构级别。但我认为 mux 部分可能会提供解决方案....给我一些时间。
  • 我会尝试在我的多路复用器上添加一些三元运算符(在通用移位寄存器代码中),看看它是否有效。
  • 如果我能做类似 mux2to1 MUX(.in({w[i],w[n+1-i]}),.sel(LR_bar),.out(h) ); dff ff1(.d(h), .q(w[i]?LR_bar:w[n+1-1]), .clk(clk), .rst(rst));但由于 LR_bar 我无法模拟它,我不想改变我的触发器
  • 它也有一个参数 n 所以我认为 out[2]i == 2 示例部分可能只是巧合
  • 是的,它确实有效。你需要创建一个测试台来模拟它。
猜你喜欢
  • 2013-12-16
  • 1970-01-01
  • 2023-03-13
  • 2018-12-20
  • 2021-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多