Код Verilog моделирует, но не работает так, как прогнозируется на FPGA.
Вопрос
Я смоделировал поведение своего кода, и он работает отлично.Результаты соответствуют прогнозам.Когда я синтезирую свой код, загружаю его в спартанскую 3e FPGA и пытаюсь проанализировать с помощью чипскопа, результаты даже близко не соответствуют тем, которые я ожидал.Что я сделал неправильно?http://pastebin.com/XWMekL7r
Решение
Ваша проблема в строках 13-16, где вы задаете начальные значения для госрегистров:
reg [OUTPUT_WIDTH-1:0] previousstate = 0;
reg [OUTPUT_WIDTH-1:0] presentstate = 1;
reg [6:0] fib_number_cnt = 1;
reg [OUTPUT_WIDTH-1:0] nextstate = 1;
Это эквивалент написания «начального» оператора, присваивающего эти значения, который не поддается синтезу — в аппаратном обеспечении не существует такого понятия, как значение по умолчанию.Когда вы помещаете свой проект в FPGA, все эти регистры будут принимать случайные значения.
Вместо этого вам необходимо инициализировать эти счетчики/состояния внутри вашего блока Always, когда значение сброса высокое.
always @(posedge clk or posedge reset)
if (reset) begin
previousstate <= 0;
presentstate <= 1;
... etc ...
end
Ответ на уточняющие вопросы:
Когда вы инициализируете такой код, в аппаратном обеспечении вообще ничего не происходит — он полностью игнорируется, как если бы вы ввели оператор $display.Инструмент синтеза пропускает все конструкции, предназначенные только для моделирования, обычно выдавая об этом какое-то предупреждение (это действительно зависит от инструмента).
Теперь вопрос о блокировке и неблокировке требует очень длинного ответа :).Я направлю вас к статье SNUG-2000, которая, вероятно, является лучшей статьей, когда-либо написанной по этой теме.Он отвечает на ваш вопрос, а также на многие другие по этой теме.Впоследствии вы поймете, почему использование операторов блокировки в последовательной логике считается плохой практикой и почему ваш код в любом случае отлично работает с операторами блокировки.
http://cs.haifa.ac.il/courses/verilog/cummings-nonblocking-snug99.pdf
Еще ответы:
Обычный «шаблон» создания логики, подобной вашей, состоит в том, чтобы иметь два блока Always: один определяет логику, а другой определяет флопы.В первом случае вы используете операторы блокировки для реализации логики, а во втором — фиксируете (или сбрасываете) сгенерированное значение.Итак, что-то вроде этого:
wire some_input;
// Main logic (use blocking statements)
reg state, next_state;
always @*
if (reset) next_state = 1'b0;
else begin
// your state logic
if (state) next_state = some_input;
else next_state = 1'b0;
end
// Flops (use non-blocking)
always @(posedge clock)
if (reset) state <= 1'b0;
else state <= next_state;
Обратите внимание, что я использую синхронный сброс, но при необходимости вы можете использовать асинхронный.
Другие советы
Строки 13-16 верны."Рег [6: 0] fib_number_cnt = 1;" это не то же самое, что использование «начального» оператора.Прочтите руководство по синтезу Xilinx для более подробного описания инициализации регистров.