Кажется, у вас проблемы с английским языком, который не является вашей ошибкой, но из-за этого я могу неправильно истолковать ваш вопрос.
У вас есть форма волны того, что вам нужно достичь.Для меня это говорит о том, что это школьное задание, и поэтому я буду относиться к нему таким образом.Это означает, что я ** не * дам вам полный ответ, но дам вам подсказки о том, где вы идете не так.(Это все должно быть в комментарии, но теперь есть способ, которым это будет соответствовать).
... получил последние и действительные значения в случайный период из тестового стенда.
Первое, что нужно понять, это написание тестового стенда так же сложно, если не сложнее, чем написание самого кода RTL.
В вашем тестовом стенде вы используете always @(posedge clk)
, но внутри этогораздел вы используете #...
заявления.Это само по себе не так.Опасно, да, но не обязательно неправильно.
Но
Ваши часы имеют период времени 2 (parameter clk_period=2;
), и внутри ваших часовых часов вы используете задержки, которые равно или больше , чем период времени.Как вы уже выяснили, это часто приводит к катастрофе.
Узнайте о том, как работает Verilog, особенно когда используется список чувствительности always @...
: он не срабатывает, пока не будут рассмотрены все утверждения в разделе.В вашем случае это означает, что потребуется несколько фронтов тактовой частоты, пока снова не будет запущен блок Always.
Test Bench
Я не знаю, каково было назначение, поэтому я 'Я буду использовать форму волны, которую вы дали.Поскольку last
и valid
являются входами для вашего модуля, я дам вам указания, как их сделать.
valid
имеет высокий уровень для 4 тактов, а затем низкий для одного такта, после чегоэто повторяется.Это означает, что вам нужен шаблон, который повторяется каждые 5 тактов, и, следовательно, вам нужно создать счетчик, который считает 0,1,2,3,4,0,1,2,3,4, ...
Вы должны не сделать это с помощью #.....
операторов.Вы должны использовать часы на испытательном стенде и создать счетчик, который будет считать!
Создание счетчика, который считает, как описано выше, это первое, что вам нужно изучить в HDL!Вы обнаружите, что вам нужно делать это снова и снова, снова и снова. В каждом фрагменте кода RTL и на каждом тестовом стенде.
Счетчик по модулю 5.
Я предпочитаю, чтобы все мои модули и мои испытательные стенды имели сброс.Если только это позволяет мне начать новый тест из известного состояния.
reg [2:0] counter;
always @(posedge clk or negedge reset_n)
begin
if (reset_n)
counter <= ...
else // clocked section
begin
if (..)
counter <= ...
else
counter <= ...
end
end
Запустите заново и запустите приведенный выше код первым.Обратите внимание, что счетчик действительно работает 0,1 2, 3, 4, 0, ... прежде чем продолжить.
Производные сигналы.
Далее научитесь извлекать сигналы из этого.
Основное правило: в тактовой секции, если вам нужен сигнал со значением счетчика X, вы должны генерировать его в цикле X-1.
Таким образом, чтобы сделать последний максимум, когда счетчик равен 3, вы должныустановите его, когда счетчик равен 2:
always @(posedge clk...
...
if (counter==3'h2)
last <= 1'b1;
else
last <= 1'b0;
Я оставляю для вас действительное значение.
После того, как вы запустили тестовый стенд, начните работать над модулем design_d.
Несколько советов:
Используйте всегда неблокирующие назначения <=
в своем временном разделе.**
НЕ используйте период времени 2, используйте 100 или 1000. В свое время вы узнаете, почему это лучше.
Не используйте always @(posedge clk or [one or more signals] )
, если не в соответствии с моим примером.**
Позаботьтесь о своем отступе.Я должен был отредактировать мэра в вашем коде.
** Извините, я не могу вдаваться в подробности, почему это хорошая практика для большинствавремя как это утроило бы размер этого ответа.А пока, пожалуйста, следуйте советам.
Я мог бы написать действительный код за десятую часть времени, которое понадобилось мне, чтобы написать все это, поэтому я надеюсь, что вы не удалите вопрос, поскольку другие могут извлечь из этого пользуэто.