移位寄存器Verilog

Gre*_*rey 4 verilog vlsi

我是HDL语言的新手.我有一个关于如何编程移位寄存器的问题.(我知道我转向另一个方向).为什么这本书使用wire[N-1:0] r_next?我的实施有什么缺点?谢谢

我的第一次尝试如下

module lesson04#(parameter N=8)(
    input wire clk, reset,
    input wire data,
    output wire out
);

reg [N-1: 0] r_reg;


always @(posedge clk or negedge reset)
begin
    if(!reset)
         r_reg =0;
    else 
        r_reg[0]=data;
        r_reg = r_reg<<1;
end

assign out =r_reg[N-1];
endmodule 
Run Code Online (Sandbox Code Playgroud)

但是这本书给出了:

module lesson04#(parameter N=8)(
    input wire clk, reset,
    input wire data,
    output wire out
);

reg [N-1: 0] r_reg;
wire[N-1:0] r_next;

always @(posedge clk or negedge reset)
begin
    if(!reset)
         r_reg =0;
    else 
        r_reg <= r_next;
end

assign r_next= {data, r_reg[N-1:1]};
assign out =r_reg[N-1];
endmodule
Run Code Online (Sandbox Code Playgroud)

Mar*_*rty 6

首先,不要忘记你begin- endS周围的代码段:

else begin
     r_reg[0]=data;
     r_reg = r_reg<<1;
end
Run Code Online (Sandbox Code Playgroud)

没有这个,只会在声明r_reg[0]=dataelse条款中if.这会起作用,但由于顺序逻辑描述中的阻塞语句而被认为是不好的样式...

其次,对于建模顺序块,使用非阻塞分配(<=)或您的计算可能会"失败"(谷歌非阻塞与阻止更多信息).您的示例可能非常有效(您是否在模拟器中尝试过?)但如果事情变得更复杂并且添加了更多变量,则事情可能会中断.

always @(posedge clk or negedge reset)
begin
    if(!reset)
         r_reg <= 0;
    else begin // This is horrible! Don't write code like this!
        r_reg[0] = data;     // blocking
        r_reg <= r_reg<<1;   // non-blocking
    end
end
Run Code Online (Sandbox Code Playgroud)

由于上述原因,有时建议将组合逻辑与顺序逻辑分开,以便您可以将非阻塞分配写入顺序块中的寄存器,并在组合块中进行阻塞,而不必担心调度.

要以这种方式编码,您需要使用当前状态计算下一个输出应该是什么,因此r_next答案中的总线.如果所有的触发器都以这种方式与周围的组合逻辑分离,我认为它也有助于合成工具.

此外,如果您的重置为低电平有效(即LOW重置),则应将其命名为,例如resetbreset_n.