Арифметическое уравнение в Verilog делится на уровни с часами, получая "Предупреждения защелки", пожалуйста, советы

ОБНОВЛЕНИЕ: я редактирую этот вопрос, чтобы изменить уравнение на более простое, хотя проблемы примерно одинаковы, с той разницей, что на этот раз, я действительно мог бы это сделать, это дает правильный ответ на расчет, но я продолжаю возникла проблема с "защелками" (мое исходное уравнение также работает нормально, но возникают те же проблемы с защелками).

Я хочу сделать простое уравнение шаг за шагом, которое выглядит следующим образом:

                             c = 50 / (|a - 2|^2 + |b - 5|^2) 

Данные представляют собой беззнаковые двоичные 32-битные значения, результат вычитания также является беззнаковым (абсолютные значения). Что я хочу сделать, это выполнить это в несколько этапов, используя часы,

       |a - 2| ,               // First this subtraction
       |b - 5| AND |a - 2|^2,  // then a subtraction and a square of before
       |a - 2|^2 + |b - 5|^2   // then the another square plus the before square
       c = 50 / |a - 2|^2 + |b - 5|^2   /// finally a division of 50

Я ожидаю, что инструмент синтеза генерирует только 1 вычитание, 1 возведение в квадрат и 1 деление для всего процесса, в этой упрощенной версии ситуация возникает только при возведении в квадрат и вычитании, поскольку существует только 1 операция деления. Первый вопрос: действительно ли я делаю то, что намеревался? Quartus II генерирует "канал данных"? действительно ли экономится оборудование / энергия?

Я новичок в verilog и цифровом дизайне в целом и учу себя этому, пожалуйста, поправьте меня, если мои концепции неверны.

Я создал модули деления, вычитания и возведения в квадрат отдельно, потому что планирую реализовать их позже, вместо того чтобы полагаться на операторы /,-,*. Причина в том, что, как я могу догадаться, программируя более эффективный алгоритм (например, доступный авторам в Интернете), я мог бы заменить алгоритмы, выведенные операторами, в Quartus II. Но опять же я не уверен.

Эта программа работает правильно, вывод ожидаемый, однако я получаю много предупреждений от Quartus-II, как это

Предупреждение (10240): предупреждение Verilog HDL Always Construct в FCM_EQ.v(88): вывод защелки (ей) для переменной "SU_in_a", которая хранит свое предыдущее значение в одном или нескольких путях через конструкцию всегда

Предупреждение (13012): защелка SQ_in_a[18] имеет небезопасное поведение. Предупреждение (13013): порты D и ENA на защелке питаются одним и тем же состоянием сигнала.S2

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

Топ-модуль таков:

module FCM_EQ (a, b, c, clk, enable, rst_n, all_finish, OBS);

input [31:0] a, b; 
input clk, enable, rst_n; 
output [31:0] c;
output [63:0] OBS;
output all_finish;

reg [31:0] SU_in_a, SU_in_b; 
wire [31:0] SU_out_r;

reg [31:0] SQ_in_a;
wire [63:0] SQ_out_r;

reg [63:0] DIV_in_b;
reg [63:0] DIV_in_a;
wire [63:0] DIV_out_r; 

reg [31:00] botA, botB, c;
reg [63:00] SQ_botA, SQ_botB, N_C;                    
reg [63:0] den_total;

reg all_finish;
reg [4:0] state, nextstate;
reg [63:0] OBS;

parameter FIFTY = 64'b0000000000000000_0000000000110010_0000000000000000_0000000000000000;
parameter FIVE = 32'b0000000000000101_0000000000000000;
parameter TWO = 32'b0000000000000010_0000000000000000;

parameter reset = 0;
parameter S0 = 1;
parameter S1 = 2;
parameter S2 = 3;
parameter S3 = 4;

SUB_VAL SU_inst1(.a (SU_in_a),.b (SU_in_b),.r (SU_out_r) );

SQ_VAL SQ_inst1 (.a (SQ_in_a),.r (SQ_out_r) );

DIV_VAL DIV_inst1 (.a (DIV_in_a),.b (DIV_in_b),.r (DIV_out_r) );

always @ (posedge clk or negedge rst_n)
  if (~rst_n) 
    state <= reset ;
  else
    state <= nextstate; 

always @*
begin
            case (state)    
reset:              
            begin
                if (enable == 1) 
                   nextstate = S0;                  
                else 
                    nextstate = reset;
            end
S0: 
            begin 
                SU_in_a = a;
                SU_in_b = TWO;         
                botA = SU_out_r;                                
                nextstate = S1;
            end
S1:
            begin
                SU_in_a = b;
                SU_in_b = FIVE;         
                botB = SU_out_r;                            

                SQ_in_a = botA;
                SQ_botA = SQ_out_r;
                nextstate = S2;
            end 
S2:
            begin
                SQ_in_a = botB;
                SQ_botB = SQ_out_r;      // SQ_botB is 64 bits (32_32)

                den_total = SQ_botA + SQ_botB;
                den_total = den_total >> 24;            
                nextstate = S3;
            end 
S3: 
            begin
                DIV_in_a = FIFTY;                  
                DIV_in_b = den_total;                 
                N_C = DIV_out_r;                        
                OBS = N_C;
                c = N_C [31:0];     // Extract 32 bits en total (16_24)                 
                all_finish = 1;
                nextstate = reset;
            end

default: 
            begin
                nextstate = reset;
            end
         endcase
 end
 endmodule

Регистр OBS - просто мой новый способ проверить значение регистра в Modelsim, так как я игнорирую, если есть лучший способ следить за этим.

Testbench и полный код можно посмотреть здесь

http://www.edaplayground.com/x/RTC

1 ответ

Решение

Не полный ответ, просто быстрые наблюдения:

always @ (posedge clk)
  state <= nextstate; //Use Non blocking

  always @* // Auto sensitivity list
  begin
    case (state)

Я также рекомендовал бы сбросить ваше состояние:

always @ (posedge clk or negedge rst_n)
  if (~rst_n) 
    state <= 'b0 ;
  else
    state <= nextstate; //Non blocking
Другие вопросы по тегам