2013-04-05 3 views
-1

Я написал поведенческую программу для множителя стенда (radix 2) с использованием концепции конечного автомата, я правильно получаю результаты во время моделирования программы с помощью modelsim, но когда i поместите его в fpga (спартанское 3), результаты не так ожидаются. Кто-то, пожалуйста, помогите мне с этим. Где я ошибся?Поведенческий код Verilog правильно моделируется, но не работает как ожидалось на FPGA

module booth_using_statemachine(Mul_A,Mul_B,Mul_Result,clk,reset); 

input Mul_A,Mul_B,clk,reset; 
output Mul_Result; 
wire [7:0] Mul_A,Mul_B; 
reg [7:0] Mul_Result; 


reg [15:0] R_B; 
reg [7:0] R_A; 
reg prev; 
reg [1:0] state; 
reg [3:0] count; 

parameter start=1 ,add=2 ,shift=3; 
always @(state) 
begin 

case(state) 

    start: 
    begin 
     R_A <= Mul_A; 
     R_B <= {8'b00000000,Mul_B}; 
     prev <= 1'b0; 
     count <= 3'b000; 
     Mul_Result <= R_B[7:0]; 
    end 

    add: 
    begin 

    case({R_B[0],prev}) 

     2'b00: 
      begin 
      prev <= 1'b0; 
      end 

     2'b01: 
      begin 
      R_B[15:8] <= R_B[15:8] + R_A; 
     prev  <= 1'b0; 
      end 

     2'b10: 
     begin 
       R_B[15:8] <= R_B[15:8] - R_A; 
       prev  <= 1'b1; 
      end 

     2'b11: 
      begin 
       prev <=1'b1; 
      end 

     endcase 

    end 

    shift: 
    begin 
    R_B <= {R_B[15],R_B[15:1]}; 
    count <= count + 1; 
    end 

endcase 


end 


    always @(posedge clk or posedge reset) 
    begin 

    if(reset==1) 
     state <= start; 

    else 
     begin 

     case(state) 

      start: 
       state <= add; 

      add: 
       state <= shift; 


      shift: 
       begin 

       if(count>7) 
        state <= start; 

      else 
       state <=add; 

       end 



    endcase 
    end 
    end 
endmodule 

ответ

0

Выполните следующий контрольный список, если что-то делает работу в моделировании, но не в реальности:

  • Вы настроите каждый регистр? (Да)
  • ли вы использовать 2 регистра для одной рабочей переменной, вы передаете после каждого такта (нет) (использование для состояния 2 сигналов/проводов, например, состояние и state_next и передачи после каждого тактового state_next в состоянии)

Пример второй точки: here, вам нужна следующая логика этапа, логика текущего состояния и логика вывода.

Для получения дополнительной информации о том, как правильный код FSM для FPGA см here (перейти к HDL Coding Techniques -> Основные HDL кодирования Techniques)

+0

Я не получил ваш второй пункт. Не могли бы вы рассказать подробнее? –

+0

Мое последнее редактирование объясняет это подробно? – Quonux

+0

У меня есть следующая логика состояния (блок 2-го блока case, @ posedge clk), а логика вывода - блок первого блока. Этого достаточно? –

3

У вас есть список неполный чувствительности в вашем комбинационной always блоке. Изменение:

always @(state) 

к:

always @* 

Это может быть синтезирования защелок.

Используйте блокирующие назначения в комбинационном блоке always. Изменить <= на =.

Хорошие инструменты для синтеза и литья должны предупредить вас об этих конструкциях.

0

У вас здесь различные проблемы.

  1. Ваш список чувствительности для первого всегда блока является неполным. Вы смотрите только на state, но есть множество других сигналов, которые должны быть там. Если ваши инструменты поддерживают его, используйте always @*, который автоматически генерирует список чувствительности. Измените это, и ваш код начнет имитировать, как он работает на FPGA.

    Это скрывает другие проблемы с кодом, потому что это вызывает сигналы для обновления в неподходящее время. Вам удалось заставить ваш код работать в симуляторе, но он основан на лжи. Лежит в том, что R_A, R_B, prev, count & Mul_Result является только зависит от изменений в состоянии, но есть больше сигналов, которые являются входами в эту логику.

  2. Вы попали в ловушку, где ключевое слово Verilog reg создает регистры. Это не так. Я знаю, что это глупо, но так оно и есть. То, что reg означает, что это переменная, которая может быть назначена из процедурного блока.wire s не может быть назначено внутри процедурного блока.

    Регистр создается, когда вы назначаете что-то в рамках процедурного блока с тактовой частотой (см. Сноску), как и ваша переменная state. R_A, R_B, prev и count все, как представляется, сохраняют значения в циклах, поэтому должны быть регистры. Я изменил код так:

Сначала я бы создать набор next_* переменных. Они будут содержать значение, которое мы хотим в каждом регистре следующих часов.

reg [15:0] next_R_B; 
reg [7:0] next_R_A; 
reg  next_prev; 
reg [3:0] next_count; 

Тогда я изменил бы процесс с тактовой частотой использовать эти:

always @(posedge clk or posedge reset) begin 

if(reset==1) begin 
    state <= start; 
    R_A <= '0; 
    R_B <= '0; 
    prev <= '0; 
    count <= '0; 

end else begin 
    R_A <= next_R_A; 
    R_B <= next_R_B; 
    prev <= next_prev; 
    count <= next_count; 

    case (state) 
    ..... 

Тогда, наконец, изменить первый процесс для назначения next_* переменных:

always @* begin 
    next_R_A <= R_A; 
    next_R_B <= R_B; 
    next_prev <= prev; 
    next_count <= count; 

    case(state) 

    start: begin 
     next_R_A <= Mul_A; 
     next_R_B <= {8'b00000000,Mul_B}; 
     next_prev <= 1'b0; 
     next_count <= 3'b000; 
     Mul_Result <= R_B[7:0]; 
    end 

    add: begin 

     case({R_B[0],prev}) 
     2'b00: begin 
      next_prev <= 1'b0; 
     end 

    ..... 

Примечание:

  • Все регистры теперь h ave a reset
  • Значение next_ для любого регистра по умолчанию соответствует его предыдущему значению.
  • next_ значения никогда не читают, для синхронизированного процесса
  • не- next_ значения никогда не написано, за исключением синхронизированного процесса, за исключением.

Я также подозреваю, что вы хотите Mul_Result быть wire и он assign Mul_Result = R_B[7:0];, а не причем другой регистр, который обновляется только в состоянии запуска, но я не уверен, что вы собираетесь там.


  • Регистр обычно является reg, но reg не должен быть регистр.
Смежные вопросы