Verilog 移位寄存器

Verilog 移位寄存器,verilog,vlsi,Verilog,Vlsi,我对HDL语言非常陌生。我有一个关于如何编程移位寄存器的问题。(我知道我转向了另一个方向)。为什么这本书接下来要使用wire[N-1:0]r\u?我的实现有什么缺点? 谢谢 我的第一次尝试如下 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 ne

我对HDL语言非常陌生。我有一个关于如何编程移位寄存器的问题。(我知道我转向了另一个方向)。为什么这本书接下来要使用
wire[N-1:0]r\u
?我的实现有什么缺点? 谢谢

我的第一次尝试如下

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 
模块lesson04#(参数N=8)(
输入线时钟,复位,
输入导线数据,
输出线输出
);
注册号[N-1:0]r\u注册号;
始终@(posedge clk或negedge重置)
开始
如果(!重置)
r_reg=0;
其他的
r_reg[0]=数据;

r_reg=r_reg首先,不要忘记代码部分的
begin
-
end
s:

else begin
     r_reg[0]=data;
     r_reg = r_reg<<1;
end
出于上述原因,有时建议将组合逻辑与顺序逻辑分离,以便您可以将非阻塞分配写入顺序块中的寄存器,并在组合块中写入阻塞,而无需担心调度问题

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


此外,如果重置为低激活状态(即
low
resets),则应将其命名为低激活状态,例如
resetb
reset\n
,您的实现产生的输出与本书的输出完全不同。您应该通过构造一个简单的测试台来驱动输入并运行模拟来证明这一点。您将看到本书的输出将输入数据移动一个时钟周期,而您的输出将输入数据移动八个时钟周期

通过将
始终
块缩进的方式,我相信这不是您想要的。这就是块的实际行为:

always @(posedge clk or negedge reset)
begin
    if(!reset) begin
         r_reg =0;
    end else begin
        r_reg[0]=data;
    end
    r_reg = r_reg<<1;
end
始终@(posedge clk或negedge重置)
开始
如果(!重置)开始
r_reg=0;
结束,否则开始
r_reg[0]=数据;
结束

这本书的答案是“错的”,不是吗?如果你只想延迟一个时钟周期,为什么会有8次触发器。。。除非是成绩单上的一个打字错误(毕竟,有证据)…这似乎是对死亡领域的极大浪费!
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
always @(posedge clk or negedge reset)
begin
    if(!reset) begin
         r_reg =0;
    end else begin
        r_reg[0]=data;
    end
    r_reg = r_reg<<1;
end