Перейти к содержанию
    

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

Есть модуль, у которого входы 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) соответственно.

 

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

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

 

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

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

always@(posedge Clk or posedge Rst)

 

Касательно самого первого примера - а такие вложенные always-ы вообще допустимы?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я бы поставил перед 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.

 

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

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

 

P.S.

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

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

verilog.pdf

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вам нужно сделать синхронизацию по фронту, тогда все будет работать: 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

Изменено пользователем M@kar

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...