verilog - 移位寄存器 Verilog

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

但是这本书给出了:

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

最佳答案

首先,不要忘记您的 begin -end围绕代码部分:

else begin
     r_reg[0]=data;
     r_reg = r_reg<<1;
end

没有这个,只有r_reg[0]=data将在 else if 的条款陈述。这可行,但由于顺序逻辑描述中的阻塞语句而被认为是不好的风格......

其次,对于顺序 block 建模,请使用非阻塞分配 ( <= ),否则您的计算可能会“失败”(谷歌非阻塞与阻塞以获取更多信息)。您的示例可能非常有效(您在模拟器中尝试过吗?),但是如果事情变得更加复杂并且添加了更多变量,事情可能会崩溃。

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

出于上述原因,有时建议将组合逻辑与顺序逻辑分开,以便您可以将非阻塞赋值写入顺序 block 中的寄存器,并在组合 block 中写入阻塞,而不必担心调度。

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

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

关于verilog - 移位寄存器 Verilog,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3517752/

相关文章:

add - 华莱士树和达达乘数之间的差异

floating-point - Verilog 中的复杂浮点时序逻辑

compiler-errors - ModelSim Altera 10.1d - verilog 我无法获得波形

verilog - 编写一个简单的函数来计算向量中的个数

verilog - 如何在 RTL 中使用时钟门控?

verilog - SystemVerilog 宏在行尾不需要 ';'

verilog - 不允许同时分配给非网络

compiler-errors - 错误:near “initial” : syntax error, unexpected initial [closed]

vhdl - verilog中的整数输入端口类似于vhdl?