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

    

Вопрос по работе CASE в Verilog

Всем привет!

Осваиваюсь с Verilog и с ПЛИС. Возник вопрос по работе оператора CASE.

Значение регистра dig в приведённом коде должно(в моём понимании) становиться становиться 4'b0010, либо 4'b1000, либо 4'b0001 и должно меняться в трёх случаях:

когда значение disp_dat становится 0, 1 или 4.

На деле же оно меняется и тогда, когда disp_dat становится 2 и 5. В этих случаях оно становится 4'b0010 и 4'b1001.

Но у меня даже числа такие нигде в коде не фигурируют. Вопрос: почему dig меняется и в случаях, когда disp_dat становится 2 и 5?

 

Прилагаю код и скриншот отладки в SignalTap Quartus 2.11

module sled(seg,dig,clock,disp_dat);
input clock;
output [7:0] seg; 
output [3:0] dig; 
reg [7:0] seg; 
reg [3:0] dig; 
output reg [3:0] disp_dat; 
reg [36:0] count; 


always @ (posedge clock )
begin 
count = count + 1'b1;
end

always @ (count[24])
begin
disp_dat = {count[28:25]};
end
always @ (disp_dat)
begin 
case (disp_dat)
4'h0 : begin 
		seg <= 8'hc0; //"0"
		dig <= 4'b0010;
	end
4'h1 : begin 
			seg <= 8'hf9; //"1"
			dig <= 4'b1000;
		end
4'h2 : begin 
			seg <= 8'ha4; //"2"
	end
4'h3 : begin 
			seg <= 8'hb0; //"3"
	end
4'h4 : begin
			seg <= 8'h99; //"4"
			dig<=4'b0001;
	end
4'h5 : seg <= 8'h92; //"5"
4'h6 : seg <= 8'h82; //"6"
4'h7 : seg <= 8'hf8; //"7"
4'h8 : seg <= 8'h80; //"8"
4'h9 : seg <= 8'h90; //"9"
4'ha : seg <= 8'h88; //"a"
4'hb : seg <= 8'h83; //"b"
4'hc : seg <= 8'hc6; //"c"
4'hd : seg <= 8'ha1; //"d"
4'he : seg <= 8'h86; //"e"
4'hf : seg <= 8'h8e; //"f"
endcase

end
endmodule

 

Signal_Tap.jpg

Изменено пользователем jurist

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


Ссылка на сообщение
Поделиться на другие сайты
always @ (count[24])
begin
disp_dat = {count[28:25]};
end

Здесь что-то странное. Что вы хотели тут сделать?

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


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

eugen_pcad_ru

Значение disp_dat состоит из 4 бит и чисто физически может принимать значения от 0h до Fh. Все 16 состояний у меня описаны и последовательно отрабатываются. Это видно по приложенной к первому сообщению картинке - все значения строго от 0h до Fh.

Я слышал, что в Verylog бывают неопределённые состояния... Даже если предположить, что в disp_dat могло попасть другое значение, оно было бы проигнорировано, т.к. не подходит ни под одно из условий CASE.

 

Для верности, дописал обработку для значения default, запустил на отладочной плате, но ничего не поменялось.

 

 

andrew_b

Каждый раз, когда меняется значение count[24], в disp_dat заносятся 4 бита count[28] - count[25].

Можно заменить count[24] на count[25] или на posedge clock, на конечный результат в данном случае это никак не повлияет.

 

И ещё, Verilog пишет следующее предупреждение, касательно dig: Warning (13012): Latch dig[0]$latch has unsafe behavior

Нашёл статью по теме: https://marsohod.org/verilog/155-verilogmux

Но всё равно пока не могу понять, как значения могут меняться на самопроизвольные, если я конкретно описал нужные мне случаи и значения?

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


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

Мне в этом коде не нравится:

1 в always стоят не клоки

2 входные данные внутри always не зафиксированы на предыдущем такте / полутакте.

 

module sled(seg,dig,clock,disp_dat);
input clock;
output [7:0] seg; 
output [3:0] dig; 
reg [7:0] seg; 
reg [3:0] dig; 
output reg [3:0] disp_dat; 
reg [36:0] count; 


always @ (posedge clock ) //count changes on poedge
begin 
	count = count + 1'b1;  
end


always @ (posedge clock ) //disp_dat_CE changes on posedge
begin 
	disp_dat_CE =...
end

always @ (negedge clock ) //disp_dat changes on negedge
begin 
if (disp_dat_CE) disp_dat = {count[28:25]}; 
end


always @ (negedge clock ) //dseg_dig_CE changes on negedge
begin 
dseg_dig_CE = …
end

always @ (posedge clock ) //seg & dig changes on posedge
begin
if (dseg_dig_CE) 
case (disp_dat)
4'h0 : begin 
		seg <= 8'hc0; //"0"
		dig <= 4'b0010;
	end
4'h1 : begin 
			seg <= 8'hf9; //"1"
			dig <= 4'b1000;
		end
4'h2 : begin 
			seg <= 8'ha4; //"2"
	end
4'h3 : begin 
			seg <= 8'hb0; //"3"
	end
4'h4 : begin
			seg <= 8'h99; //"4"
			dig<=4'b0001;
	end
4'h5 : seg <= 8'h92; //"5"
4'h6 : seg <= 8'h82; //"6"
4'h7 : seg <= 8'hf8; //"7"
4'h8 : seg <= 8'h80; //"8"
4'h9 : seg <= 8'h90; //"9"
4'ha : seg <= 8'h88; //"a"
4'hb : seg <= 8'h83; //"b"
4'hc : seg <= 8'hc6; //"c"
4'hd : seg <= 8'ha1; //"d"
4'he : seg <= 8'h86; //"e"
4'hf : seg <= 8'h8e; //"f"
endcase

end
endmodule

 

пишу по памяти, но идея должна быть понятна...

 

PS: значение disp_dat_CE должно быть равно 1 или то от чего оно зависит должно меняться на negedge

значение dseg_dig_CE должно быть равно 1 или то от чего оно зависит должно меняться на posedge

 

 

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


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

1 в always стоят не клоки

2 входные данные внутри always не зафиксированы на предыдущем такте / полутакте.

 

...

 

PS: значение disp_dat_CE должно быть равно 1 или то от чего оно зависит должно меняться на negedge

значение dseg_dig_CE должно быть равно 1 или то от чего оно зависит должно меняться на posedge

 

Т.е. ТС надо почитать о "синхронном проектировании". И о метастабильности... И прочитать, когда в case образуются latch...

Делалась ли RTL симуляция? Или сразу непроверенный код - в железо?

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


Ссылка на сообщение
Поделиться на другие сайты
Каждый раз, когда меняется значение count[24], в disp_dat заносятся 4 бита count[28] - count[25].
Каждый раз меняется -- это оба фронта, да? Во-первых, вы заводите на тактовый вход триггера нетактовый сигнал. Это неправильно, в FPGA это не приветствуется. Во-вторых, в FPGA нет триггеров, работающих по обоим фронтам. Вы смотрели результат синтеза, он вас устраивает?

Можно заменить [...] на posedge clock
Не можно, а нужно. Гуглите "синхронный дизайн".

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

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


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

1 в always стоят не клоки

2 входные данные внутри always не зафиксированы на предыдущем такте / полутакте.

...... Во-первых, вы заводите на тактовый вход триггера нетактовый сигнал. ...

_4afc_, Идею с программой, к сожалению, не совсем понял, но Вы сказали ключевую фразу. andrew_b тоже указал на это. Спасибо!

Поставил один always с "posedge clock" всё заработало как должно. :biggrin:

Даже приведу новый код:

module sled(seg,dig,clock,disp_dat);
input clock;
output [7:0] seg; 
output [3:0] dig; 
reg [7:0] seg; 
reg [3:0] dig; 
output reg [3:0] disp_dat; 
reg [36:0] count; 

always @ (posedge clock )
begin 
count = count + 1'b1;
disp_dat = {count[28:25]};

case (disp_dat)
4'h0 : begin 
		seg <= 8'hc0; //"0"
		dig <= 4'b0010;
	end
4'h1 : begin 
			seg <= 8'hf9; //"1"
			dig <= 4'b1000;//
		end
4'h2 : begin 
			seg <= 8'ha4; //"2"
	end
4'h3 : begin 
			seg <= 8'hb0; //"3"
	end
4'h4 : begin
			seg <= 8'h99; //"4"
			dig<=4'b0001; //
	end
4'h5 : seg <= 8'h92; //"5"
4'h6 : seg <= 8'h82; //"6"
4'h7 : seg <= 8'hf8; //"7"
4'h8 : seg <= 8'h80; //"8"
4'h9 : seg <= 8'h90; //"9"
4'ha : seg <= 8'h88; //"a"
4'hb : seg <= 8'h83; //"b"
4'hc : seg <= 8'hc6; //"c"
4'hd : seg <= 8'ha1; //"d"
4'he : seg <= 8'h86; //"e"
4'hf : seg <= 8'h8e; //"f"
endcase
end
endmodule

Программа была из набора примеров для отладочной платы, а я решил с ней поковыряться. Думал, что примеры пишут более подготовленные люди.

 

Т.е. ТС надо почитать о "синхронном проектировании". И о метастабильности... И прочитать, когда в case образуются latch...

Делалась ли RTL симуляция? Или сразу непроверенный код - в железо?

В RTL Viever смотрел, но мне на данном этапе сложно читать программу в виде логических элементов.

 

Правило с правильным тактированием я усвоил. Но я ещё не осознал, почему я указываю изменение всех данных строго после изменения disp_dat, а они меняются сами, как попало. Статьи на рекомендованные темы обязательно прочитаю и постараюсь разобраться.

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


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

Я спрашивал не о " RTL Viever", а о RTL-симуляции. Это совершенно разные вещи...

 

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


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

Поставил один always с "posedge clock" всё заработало как должно. :biggrin:

 

Если у вас будет 1 always и вместо <= вы будете писать =, то безусловно синтаксис верилога приблизится к си и всё будет работать.

 

Только:

1 очень медленно

2 такой стиль не приблизит вас к освоению верилог и ПЛИС

 

 

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


Ссылка на сообщение
Поделиться на другие сайты
Я спрашивал не о " RTL Viever", а о RTL-симуляции. Это совершенно разные вещи...
До симуляторов ещё не добрался.

 

Если у вас будет 1 always и вместо <= вы будете писать =, то безусловно синтаксис верилога приблизится к си и всё будет работать.

 

Только:

1 очень медленно

2 такой стиль не приблизит вас к освоению верилог и ПЛИС

_4afc_, благодарю за грамотные советы!

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


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

Тут можно сказать только одно.

ПЛИС - это не микроконтроллер. Тут совсем другая технология. Без симуляции вообще нет смысла браться за стартовый набор. Мало того, верилог - это не программа, это описание железа. И оно тоже делается не так, как программа. Другим методом. Если хотите, то могу об этом рассказать по скайпу. Мне так будет проще.

 

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


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

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация