Verilog reg 赋值?

4

我完全不懂Verilog编程,也不知道在哪里初始化reg变量。

让我们来看一下以下代码片段:

编辑: 综合时的警告

module test (
       output LED0 
       );   
reg led = 1'b1;
assign LED0 = led;
endmodule   

或者
module test (
       output LED0 
       );   

reg led;
initial begin
    reg led <= 1'b1;
end

assign LED0 = led;
endmodule

请帮我翻译:在这一行中因为没有被赋值,所以使用led的初始值:reg led = 1'b1;

是否只有在always@块中才能分配reg类型?

另一个例子:

module fourBitCounter
       (input clk,
        output [3:0]counter
        );

wire clk;
initial begin
reg[3:0] counter = 4'b1;
end

always@ (posedge clk) begin

         if(counter > 15)
              counter <= 0;
         else
              counter <= counter + 1;
         end endmodule

这里的reg初始值为0,但我之前已将其设置为1...出了什么问题?谢谢!

2个回答

9
“reg”类型只能在always @块中进行赋值吗?
不是的,“reg”类型可以在“always”块和“initial”块中进行赋值(加上“task”和“function”,但在此问题范围内将跳过它们)。
对于您的“fourBitCounter”,在“initial”块中声明的“reg[3:0] counter”创建了一个本地变量,也称为“counter”,该变量仅在创建它的块的范围内可访问。您需要删除初始块中的“reg[3:0]”,以便分配应用于预期的“counter”。但是它仍然无法正常工作,因为您将“counter”声明为推断出的线路类型,而“always” / “initial”块无法分配线路。
“counter”被声明为4位推断电线的输出(“output [3:0] counter”与“output wire [3:0] counter”同义)。由于“counter”在“always”块和“initial”块中分配,因此它需要是“reg”类型。因此,它应声明为“output reg [3:0] counter”。
此外,您将“clk”声明为输入和本地电线,它不能同时存在。端口可以在本地访问,没有理由将其重新声明为本地网。
FYI:对于4位值,15 + 1等于0,因为没有存储MSB的东西。
module fourBitCounter (
    input clk,
    output <i><b>reg</b></i> [3:0] counter // 'output reg', not 'output'
  );

//wire clk; // do not do this, clk is an input
initial begin
  counter = 4'b1; // no 'reg' here
end

always @(posedge clk) begin
  if(counter > 15) // this will never evaluate as true with counter declared as 4-bit
    counter <= 0;
  else
    counter <= counter + 1;
end
endmodule

在Verilog中,只能将assign语句应用于网络类型(例如wire)。以下是合法的代码:
module test ( output LED0 ); // LED0 is an inferred wire
assign LED0 = 1'b1;
endmodule

这是非法的:

module test ( output reg LED0 ); // Explicit reg
assign LED0 = 1'b1; // illegal, assign on a reg
endmodule

谢谢你的回答!它帮助我纠正了我的错误,但我还有一个问题:为什么在过程块中使用非赋值语句?为什么不用:counter <= 4'b1。附言:计数器在一开始仍然为0,也许initial块是不能被合成的? - M. Alex
在初始块中,我使用了一个阻塞赋值(=)。在always块中,我使用了一个非阻塞赋值(<=),这应该用于在always块中分配预期的flops/latches。我本来可以在初始块中使用非阻塞赋值,但是根据我的编码风格,我通常不这样做。非阻塞会推迟调度器中的更新,在时钟边沿很有用,但在时间零时不需要。 - Greg
现在一切都有意义了,除了以下内容:我可以像在我的第一个例子中那样将寄存器分配给线路吗?那里出了什么问题?即使我在initial块内分配了led,我仍然会得到:使用led的初始值,因为它从未被分配。 - M. Alex
我当然可以直接将LED0赋值为1,但我想看看是否可以将寄存器分配给线路。请看一下我上传的第一篇帖子中的图片。非常感谢您的时间! 感谢你们所有人! - M. Alex
led的问题是综合警告。除了只读存储器(ROM)外,初始化寄存器然后从未更新它并不常见。这是合法的,但通常是无意的,因为它更可能是一个错误或不完整的代码;因此它是一个警告。我建议尽可能解决所有警告;当设计不按预期工作时,这使得调试更容易找到问题所在。 - Greg
如果我的回答满足了您的问题,请接受我的答案。这将让其他人知道可以找到一个可接受的解决方案。 - Greg

0

从你的第一个代码示例:

reg led;             // <-- This declares one register called "led"
initial begin
    reg led <= 1'b1; // <-- This declares a *separate* register called "led"
end                  //     which is only valid in the initial block

你的第二个示例中也存在同样的问题;你在initial块中声明了一个单独的寄存器。如果你只是想赋值,不要使用regwire关键字。

是的,我确实犯了一个错误。但是即使在变量名前面没有reg或wire,它也不能正常工作。那么我的第一个例子呢? - M. Alex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接