Jump to content

    
Sign in to follow this  
KWIer

Борьба с Latches на verilog

Recommended Posts

Ну парни, всем спасибо, я устал возится с этим простейшим куском....

Чувствую себя неудавшимся кодером, потому как в графике нарисовал все за 5 минут и все работает..

Выложу, может пригодится или хоть настроение поднимет кому :)

module shift_reg
(
    input enable,
    input clr,
    input cpu_data_in, cpu_clk_in,
    output reg [263:0] sr = 0,
    output wire [8:0] bytenums
);

    reg [8:0] cntr;


assign bytenums = cntr;
     always @ (posedge cpu_clk_in or posedge clr) begin
            if (clr == 1'b1) begin
            cntr <= 9'd0;
            end
            else begin
            if (enable==1'b1) begin
              sr[263:1] <= sr[262:0];
              sr[0] <= cpu_data_in;
              cntr <= cntr + 1'b1;
              end
            end
      end


endmodule

 

module cntr264
(
    input enable,
    input clr, cpu_clk_in,
    output reg rec_ready
);

    reg [8:0] cntr;


     always @ (posedge cpu_clk_in or posedge clr) begin
            if (clr==1'b1) cntr <= 9'd0;
            else begin
              if (enable == 1'b1) begin
              cntr <= cntr + 1'b1;
              if (cntr == 9'd263) begin
                cntr <= 9'd0;
                rec_ready    <= 1'b1;
                end
            else rec_ready    <= 1'b0;
                
              end
              end
            
      end


endmodule

post-25041-1324363162_thumb.jpg

Share this post


Link to post
Share on other sites

Попробуйте вот так:

module cpu_in
  (
      input enable,
      input cpu_data_in, cpu_clk_in,
      output reg [263:0] cpu_mess,
      output wire [8:0] bytenums
  );
  
      reg [263:0] sr = 0;
      reg [8:0] cntr;
  
  assign bytenums = cntr;
     always @(enable) begin  
       always @ (posedge cpu_clk_in) begin
                sr[263:1] <= sr[262:0];
                sr[0] <= cpu_data_in;
                cntr <= cntr +1;
       end
     end
     always @(negedge enable) begin
        if (cntr==9'd264) cpu_mess <= sr;
        cntr <= 0;
     end
    endmodule

Не знаю, скомпилируется ли. Нет под рукой компилятора.

Share this post


Link to post
Share on other sites
Попробуйте вот так:

module cpu_in
   (
       input enable,
       input cpu_data_in, cpu_clk_in,
       output reg [263:0] cpu_mess,
       output wire [8:0] bytenums
   );
   
       reg [263:0] sr = 0;
       reg [8:0] cntr;
   
   assign bytenums = cntr;
      always @(enable) begin  
        always @ (posedge cpu_clk_in) begin
                 sr[263:1] <= sr[262:0];
                 sr[0] <= cpu_data_in;
                 cntr <= cntr +1;
        end
      end
      always @(negedge enable) begin
         if (cntr==9'd264) cpu_mess <= sr;
         cntr <= 0;
      end
     endmodule

Не знаю, скомпилируется ли. Нет под рукой компилятора.

 

Нее, не удается :(

Во-первых похоже не понравилось что always внутри другого always,

затем Error (10028): Can't resolve multiple constant drivers for net "cntr[8]" at cpu_in.v(20)

и еще кажется нельзя в одном модуле событие обрабатывать по enable и negedge enable

Share this post


Link to post
Share on other sites
Во-первых похоже не понравилось что always внутри другого always,

затем Error (10028): Can't resolve multiple constant drivers for net "cntr[8]" at cpu_in.v(20)

и еще кажется нельзя в одном модуле событие обрабатывать по enable и negedge enable

Похоже на правду. Главное, что у вас все заработало уже :cheers:

Так наверно тоже ругаться будет на latch?

always @(negedge enable) begin  
   if (cntr==9'd264) cpu_mess <= sr;
   cntr <= 0;
end
always @ (posedge cpu_clk_in) begin
   if (enable) begin
      sr[263:1] <= sr[262:0];
      sr[0] <= cpu_data_in;
      cntr <= cntr +1;
   end
end

Edited by M@kar

Share this post


Link to post
Share on other sites
Похоже на правду. Главное, что у вас все заработало уже :cheers:

Так наверно тоже ругаться будет на latch?

always @(negedge enable) begin  
    if (cntr==9'd264) cpu_mess <= sr;
    cntr <= 0;
end
always @ (posedge cpu_clk_in) begin
    if (enable) begin
       sr[263:1] <= sr[262:0];
       sr[0] <= cpu_data_in;
       cntr <= cntr +1;
    end
end

 

Ругается, но не на латч... А на несколько драйdеров cntr

Error (10028): Can't resolve multiple constant drivers for net "cntr[3]" at cpu_in.v(17)

Share this post


Link to post
Share on other sites

Тогда так:

always @(negedge enable) begin  
    if (cntr==9'd264) cpu_mess <= sr;
end
always @ (posedge cpu_clk_in) begin
    if (enable) begin
       sr[263:1] <= sr[262:0];
       sr[0] <= cpu_data_in;
       cntr <= cntr +1;
    end
    else  cntr <= 0;
end

 

Хотя не, так он else cntr <= 0; не обнулит никогда. Тогда у меня только вариант с латчем уживаться:

always @ (posedge cpu_clk_in or negedge enable) begin
  if (enable) begin
    sr[263:1] <= sr[262:0];
    sr[0] <= cpu_data_in;
    cntr <= cntr +1;
  end
  else begin // if (!enable) begin
    if (cntr==9'd264) cpu_mess <= sr;
    cntr <= 0;
  end 
end

Его можно попробовать так убрать:

module cpu_in
  (
      input enable,
      input cpu_data_in, cpu_clk_in,
      output reg [263:0] cpu_mess,
      output wire [8:0] bytenums
  );
  
      reg [263:0] sr = 0;
      reg [263:0] temp = 0;
      reg [8:0] cntr;
  
  assign bytenums = cntr;

  always @ (posedge cpu_clk_in or negedge enable) begin
  if (enable) begin
    sr[263:1] <= sr[262:0];
    sr[0] <= cpu_data_in;
    cntr <= cntr +1;
  end
  else begin // if (!enable) begin
    if (cntr==9'd264) begin 
      cpu_mess <= sr;
      temp <= sr;
      cntr <= 0;
    end
        else begin 
          cntr <= 0;
          cpu_mess <= temp;
       end
  end
endmodule

Хотя так жаловаться на temp будет :rolleyes:

Edited by M@kar

Share this post


Link to post
Share on other sites

Предполагаю, что вначале поднимается enable, потом 264 раза бьёт клок, потом enable опускается. Именно так типично управляется spi с микроконтроллера.

module cpu_in
(
     input enable,
     input cpu_data_in, cpu_clk_in,
     output reg [263:0] cpu_mess,
     output wire [8:0] bytenums
);

    reg [263:0] sr;
    reg [8:0] cntr;
    reg reset_count;
assign bytenums = cntr;
    always @ (posedge cpu_clk_in)
    begin
        if (enable)
        begin
            sr[263:1] <= sr[262:0];
            sr[0] <= cpu_data_in;
            if(reset_count)
                cntr <= 9'b0;
            else
                cntr <= cntr+1;
        end
    end
    always @(negedge enable)
    begin
        if(cntr = 9'd264)cpu_mess < sr;
    end
    always @(posedge cpu_clk_in or negedge enable)
        if enable = 1'b0 reset_count <= 1'b1;
        else reset_count <= 1'b0;

endmodule

Отдельно определяем регистр для cpu_mess, который защёлкивается по фронту enable,

и ещё специальный триггер для управления сбросом счётчика бит, который асинхронно устанавливается по уровню enable и сбрасывается после первого клока(который одновременно сбрасывает счётчик).

И не забывайте о синхронизации всего этого с системным клок доменом.

Ещё надо проверить конечное значение счётчика, которое может получится на 1 меньше, чем ожидалось.

Share this post


Link to post
Share on other sites

Я могу быть не права, но обратите внимание вот на что:

1) У всех авторов в их кодах считается не 264 бита, а 265, поскольку счетчик cntr начинает считать с 0, а значение снимается по счету 264, т.е. всего 265 тактов. Это же явно видно по схеме в аттачах автора KWIer.

2) У автора KWIer был запрос был такой, перефразирую - когда enable будет держаться 264 тактов подряд - только тогда считать информацию на шине правильной, т.е. защититься от внезапных всплесков enable, так? Если так, то никто из авторов не позаботился о том, чтобы "неправильные данные" во время случайного всплеска не попали в регистр sr, а ведь он потом перейдет в cpu_mess. Может стоит обнулять sr, когда enable не находится в единичном состоянии 264 такта подряд?

3) Автор KWIer скажите мне, КАК вы умудрились на схематике подключить ШИНУ на однобитный вход триггера (DFF кажется) и не получить ошибок?

4) Автор Timmy кажется приблизил этот код к работоспособности, но (без компилятора, на глаз) вижу такое несоответствие задумке: поясню

ЕСЛИ (enable = 0) ТО (reset_count = 1) - указано явно

ЕСЛИ (enable = 1) ТО (reset_count = 0) - указано неявно через else

в другом же процессе происходит проверка ЕСЛИ ((enable = 1) И (reset_count = 1)) ТО (cntr = 0) - сгруппировано мной для наглядности.

Так вот, cntr похоже никогда так 0 не станет.

 

 

 

Share this post


Link to post
Share on other sites
Я могу быть не права, но обратите внимание вот на что:

1) У всех авторов в их кодах считается не 264 бита, а 265, поскольку счетчик cntr начинает считать с 0, а значение снимается по счету 264, т.е. всего 265 тактов. Это же явно видно по схеме в аттачах автора KWIer.

2) У автора KWIer был запрос был такой, перефразирую - когда enable будет держаться 264 тактов подряд - только тогда считать информацию на шине правильной, т.е. защититься от внезапных всплесков enable, так? Если так, то никто из авторов не позаботился о том, чтобы "неправильные данные" во время случайного всплеска не попали в регистр sr, а ведь он потом перейдет в cpu_mess. Может стоит обнулять sr, когда enable не находится в единичном состоянии 264 такта подряд?

4) Автор Timmy кажется приблизил этот код к работоспособности, но (без компилятора, на глаз) вижу такое несоответствие задумке: поясню

ЕСЛИ (enable = 0) ТО (reset_count = 1) - указано явно

ЕСЛИ (enable = 1) ТО (reset_count = 0) - указано неявно через else

в другом же процессе происходит проверка ЕСЛИ ((enable = 1) И (reset_count = 1)) ТО (cntr = 0) - сгруппировано мной для наглядности.

Так вот, cntr похоже никогда так 0 не станет.

по 1)Я тоже обратил внимание в предыдущем посте, что 264 надо проверить и исправить:).

по 2)Случайные данные могут сколько угодно задвигаться в sr, в cpu_mess они не попадут, если enable держался не 264 клока. А потом полностью перезапишутся правильным пакетом в 264 клока.

по 4)Обращайте также внимание на условия выполнения процессов. В соответствии с ними reset_count безусловно и асинхронно устанавливается по низкому уровню enable, а сбрасывается по фронту clk при высоком уровне enable. Одновременно по тому же фронту clk сбросится и cntr, это не зря называется flip-flop.

Надеюсь, код типа

reset_count <= 1'b0;
if(reset_count==1'b1)cntr <= 9'b0;

не вызывает у Вас когнитивного диссонанса?:)

 

Ещё заметил, что я по VHDL-ной привычке иногда пишу "if" без скобок и = вместо ==.

 

Share this post


Link to post
Share on other sites
по 1)Я тоже обратил внимание в предыдущем посте, что 264 надо проверить и исправитьsm.
Обращал внимание автора на это, он говорит так и надо. Спасибо вам за пример, а то я так и не сообразил.
Edited by M@kar

Share this post


Link to post
Share on other sites
Надеюсь, код типа
reset_count <= 1'b0;
if(reset_count==1'b1)cntr <= 9'b0;

не вызывает у Вас когнитивного диссонанса?:)

 

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

 

if(reset_count==1'b1)
begin
   cntr <= 9'b0;
   reset_count <= 1'b0;
end

Share this post


Link to post
Share on other sites
считаю что код вырван из контекста

 

И Ваш тоже. Ибо все что Выше , предлагалось ввиде наброска без использования внутренней системной частоты. Что наложило свой отпечаток на реализацию в виде двух процессов always @(posedge cpu_clk_in) и always @(posedge cpu_clk_in or negedge enable), поэтому и разнесены по процессам reset_count и cntr.

Если и настаивать на чем либо, тестбенч желательно прилагать.

 

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

Share this post


Link to post
Share on other sites

Timmy, Спасибо за рабочий код... прогнал в симуляторе и в железе, все работает как часы...

На всякий случай выкладываю финальную редакцию твоего кода.

 

Я могу быть не права, но обратите внимание вот на что:

1) У всех авторов в их кодах считается не 264 бита, а 265, поскольку счетчик cntr начинает считать с 0, а значение снимается по счету 264, т.е. всего 265 тактов. Это же явно видно по схеме в аттачах автора KWIer.

...

3) Автор KWIer скажите мне, КАК вы умудрились на схематике подключить ШИНУ на однобитный вход триггера (DFF кажется) и не получить ошибок?

...

1) в реализации у Timmy, условие действительно должно быть if(cntr == 9'd263), чтобы считать ровно 264 клока (симуляция во вложении), так как счетчик увеличивается лишь по второму импульсу клока.

А вот в моей первой реализации по первому переднему фронту клока сдвигался 1 бит и счетчик становился равным 1, соответственно счетчик = 264 когда сдвинуто 264 бита, а не 265.

Можете провести сравнение двух симуляций в посках различий в поведении счетчиков :)

 

3) Quartus такие действия разрешает, если на входе и выходе DFF шина одинаковой ширины, он создает массив триггеров.

 

Еще раз всем спасибо! :santa2:

Вопрос можно считать решенным, а тему - завершенной

cpu_in.v

post-25041-1324618837_thumb.jpg

Edited by KWIer

Share this post


Link to post
Share on other sites
Что касается Вашего вопроса по графическому редактору, то как известно параметризированные lpm функции занимают много места на листе ватмана, поэтому и используют одиночные примитивы, ибо если к одиночному примитиву подвести шину, квартус размножает этот примитив до разрядности этой шины.

3) Quartus такие действия разрешает, если на входе и выходе DFF шина одинаковой ширины, он создает массив триггеров.

 

Ух ты! Забавно, что Квартус так умеет, не знала, спасибо)

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this