Предотвращение защелок в выписке по делу Verilog - PullRequest
2 голосов
/ 05 декабря 2011

У меня проблемы с пониманием того, как я могу предотвратить создание защелок в проекте Verilog. Я понимаю, что создаются защелки, потому что я не указываю, что происходит со всеми сигналами в каждом операторе case. Однако я не знаю, есть ли способ избежать этого (кроме драконовского метода, который я использовал в данный момент).

В настоящее время у меня есть два регистра сдвига, register X и register R. Каждый из этих регистров сдвига имеет 5-битную шину управления, управляемую из конечного автомата. Чтобы упростить управление этими регистрами сдвига, я надеялся использовать побитовые операции для установки и сброса битов шины управления.

Например, в состоянии done мне нужно сбросить бит shiftRight для register R. Для этого я могу выполнить следующую побитовую операцию:

rRegisterControlBus = rRegisterControlBus & ~register_ctrl_shiftRight;

Это работает отлично. Ниже вы можете увидеть все сигналы и побитовые операции, которые я определил для шины управления регистром. Однако, поскольку мне не нужно изменять все шины управления регистрами для обоих регистров в каждом состоянии, я получаю защелки. Например, в состоянии done ниже мне нужно только изменить шину управления регистром для register R. В результате создается защелка для register X шины управления.

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

Однако я считаю, что метод побитовой операции чище - я хотел бы знать, есть ли для меня возможность продолжать использовать этот метод, не имея дело с защелками. Это делает код намного проще для чтения и изменения.

Как всегда, спасибо за любую помощь.

// Register Control Bus Signals
// bit # - purpose
// 0 - reset (rst)
// 1 - load (ld)
// 2 - shift left (sl)
// 3 - shift right (sr)
// 4 - auxilary 1 (mux select)
parameter register_ctrl_reset = 5'b00001;
parameter register_ctrl_load = 5'b00010;
parameter register_ctrl_shiftLeft = 5'b00100;
parameter register_ctrl_shiftRight = 5'b01000;
parameter register_ctrl_auxilary = 5'b10000;
parameter register_ctrl_width = 5;
output reg [register_ctrl_width-1:0] xRegisterControlBus;
output reg [register_ctrl_width-1:0] rRegisterControlBus;

Предыдущее решение:

always@(currentState, ryCompareOut)
begin
  case(currentState)
   shiftRight:
   begin
     rRegisterControlBus = rRegisterControlBus & ~register_ctrl_shiftLeft;
     xRegisterControlBus = xRegisterControlBus & ~register_ctrl_shiftLeft;
     rRegisterControlBus = rRegisterControlBus | register_ctrl_shiftRight;
   end

   done:
   begin
    rRegisterControlBus = rRegisterControlBus & ~register_ctrl_shiftRight; 
   end

  endcase
end

Ответы [ 2 ]

3 голосов
/ 05 декабря 2011

Это verilog - вы можете получить биты напрямую. Возможно, измените ваши параметры на битовые индексы:


module case_statements #( parameter REGISTER_CTRL_WIDTH = 5 ) ( input [3:0] currentState, output reg [REGISTER_CTRL_WIDTH-1:0] xRegisterControlBus, output reg [REGISTER_CTRL_WIDTH-1:0] rRegisterControlBus );

localparam REGISTER_CTRL_RESET = 0;
localparam REGISTER_CTRL_LOAD = 1;
localparam REGISTER_CTRL_SHIFTLEFT = 2;
localparam REGISTER_CTRL_SHIFTRIGHT = 3;
localparam REGISTER_CTRL_AUXILARY = 4;

localparam STATE_SHIFTLEFT = 0;  // or enum, maybe?
localparam STATE_SHIFTRIGHT = 1;
localparam STATE_DONE = 2;

always@(*)
  begin
      // Defaults:
      rRegisterControlBus = 5'd0; // or whatever
      xRegisterControlBus = 5'd0;

      // Special cases:
      case(currentState)
        STATE_SHIFTRIGHT:
          begin
              rRegisterControlBus[REGISTER_CTRL_SHIFTRIGHT] = 1'b1;
          end
        STATE_SHIFTLEFT:
          begin
              rRegisterControlBus[REGISTER_CTRL_SHIFTLEFT] = 1'b1;
          end
        STATE_DONE:
          begin
              rRegisterControlBus[REGISTER_CTRL_SHIFTRIGHT] = 1'b0;
              rRegisterControlBus[REGISTER_CTRL_SHIFTLEFT] = 1'b0;
          end
      endcase
  end

endmodule

Чтобы избежать защелок и избежать необходимости писать множество verilog, чтобы убедиться, что каждая логическая ветвь устанавливает все переменные, я использую технику, для которой я не знаю имени!

Идея состоит в том, чтобы установить любые переменные, которые вы назначаете в процедуре always, на некоторый набор разумных «значений по умолчанию» в начале. Затем вы можете рассматривать любые отклонения от этих значений по умолчанию как особые случаи, и вам не нужно беспокоиться о том, чтобы убедиться, что все ваши переменные установлены во всех ветвях вашего кода - они получат значение по умолчанию.

0 голосов
/ 18 августа 2016

Этот тип линии не подходит для комбинаторного оператора.

rRegisterControlBus = rRegisterControlBus & ~register_ctrl_shiftLeft;

Вход влияет на вывод в этой строке комбинаторно. Инструмент видит это и сообщает, что это проблема. Чтобы прояснить проблему и показать, что беспокоит инструмент, представьте, что я написал:

always (*)
begin  
my_sig = ~my_sig;
end

Комбинаторно, сигнал всегда хочет инвертировать, и это будет происходить со скоростью распространения логики. Я только что сделал генератор, потому что он никогда не придет в состояние покоя. Инструменты знают, что это, вероятно, не то, что нужно, и дают мне знать.

...