Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
always @(posedge clk, negedge nreset)
begin
if(!nreset) begin
// Установка передатчика в исходное состояние
div4 <= 2'd0;
s <= 4'd10;
gotdata <= 1'b0;
end else begin
// Пока нет признака передачи стартового бита в этом цикле
sendstart = 1'b0;
// Начальная установка признака запроса данных на передачу
canfetch = wr;
if(div4 == 2'd0) begin
case(s)
4'd0:
begin
// Передача стартового бита будет инициирована ниже
sendstart = 1'b1; // ОШИБКА
// Передатчик занят, нельзя запрашивать новые данные
canfetch = 1'b0; // ОШИБКА
To ensure proper recognition and inference of state machines and to improve the quality of results, Altera recommends that you observe the following guidelines, which apply to both Verilog HDL and VHDL:
• Assign default values to outputs derived from the state machine so that synthesis does not generate unwanted latches.
• Separate the state machine logic from all arithmetic functions and data paths, including assigning output value
Всё ещё хуже — чтение сигнала, который присваивается в том же always блоке с помощью = (блокирующего присваивания) это состояние гонки. У меня sendstart сначала вычисляется и только потом читается. Последовательностей, которые Вы привели ниже в примерах (сигнал сначала читаем, а потом его же блокирующе модифицируем), у меня нет (то, что так делать нельзя, было интуитивно понятно). Просто во многих примерах в инете я видел применение блокирующих и неблокирующих присваиваний внутри одного always-блока, причем авторы утверждали, что синтезатор с этим успешно справляется. Да, в моей реализации все вычисляемые при помощи блокирующих присваиваний сигналы вполне можно вынести за always-блоки, просто формулы их вычислений повторят нынешние условия if/else и станут более громоздкими и сложными для понимания (человеком). Да, я читал статью от dsmv2014 и думал, что если мне понадобится симуляция, то я смогу воспользоваться этим хаком. Так все-таки вопрос к Вам, как профессионалу: синтезатору в моем случае все равно, где расположены блокирующие присваивания? Не симулятору, а именно синтезатору? А если не все равно, то почему именно? Можно разжевать в комментарии, можно отправить к источнику. В любом случае я буду весьма благодарен за совет.
У меня sendstart сначала вычисляется и только потом читается.
if(div4 == 2'd0) begin и проверка условия if (canfetch) происходят параллельно. Что самое неприятное: нельзя сказать, успеет он в том же такте проверить флаг canfetch или нет. Как разведётся.
always @(posedge clk) begin
a = b;
b = c;
end
always @(*) begin
a = a + 1;
end
Что такое «потом»? Код на Verilog не императивный, он декларативный. Его обманчивая похожесть на C/Java — его самый большой недостаток. Если внутри always-блока вы напишете несколько if на одном уровне вложенности, они все будут проверяться ПАРАЛЛЕЛЬНО и ОДНОВРЕМЕННО (с поправкой на время распространения фронта тактирующего сигнала).
Если внутри always-блока вы напишете несколько if на одном уровне вложенности, они все будут проверяться ПАРАЛЛЕЛЬНО и ОДНОВРЕМЕННО (с поправкой на время распространения фронта тактирующего сигнала).
always @(posedge clk) begin
a = b;
b = c;
end
always @(posedge clk) begin
a <= b;
b <= c;
end
always @ (posedge clk) begin
a <= b;
end
assign a = b & (c > 0); // здесь a должен быть wire
always @ (*) begin
a = b & (c > 0); // здесь a должен быть reg
end
always @(*) begin
a = a + 1;
end
always @(posedge clk) begin
if (a) begin
a = 0;
end
else begin
a = 1;
end
end
Врядли он будет работать, если частота обработки данных не в разы превышает скорость обмена по UART.
always @(*)
begin
if(nreset) begin
if(div4 == 2'd0) begin
case(s)
4'd0: begin
sendstart = 1'b1;
canfetch = 1'b0;
end
4'd9: begin
sendstart = 1'b0;
canfetch = wr;
end
4'd10:
begin
sendstart = 1'b0;
canfetch = wr;
end
default:
begin
sendstart = 1'b0;
canfetch = 1'b0;
end
endcase
end else begin
sendstart = 1'b0;
if(s < 4'd9) begin
canfetch = 1'b0;
end
else begin
canfetch = wr;
end
end
if(canfetch && idle) begin
sendstart = 1'b1;
end
else begin
sendstart = 1'b0;
end
end else begin
sendstart = 1'b0;
canfetch = 1'b0;
end
end
always @(*)
begin
if(nreset) begin
if(canfetch) begin
sendstart = 1'b1;
end
end else begin
sendstart = 1'b0;
end
end
(не помню как в Verilog, но в VHDL повторное неблокирующее присваивание в блоке считается ошибкой).
Мой «Hello World!» на FPGA или очередная версия UART