Jump to content

    
Sign in to follow this  
Sirko

Не понимаю источник проблемы на Verilog

Recommended Posts

Есть модуль, у которого входы Clk, Reset и выходы Led, Address

module MyModule(
input wire	Clk,
input wire	Reset,
output reg	[20:0]RAM_Address,
output reg	Led_Complete
);
always @ (*) begin
if (zero != 1'b0) begin
	RAM_Address  <= 0;
	Led_Complete <= 1'b0;
end else begin
	always @(posedge Clk) begin     // Здесь какаято ошибка
		if(RAM_Address < 7) begin
			RAM_Address  <= RAM_Address + 1;
		end else begin
			Led_Complete <= 1'b1;
		end
	end
end
end
endmodule

При компиляции возникает вот такая ошибка:

Error (10170): Verilog HDL syntax error at Logger.v(65) near text "always"; expecting "end"

Что я делаю не так?

 

Вариант №2

module MyModule(
input wire	Clk,
input wire	Reset,
output reg	[20:0]RAM_Address,
output reg	Led_Complete
);
always @ (Reset)
begin
RAM_Address  <= 0;
Led_Complete <= 1'b0;
end
always @ (posedge Clk)
begin
if(RAM_Address < 7)begin
	RAM_Address <= RAM_Address + 1'b0;
end else begin
//		Led_Complete <= 1'b1; Если строку разкоментарить, то возникнет ошибка
end
end
endmodule

Здесь тоже обычное присвоение вызывает ошибки

Error (10028): Can't resolve multiple constant drivers for net "Led_Complete" at Logger.v(42)

Error (10029): Constant driver at Logger.v(48)

в строках always @ (Reset) и always @ (posedge Clk) соответственно.

 

Помогите понять суть проблемы.

 

Share this post


Link to post
Share on other sites
Есть модуль, у которого входы Clk, Reset и выходы Led, Address

end else begin
	always @(posedge Clk) begin     // Здесь какаято ошибка
		if(RAM_Address < 7) begin
endmodule

При компиляции возникает вот такая ошибка:

Error (10170): Verilog HDL syntax error at Logger.v(65) near text "always"; expecting "end"

Что я делаю не так?

Так пишет же, что ожидает end. Значит, количество begin не соответствует количество end. Посчитайте аккуратно.

 

always @ (Reset)
begin
RAM_Address  <= 0;
Led_Complete <= 1'b0;
end
always @ (posedge Clk)
begin
if(RAM_Address < 7)begin
	RAM_Address <= RAM_Address + 1'b0;
end else begin
//		Led_Complete <= 1'b1; Если строку разкоментарить, то возникнет ошибка
end
end
endmodule

Здесь тоже обычное присвоение вызывает ошибки

Error (10028): Can't resolve multiple constant drivers for net "Led_Complete" at Logger.v(42)

Error (10029): Constant driver at Logger.v(48)

в строках always @ (Reset) и always @ (posedge Clk) соответственно.

 

Помогите понять суть проблемы.

И тут всё понятно. Вы пытаетесь присвоить Led_Complere значения в разных блоках, что при синтезе не разрешено, о чём вам синтезатор и сообщает. Сами подумайте, поставьте себя на место синтезатора - как бы вы реализовывали в железе этот код? Ведь это просто аппаратная коллизия. Именно поэтому синтезатор и не позволяет этого делать. Все присвоения переменной должны делаться в одном блоке. На симуляторе, конечно, такой код прокатит, но будут гонки и нестабильная работа кода, поэтому и для несинтезирумого кода так писать не надо.

Share this post


Link to post
Share on other sites
Так пишет же, что ожидает end
А где? Поштучно вроде как совпадает. Это весь код, не считая некоторых дополнительных входных и выходных параметров.

 

Сами подумайте, поставьте себя на место синтезатора
Я бы поставил перед Led_Complete мультиплексор и в зависимости от значения Reset, подавал бы на Led_Complete либо "0" либо значения с другого модуля. Тоже относится и к RAM_Address.

Понимаю, что я желаемое описываю неверно, но как должно быть, не представляю.

 

Это самые первые мои шаги в освоении ПЛИС. Вернее, какие там шаги? Я еще носки обуть не знаю как. В голове упорно сидят СИшные представления и для их "искривления" нужно немножко времени и практики. А пока :help:

 

 

Share this post


Link to post
Share on other sites

Сделайте вот так:

module MyModule(
input wire Clk,
input wire Reset,
output reg [20:0]RAM_Address,
output reg Led_Complete
);
always @ (Reset or posedge Clk)
if (Reset) begin
  RAM_Address <= 0;
  Led_Complete <= 1'b1;
end
else begin
  if(RAM_Address < 7)begin
    RAM_Address <= RAM_Address + 1'b0;
  end 
  else begin
    Led_Complete <= 1'b1; 
  end
end
endmodule

Share this post


Link to post
Share on other sites

А можно прокоментировать, почему сигнал Reset обязательно добавлять в перечень чувствительностей блока?

По поводу "Сделайте вот так:"появляется вот такая ошибка

Error (10122): Verilog HDL Event Control error at Logger.v(72): mixed single- and double-edge expressions are not supported

 

Может у моего проекта какие-то настройки нужно поправить?

Share this post


Link to post
Share on other sites

А вы в какой среде работаете? Quartus? Попробуйте строчку на такую заменить: always @ (posedge Reset or posedge Clk), либо вообще always @ (posedge Clk), а остальное так же. Он как раз жалуется на то, что в условии два выражения. У меня в ModelSim нет такой проблемы.

А можно прокоментировать, почему сигнал Reset обязательно добавлять в перечень чувствительностей блока?
Вы имеете ввиду вместе с posedge Clk? Можно и не добавлять, тогда все будет выполняться от клока, впрочем так и должно быть. Просто если снаружи изменить reset, то условия выполнятся не дожидаясь переднего фронта clk в случае с такой конструкцией: always @ (posedge Reset or posedge Clk).
Edited by M@kar

Share this post


Link to post
Share on other sites

Среда Quartus 9.1. Добавление posedge к Reset - ошибку устранило. Но мне не ясно, почему на все триггеры компилятор не может просто завести сброс, минуя клок?

На вопрос " а такие вложенные always-ы вообще допустимы?" я, пока-что, затрудняюсь ответить.

Share this post


Link to post
Share on other sites
always@(posedge Clk or posedge Rst)
В стандарте IEEE_Std_1364-2001 (Verilog) описаны такие конструкции. А вот как они будут синтезироваться я не знаю, но у Xilinx в примерах тоже встречал.

Но мне не ясно, почему на все триггеры компилятор не может просто завести сброс, минуя клок?
Почему нельзя, можно. Если вот такую конструкцию использовать always@(posedge Clk or posedge Reset), то так оно и будет. Просто если ты сделаешь, как предлагал в начале:
always @ (Reset)
begin
RAM_Address <= 0;
Led_Complete <= 1'b0;
end
always @ (posedge Clk)
begin
if(RAM_Address < 7)begin
RAM_Address <= RAM_Address + 1'b0;
end else begin
// Led_Complete <= 1'b1; Если строку разкоментарить, то возникнет ошибка
end
end
endmodule

То при установке Reset у тебя будет выполняться присвоение в блоке always @ (Reset) begin и тут же по клоку в блоке always @ (posedge Clk) begin.

Share this post


Link to post
Share on other sites
Я бы поставил перед Led_Complete мультиплексор и в зависимости от значения Reset, подавал бы на Led_Complete либо "0" либо значения с другого модуля. Тоже относится и к RAM_Address.

Понимаю, что я желаемое описываю неверно, но как должно быть, не представляю.

С мультиплексором это будет совсем не то, что вы описываете. Мультиплексором надо тоже управлять. И если запись опять идёт в разных блоках, т.е. параллельно, то как быть с в случае, если управляющие сигналы на мультиплексор приходят одновременно? Какому из них отдать предпочтение? Вы себе аппаратную реализацию представьте: вот ваша эта переменная должна просинтезироваться в триггер. На вход триггера вы подаёте сигналы от двух источников сразу. Это аппаратная коллизия и ничего более. Поэтому присвоения переменным должны выполняться строго внутри одного и того же блока, это залог правильной работы как симуляционных моделей, так и аппаратной имплементации.

 

Это самые первые мои шаги в освоении ПЛИС. Вернее, какие там шаги? Я еще носки обуть не знаю как. В голове упорно сидят СИшные представления и для их "искривления" нужно немножко времени и практики. А пока :help:

Это нормально, все через это проходят. Когда пишете на HDL, всегда держите в голове фоном, что тут все блоки работают параллельно во времени (HDL - это параллельные языки). Если хочется аналогий с С, то представьте, что у вас программа работает под управлением ОС, которая сама синхронизирует потоки выполнения в разных блоках (кстати, симулятор так и работает).

 

А можно прокоментировать, почему сигнал Reset обязательно добавлять в перечень чувствительностей блока?

Почему обязательно? Не обязательно. Если вы хотите получить триггер с асинхронным сбросом, то нужно добавить 'posedge clk', а если хотите синхронный сброс, то не надо добавлять:

always *(posedge clk, posedge reset) begin
    if(reset) begin
    ...        // асинхронный сброс 
    end
    else begin
    ...       // рабочая логика
    end
end

always *(posedge clk) begin
    if(reset) begin
    ...        // синхронный сброс 
    end
    else begin
    ...       // рабочая логика
    end
end

 

А вообще, если юзаете квартус, то лучше юзать и SV'шые конструкции: always_ff, always_comb.

 

И ещё совет. Если используете регистровый блок (т.е. который порождает триггеры), то рекомендуется использовать неблокирующие присваивания <=, а если комбинационный блок (т.е. где порождается только логика), то блокирующие =.

 

Share this post


Link to post
Share on other sites

Спасибо всем за разъяснения.

Буду кропать дальше.

 

Пока, что для представления разницы между блокирующим и не блокирующим присваиванием, требуется некоторое напряжение извилин. А SV'шые конструкции: always_ff, always_comb впервые слышу. Так, что возвращаюсь к чтиву.

 

P.S.

Если кто встечал русскоязычные рессурсы с пошаговыми примерами на верилоге с квартусом, пожалуйста, поделитесь. Ориентируюсь пока что марсоходом.

 

 

Share this post


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

verilog.pdf

Share this post


Link to post
Share on other sites

Объясните, пожалуйста, такое поведение кода:

module m1(clk, d0, d1, d2, d3, out, counter);

input wire clk;
input wire d0, d1, d2, d3;
output reg out = 0;
output reg [3:0] counter = 0;


always @(clk ) begin
    counter = counter + 1;
end
endmodule

Насколько я понимаю, то, при каждом изменении clk, должен увеличиваться счетчик. В симуляторе почему-то его выходы в неопределенном состоянии.post-29795-1324682141_thumb.png

 

Попробовал вот такой фокус:

module m1(clk, d0, d1, d2, d3, out, counter);

input wire clk;
input wire d0, d1, d2, d3;
output reg out = 0;
output reg [3:0] counter = 0;

reg [3:0] old = 0;

always @(clk ) begin

    if (clk != old) begin
        old = clk;
        counter = counter + 1;
        out = counter[0];
    end
end
endmodule

но здесь совсем :wacko:

post-29795-1324682434_thumb.png

модуль ни к чему не прицеплен

post-29795-1324682574_thumb.png

 

Кстати, а есть ли возможность в квартусе увидеть "принципиальную схему" скомпилированного блока?

Share this post


Link to post
Share on other sites

Объясните, пожалуйста, такое поведение кода:

module m1(clk, d0, d1, d2, d3, out, counter);

input wire clk;
input wire d0, d1, d2, d3;
output reg out = 0;
output reg [3:0] counter = 0;


always @(clk ) begin
    counter = counter + 1;
end
endmodule

Насколько я понимаю, то, при каждом изменении clk, должен увеличиваться счетчик. В симуляторе почему-то его выходы в неопределенном состоянии.post-29795-1324682141_thumb.png

 

Попробовал вот такой фокус:

module m1(clk, d0, d1, d2, d3, out, counter);

input wire clk;
input wire d0, d1, d2, d3;
output reg out = 0;
output reg [3:0] counter = 0;

reg [3:0] old = 0;

always @(clk ) begin

    if (clk != old) begin
        old = clk;
        counter = counter + 1;
        out = counter[0];
    end
end
endmodule

но здесь совсем :wacko:

post-29795-1324682434_thumb.png

модуль ни к чему не прицеплен

post-29795-1324682574_thumb.png

 

Кстати, а есть ли возможность в квартусе увидеть "принципиальную схему" скомпилированного блока?

Share this post


Link to post
Share on other sites

Вам нужно сделать синхронизацию по фронту, тогда все будет работать: always @(posedge clk) begin

module m1(clk, d0, d1, d2, d3, out, counter);

input wire clk;
input wire d0, d1, d2, d3;
output reg out = 0;
output reg [3:0] counter = 0;


always @(posedge clk) begin
    counter <= counter + 1;
end
endmodule

Edited by M@kar

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