Set
https://pic.maxiol.com/thumbs2/17294...54.srprio2.png
Вид для печати
На всякий случай надо уточнить. Я же очень начинающий вериложник)
Забыл, я там хотел неблокирующее присваивание написать, <= вмест =.
- - - Добавлено - - -
Проанализировал по схем блок запроса шины. Если сравнивать с оригинальной документацией, то тайминги все навраны.
1. /BUSREQ защелкивается в другом полутакте, чем описано в документации.
2. Шины переводятся в Z-состояние тоже не в том полутакте.
3. Ну и возвращается все обратно тоже в другом полутакте.
https://pic.maxiol.com/images2/17294...eqackcycle.png
Ну от этого внешняя логика не пострадает.
Описание версталось параллельно, и, видимо, не все изменения попали в него. А потом посмотрели - и забили, как на не особо критичные.
Написал небольшой кусочек управления шинами и чтения кода команды в полностью синхронном дизайне.
Все тайминги совпадают с теоретически предсказанными, что не может не радовать)
https://pic.maxiol.com/images2/17295...d102120240.png
Вот фрагмент кода управления шиной для примера.
Если есть концептуальные косяки, можно сделать замечание)
Код://----------------------------------------------------------------------
//
// Управление внешней шиной
//
//----------------------------------------------------------------------
assign stop_rd_cycle = ((!m1) & t3) | t4 | res; // Сигнал окончания циклов MREQ, IORQ, RD для чтения/записи данных
// По сигналу RES
// По T4 любого цикла
// По Т3 любого цикла кроме M1
// Сигнал нначала цикла памяти
assign start_mem_cycle = ((!m1) & t1 & (!grp_io) | // По сигналу GRP_IO и T1 любого цикла, кроме M1
(m1 & t1 & (!int_ack))) & // По M1.T1, кроме INT_ACK (цикл чтения кода команды)
(!dis_bus); // При этом сигнал DIS_BUS не должен быть активен
// Вспомогательные сигналы
assign m1_t3_mask = t3_del & m1 & t3; // Сигнал маски по M1.T3.2
always @ (negedge clk) // Управление триггером mreq_rs (/CLK)
begin
if (stop_rd_cycle) // Если сигнал окончания записи,
mreq_rs <= 0; // то mreq_rs = 0 (высший приоритет),
else if (start_mem_cycle) // Иначе, если сигнал начала цикла памяти,
mreq_rs <= 1; // то mreq_rs = 1
end
assign mreq = mreq_rs & (!m1_t3_mask); // Внешний сигнал запроса памяти формируется с учетом врезки окончания цикла чтения кода операции
always @ (posedge clk) // Управление разрешением RD (CLK)
begin
disable_rd_port <= (int_ack & m1) | // В m1.int_ack,
req_write | // В цикле записи
dis_bus; // В цикле без доступа к памяти
end
always @ (negedge clk) // Управление триггером rd_rs (/CLK)
begin
if (stop_rd_cycle | // Если сигнал окончания записи,
(m1 & t3)) // или начало цикла регенерации памяти M1.T3,
rd_rs <= 0; // то mreq_rs = 0 (высший приоритет),
else if (start_mem_cycle & (!disable_rd_port)) // Иначе, если сигнал начала цикла памяти и сигнал RD не запрещен,
rd_rs <= 1; // то mreq_rs = 1
end
assign rd = rd_rs & (!(t3_del & m1)); // Внешний сигнал чтения памяти формируется с учетом удлиненной врезки окончания цикла чтения кода операции
Замечаний нет, есть немного обмена опытом.
После assign можно написать #n (n - число), чтобы сделать задержку при симуляции.
Только CLK в тестбенче нужно делать не always #1 CLK = ~CLK;, а подольше, можно даже примерно подогнать тайминги под timescale.
Например на самом верху пишем: `timescale 1ns/1ns (1 шаг равен 1 нс), а для дергания CLK пишем always #120 CLK = ~CLK; -- что равно 120 нс на полупериод (240 нс - 1 цикл).
Что даёт возможность делать задержки сигнала в симуляции с шагом 1/120 нс.
Таким образом можно имитировать все эти ваши "транзисторные особенности" :)
- - - Добавлено - - -
P.S. Немного читнул ранее про "ПОЛУ-такты". Да, это так. Большая часть ядер ретро-чипов (да что там.. скорее даже все) реализует оба полупериода (полуцикла), ещё их называют "фазами". Это абсолютная нормальность на таком уровне, если есть какой-то психологический "запор" в восприятии, то его необходимо как можно быстрее "пробить" :)
Все манипуляции с " #1 CLK = ~CLK; `timescale 1ns/1ps " абсолютно не важно до тех пор пока "мы" не начнём учитывать реальные времянки логических элементов. Вот тут две дороги:
1) мы моделируем абстрактные времянки абстрактной ЛА3 - и это будет абсолютно не синтезируемая модель поведения.
или
2) мы не мудрим с этими абстракциями, а задаём рельную частоту клока и реальны тип плисы.
При этом #1 и еже с ними используется для моделирования поведения внешнего окружения (как то sdarm память - реальная микросхема, аль ещё чего...) - но ни разу не используется в синтезируемой части кода.
ПС:
Это типовое значение и именно nS и pS
`timescale 1ns/1ps
ПС:ПС:
#1 CLK = ~CLK
здесь по первости можно указывать #5 чтоб получить "красивую" частоту в 100 МГц. и чтоб проще "отсчитывать" какой щаз период времени (хотя это можно сделать в автоматическом режиме отображение номера периода со счётчик оного клока).
Ребята, я вовсе не собираюсь на верилоге моделировать работу реальных транзисторов. Наоборот, весь мой код и реализация заточены под реальные возможности ПЛИС, синхронную архитектуру. Поэтому вопрос по коду на верилоге был задан именно исходя из этого. Правильно ли я пишу, пока не написал много, чтобы потом не пришломсь все переделывать.