Verilog: присвоение значения reg - PullRequest
0 голосов
/ 21 марта 2020

У меня вопрос для Верилога о новичках, и я хотел бы помочь, пожалуйста.

Ниже вы можете увидеть код простого счетчика, который имеет:

  1. вход: одиночный синхросигнал, подключенный к входу часов
  2. : сигнал сброса, который подключен к физической кнопке
  3. выход: выход счетчика
  4. выход: светодиод равен входу сброса

Странное поведение состоит в том, что при высоком сигнале сброса счетчик не сбрасывается в ноль. На плате я вижу включение и выключение светодиода, когда я нажимаю кнопку, чтобы сброс был истинным, но инструкция if internal_counter <= 0; не выполняется (?)

Я использую Quartus Prime II Lite с DE-10 Nano Terasi c Board

Любое предложение, пожалуйста? Спасибо!

//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

Ответы [ 3 ]

2 голосов
/ 21 марта 2020

Ваш код не работает, потому что вы делаете два назначения для internal_counter. Это разрешено, но правило таково: последнее назначение «выигрывает» .

Итак, давайте пройдемся по коду, когда сброс активен:

if (reset)   
  internal_counter <= 0; 

Это делает что internal_counter сбрасывается (устанавливается в ноль).
Но позже мы получаем другое назначение:

internal_counter <= internal_counter + 1;

Поскольку это позднее / позади предыдущего назначения, оно "выигрывает". Здесь есть нет условия, поэтому этот всегда заменяет предыдущий if .... При этом код if... становится лишним. Он никогда не выполняется, и инструмент синтеза удалит для этого все логины c.

Как уже отмечали другие: вам нужен раздел 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 всегда на одно значение за внутренним_счетчиком. Это то, что вы хотите? Это также стоит вам 32 дополнительных регистра. Я ожидал бы обойтись без внутреннего счетчика и использовать direct_out direct:

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 
0 голосов
/ 22 марта 2020

Я бы предложил еще несколько улучшений, используя вариант Verilog-2001, и ваш код не работает, потому что во время сброса вы присваиваете internal_counter <= 0 и internal_counter <= internal_counter + 1'b1, поэтому обычно, когда вы изменяете, как это, инструменты принимают второе назначение. в состоянии сброса, так что это не приведет к присвоению 0 .. Я добавил reset_synchronizer в ваш код, так что ошибки включения / выключения светодиода u могут не встретиться с этой реализацией (в зависимости от некоторых используемых вами переключателей это может не работать).

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
0 голосов
/ 21 марта 2020

Я не знаю точно, почему ваш код не работает. Я работаю с 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
...