Verilog:为reg赋值

Verilog: assigning value to reg

我有一个关于 Verilog 的非常初级的问题,我希望得到一些帮助。

您可以在下面看到一个简单计数器的代码,它具有:

  1. 输入:单时钟信号,接时钟
  2. 输入:复位信号,接物理按键
  3. 输出:计数器输出
  4. 输出:led等于复位输入

奇怪的是,当复位信号为高电平时,计数器不会复位为零。 在板上,当我按下按钮时,我可以看到 LED 灯亮起和熄灭,因此重置为真,但 if 指令 internal_counter <= 0; 未执行 (?)

我将 Quartus Prime II Lite 与 DE-10 Nano Terasic 开发板一起使用

有什么建议吗?谢谢!

//Single clock input and a 32bit output port
    //reset will zero the internal_counter 
    module simple_counter (
                                    CLOCK_50,
                                    counter_out,
                                    reset,
                                    led
                                );          

    input CLOCK_50 ;
    input reset ;
    output led;
    output [31:0] counter_out;
    reg [31:0] counter_out;
    reg [31:0] internal_counter;
    reg led;

    always @ (posedge CLOCK_50) // on positive clock edge
        begin
            if (reset)
                        internal_counter <= 0;

            led <= reset;
            internal_counter <= internal_counter + 1;
            counter_out <= internal_counter;// increment counter
        end

    endmodule // end of module counter

我不知道为什么你的代码不起作用。我现在使用 VHDL。 但是,我会这样写:

module simple_counter (CLOCK_50, reset, led, counter_out);          

    input CLOCK_50 ;
    input reset ;
    output led;
    output [31:0] counter_out;

    reg [31:0] internal_counter;

    always @ (posedge CLOCK_50)
      begin
         if (reset)
            internal_counter <= 0;
         else
            internal_counter <= internal_counter + 1;

         led <= reset;
         counter_out <= internal_counter;
      end
endmodule

您的代码无法运行,因为您对 internal_counter 进行了两次赋值。这是允许的,但规则是 最后一次分配 "wins".

因此,让我们在重置处于活动状态时单步执行代码:

if (reset)   
  internal_counter <= 0; 

这使得 internal_counter 被重置(设置为零)。
但后来我们得到另一个作业:

internal_counter <= internal_counter + 1;

因为这是 later/behind 上一个作业 "wins"。这里有 no 条件所以这个 always 替换了之前的 if ...。这样 if... 代码就变得多余了。它永远不会执行,综合工具将为此删除任何逻辑。

正如其他人所指出的:您需要一个 else 部分。重置重置部分中的所有变量是一种很好的做法:

always @ (posedge CLOCK_50) // on positive clock edge
begin
   if (reset)
   begin
      internal_counter <= 0;
      led <= 1'b1; 
      counter_out  <= 0;
   end // reset section
   else
   begin // clocked section
      internal_counter <= internal_counter + 1;
      led <= 1'b0; 
      counter_out <= internal_counter; 
   end
end // clocked section 

现在我们得到一些一般性的评论:

我建议您改用 ANSI 端口定义。当你把所有东西放在一起时,它会更容易。如果您需要更改,例如counter_out 的宽度你可以在一个地方做到这一点:

module simple_counter (
    input      CLOCK_50 ,
    input      reset ,
    output reg led,
    output reg [31:0] counter_out  
   ); 

你的led有点奇怪。复位时为高,否则为低。我假设你这样做是为了调试。

counter_out 总是比 internal_counter 晚一个值。这是你想要的吗?它还会花费您 32 个额外的寄存器。我希望在没有内部计数器的情况下直接使用 counter_out:

always @ (posedge CLOCK_50) // on positive clock edge
begin
   if (reset)
   begin
      led <= 1'b1; 
      counter_out  <= 0;
   end // reset section
   else
   begin // clocked section
      led <= 1'b0; 
      counter_out <= counter_out + 1; 
   end
end // clocked section 

我会建议使用 Verilog-2001 变体进行更多改进,而您的代码无法正常工作,因为在重置期间您正在分配 internal_counter <= 0internal_counter <= internal_counter + 1'b1,所以通常当您像这样修改时工具将在重置条件下进行第二次分配,因此它不会导致分配给 0.. 我在您的代码中添加了 reset_synchronizer 因此 led u 的 on/off 中的 glithces 可能不会遇到此实现(基于在你使用的某些开关上它可能也不起作用)。

module simple_counter (
   input             clock_50
  ,input             reset
  ,output reg        led
  ,output reg [31:0] counter_out
);

reg [9:0] reset_sync = 10'h3_FF;
reg       system_reset = 1'b1 ;

// to remove glitches in PUSH Button reset
always@(posedge clock_50) begin
      reset_sync   <= #1  {reset_sync[8:0],reset};
      system_reset <= #1 &(reset_sync[9:2]);
end

always@(posedge clock_50)begin
  if (system_reset) begin
        led         <= #1 1'b0;
        counter_out <= #1 32'b0;
  end else begin
        led         <= #1 1'b1;
        counter_out <= #1 counter_out + 1'b1 ;// increment counter
  end
 end

endmodule