Titus(20.10.2024)
На всякий случай надо уточнить. Я же очень начинающий вериложник)
Забыл, я там хотел неблокирующее присваивание написать, <= вмест =.
- - - Добавлено - - -
Проанализировал по схем блок запроса шины. Если сравнивать с оригинальной документацией, то тайминги все навраны.
1. /BUSREQ защелкивается в другом полутакте, чем описано в документации.
2. Шины переводятся в Z-состояние тоже не в том полутакте.
3. Ну и возвращается все обратно тоже в другом полутакте.
![]()
Ну от этого внешняя логика не пострадает.
Описание версталось параллельно, и, видимо, не все изменения попали в него. А потом посмотрели - и забили, как на не особо критичные.
Написал небольшой кусочек управления шинами и чтения кода команды в полностью синхронном дизайне.
Все тайминги совпадают с теоретически предсказанными, что не может не радовать)
Вот фрагмент кода управления шиной для примера.
Если есть концептуальные косяки, можно сделать замечание)
Код://---------------------------------------------------------------------- // // Управление внешней шиной // //---------------------------------------------------------------------- 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. Немного читнул ранее про "ПОЛУ-такты". Да, это так. Большая часть ядер ретро-чипов (да что там.. скорее даже все) реализует оба полупериода (полуцикла), ещё их называют "фазами". Это абсолютная нормальность на таком уровне, если есть какой-то психологический "запор" в восприятии, то его необходимо как можно быстрее "пробить"![]()
Titus(22.10.2024)
Все манипуляции с " #1 CLK = ~CLK; `timescale 1ns/1ps " абсолютно не важно до тех пор пока "мы" не начнём учитывать реальные времянки логических элементов. Вот тут две дороги:
1) мы моделируем абстрактные времянки абстрактной ЛА3 - и это будет абсолютно не синтезируемая модель поведения.
или
2) мы не мудрим с этими абстракциями, а задаём рельную частоту клока и реальны тип плисы.
При этом #1 и еже с ними используется для моделирования поведения внешнего окружения (как то sdarm память - реальная микросхема, аль ещё чего...) - но ни разу не используется в синтезируемой части кода.
ПС:
Это типовое значение и именно nS и pS
`timescale 1ns/1ps
ПС:ПС:
#1 CLK = ~CLK
здесь по первости можно указывать #5 чтоб получить "красивую" частоту в 100 МГц. и чтоб проще "отсчитывать" какой щаз период времени (хотя это можно сделать в автоматическом режиме отображение номера периода со счётчик оного клока).
Последний раз редактировалось AlexG; 21.10.2024 в 23:54.
Titus(22.10.2024)
Ребята, я вовсе не собираюсь на верилоге моделировать работу реальных транзисторов. Наоборот, весь мой код и реализация заточены под реальные возможности ПЛИС, синхронную архитектуру. Поэтому вопрос по коду на верилоге был задан именно исходя из этого. Правильно ли я пишу, пока не написал много, чтобы потом не пришломсь все переделывать.
Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)