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

Первый проект на Verilog. Прошу помощи

On 6/24/2020 at 12:40 AM, pinchemierda said:

ТЗ: 

1. После принятия посылки из 8 бит по линии i_mosi, модуль должен сформировать сигнал o_irq длительностью 1 такт и выдать принятые данные на внешний порт o_rx_buf.

2. Спустя минимальное количество времени после спада i_cs или фронта o_irq должны защёлкиваться 8 бит на параллельном входе i_tx_buf. Затем этот байт должен быть передан последовательно (в соответствии с протоколом SPI CPHA=0, CPOL=0) по линии o_miso.  

Ну сейчас то уж синхронней некуда)):

на выходе порта опять светомузыка, голову сломал уже...

отлично, теперь вы знаете к чему стремиться и у вас есть основа для быстрой проверки изменений (кстати фазы вашего выхода, не соответствуют протоколу SPI 00 https://ru.wikipedia.org/wiki/Serial_Peripheral_Interface, но это не должно особо мешать).

парадигма у вас стала синхронной, но не до конца и не учтены детали, про которые вам написали коллеги.

Но вот какой факт, вы оставили без внимания: квартус переделал ваш логику, т.к. вы не корректно ее описали. Отметил эти моменты на скриншоте. Раньше квартус выдавал предупреждение об этом, но новые похоже делают так, как считают нужными. В итоге, помимо прочего, ваш асинхронный сигнал тянется через всю логику и логика отличается от того, что вы задумали. И да, симулятор эти моменты вам не покажет. Нужно работать дальше) 

spi.png

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


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

Я бы все же рекомендовал вам начать с ТЗ попроще. Но довести его до конца.

ТЗ #0:

0. Общая постановка задачи

Реализовать счетчик-делитель с изменяемым коэффициентом деления. Главный выход счетчика должен иметь duty cycle 50%. Служебный выход heartbeat должен выдавать сигнал с частотой 1 Гц, duty cycle 50% независимо от программируемого коэффициента деления.

1. В качестве тактового сигнала должен использоваться тактовый сигнал на PIN_64 (50 MHz).

2. У устройства д.б. следующие режимы работы:

  • IDLE - режим ожидания, он же режим по умолчанию после выхода из состояния RESET;
  • SETUP - режим задания коэффициента деления
  • COUNT - режим счета с заданным коэффициентом

3. У счетчика д.б. следующие органы управления:

  • 1 кнопка RESET (manual) - помимо внутреннего сигнала pwron_rst_n, получаемого в конечном счете с PIN_44
  • 1 кнопка MODE переключения режима работы; переключение - циклическое: IDLE => SETUP => COUNT => IDLE ...
  • 1..n кнопок или переключателей для задания коэффициента деления в режиме SETUP (зависит от выбранного способа ввода)

4. У счетчика д.б. следующие средства индикации (с возможностью вывода на LEDs):

  • 2-bit выход STATE - для индикации режима работы или состояния управляющей машины состояний (включая ее состояние RESET)
  • 1-bit выход HEARTBEAT - для индикации признаков жизни/счета/работоспосбности-наличия входного клока и т.п.
  • N-bit выход DIVIDE_COEFF - для индикации действующего коэффициента деления

5. Основные продукты работы устройства:

  • главный выход счетчика CLK_OUT должен быть выведен на PIN_xx
  • служебный выход HEARTBEAT д.б. выведен на PIN_yy.
  • опционально м.б. выведены для контроля промежуточные сигналы делителя на PIN_aa .. PIN_bb.

6. Входы устройства:

  • PWRON_RST_N (Power-On Reset) : PIN_44
  • RESET_N (manual reset from button) : PIN_rr
  • MODE (выбор режима) : PIN_zz

......

7. Выходы устройства (кроме указанных в п.5):

......

Примерно вот так. При реализации такого ТЗ вам придется соприкоснуться с многими моментами разработки реальных устройств. И в то же время устройство имеет обозримую сложность.

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


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

25.06.2020 в 00:46, Raven сказал:

а натягивание на 18 МГц при клоке 50 - тут без асинхронщины не обойтись

Как оказалось, моя ошибка была именно в этом. Пытаясь использовать с максимальной выгодой каждый такт, неправильно написал детектор фронтов.

Только всё равно не понимаю, почему так не работает:

always @(posedge i_core_clk)
begin
  sync_clk <= i_clk;
  sync_cs <= i_cs;
end

а так работает:

	//детектор фронта CLK
	reg clk_1, clk_2; 
	wire sync_clk;
	assign sync_clk = clk_1 & ~clk_2;
	
	//детектор спада CS
	reg cs_1, cs_2; 
	wire sync_cs;
	assign sync_cs = ~cs_1 & cs_2;
	
	always @(posedge i_core_clk)
	begin
		clk_1 <= i_clk;
		clk_2 <= clk_1;
		
		cs_1 <= i_cs;
		cs_2 <= cs_1;
	end

Последний вариант игнорировал, потому что он медленнее. Уж не знаю насколько сейчас правильно с фундаментальной (академической) точки зрения, но работает без каких либо reset-ов (я не говорю, что он не нужен, но конкретно в этом проекте, вероятно, можно обойтись и без него). С такими детекторами фронтов CLK и CS всё правильно отправляется и принимается, только на скорости не выше 8МГц. В общем, вариант не быстрее, чем реализация через автомат состояний, как в том посту. И не могу сказать, что результат меня устраивает. Как можно без асинхронщины натянуть на 18МГц при клоке в 50МГц?

Цитата

а соответствующие констрейны написаны?

Полез искать, что это вообще такое. Если правильно понял, это необходимо при асинхронном дизайне. Мне бы пока с синхронным разобраться.

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


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

5 hours ago, pinchemierda said:

Только всё равно не понимаю, почему так не работает:

...

а так работает:

...

Уже сказано, почему - см. про метастабильность.

Ваш 2-й вариант все еще недостаточно свободен от эффектов метастабильности, т.к. составляющие clk_1 и cs_1 прошли только один триггер в синхронизирующей цепочке, а не 2, как положено.

Quote

Как можно без асинхронщины натянуть на 18МГц при клоке в 50МГц?

Чтобы нормально и стабильно работало - боюсь, что никак. О чем сразу и сказал. Соотношение периодов - 56 нс и 20 нс - практически не оставляет пространства для маневра в синхронной схеме.

Quote

Полез искать, что это вообще такое. Если правильно понял, это необходимо при асинхронном дизайне. Мне бы пока с синхронным разобраться.

Нет, неправильно вы поняли. Если говорить о временнЫх констрейнтах (а констрейнты, они же ограничения, есть еще и физические - назначение пинов, привязка кусков логики к определенным внутренним блокам и т.п.), то в первую очередь они нужны для синхронных дизайнов, чтобы как раз описать рамки, в которые синтезатор должен загонять синтезируемую схему, чтобы она была синхронной и в ней все было хорошо. Да вообще весь инструментарий разработчика FPGA, который на слуху и с которым вам предстоит работать, предназначен, в основном, для синхронных дизайнов.

 

Вступая на поле асинхронщины, разработчик, в основном, остается без поддержки со стороны констрейнтов и инструментов статического временного анализа (которые как раз эти временнЫе констрейнты и используют в качестве целевых ориентиров), и должен действовать во многом на свой страх и риск. Хорошо еще, что симулятор остается верным товарищем. Но его помощь - только на его собственном поле. Можно попробовать применить аппарат временных констрейнтов для асинхронного дизайна, но результат такого применения интрумента в области, для которой он не предназначен, в общем-то, будет далек от удобства (как минимум). Чтобы описать ограничения для синтезатора, придется ему в констрейнтах расписывать требуемые времена распространения и задержки для массы сигналов (что в варианте для синхронного дизайна выражается всего 5-10 строками, здесь придется подробно расписывать в ... даже не знаю скольких строках, потому как зависит от устройства и его сложности). Для маленьких конструкций это, наверное, при определенной упертости, еще подъемно, но для серьезного устройства - увы...

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


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

6 hours ago, pinchemierda said:

Как можно без асинхронщины натянуть на 18МГц при клоке в 50МГц?

Не надо ничего "натягивать", spi slave должен работать от входного клока 18МГц, а 50МГц не использовать, если в дизайне нет других блоков. Если есть, разобраться с переводами между клоковыми доменами, но это потом, когда заработает spi от клока 18МГц.

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


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

8 минут назад, Leka сказал:

spi slave должен работать от входного клока 18МГц, а 50МГц не использовать

У автора не SPI, а просто последовательный интерфейс — SPI не берёт чужие данные на лету и у него нет никаких счётчиков бит. К тому же, этот интерфейс должен быть синхронным, потому что ТЗ требует после сеанса создать некий сигнал прерывания длиной в 1 такт — стандартный SPI на такое не способен, он не выдаёт лишних тактов после сеанса.

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


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

Но если немного видоизменить ТЗ, и этот тактовый сигнал достаточно стабилен - то это вполне вариант для ТС. Но на его месте я все же воспользовался бы возможностью поучиться чему-то за рамками этой узкой, весьма конкретной задачи (SPI).

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


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

1 hour ago, pinchemierda said:

В идеале SPI 0 slave хотелось бы получить.

Тогда все делать в домене i_clk, прием по always@(posedge i_clk), сдвиг регистра передачи по always@(negedge i_clk).

 

 

Изменено пользователем Leka
было неверно

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


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

Да вот и не получается придумать, как передачу по o_miso сделать в блоке always@(posedge i_clk). Надо как то данные из i_tx_buf защёлкивать в сдвиговый регистр при спаде i_cs и после восьми клоков. С приёмом по линии i_mosi понятнее.

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


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

У меня ошибка была, передача д/б по always@(negedge i_clk). 

i_cs можно использовать только для перевода выхода из Z-состояния в активное, и разрешения клока i_clk.

Защелкивать данные в выходной регистр надо только по клоку i_clk.

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

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


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

Цитата

передача д/б по always@(negedge i_clk). 

это да, понятно уж. Имел в виду, что сложно ограничится одним лишь сигналом в списке чувствительности и одним always блоком при передаче.

Цитата

Защелкивать данные в выходной регистр надо только по клоку i_clk.

А как передавать самый первый бит? Он же сразу должен появиться после спада i_cs. А когда приходит самый первый фронт i_clk он уже должен быть выставлен на выходе o_miso.

Прошу прощения, вы про выходной регистр. С ним то понятно всё и проблем нет.

Вопрос именно про то, как защёлкивать во входной сдвиговый, к седьмому биту которого подключен выход o_miso. 

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


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

Во входной сдвиговый защелкивать по posedge, в выходной по negedge.

o_miso д/б подключен к 7 биту не входного, а выходного регистра. 

Данные для выходного регистра можно брать с входного регистра.

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


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

Выходной регистр у меня это o_rx_buf. В нём появляется то, что пришло по линии i_mosi. Зачем к нему подключать выход o_miso?

i_tx_buf - это входной буфер того что необходимо отправить по линии o_miso. В общем, как этот буфер не называй, всё равно не понятно, как обновлять в нём байт на отправку при спаде i_cs.  

Может поделитесь готовым решением, если не сложно?

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


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

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

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

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

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

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

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

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

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

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