Продолжаю потихоньку осваивать ПЛИС. На сей раз раскурим подключение и объединение модулей.

После тестирования SPI, попытался совместить Atmega8 и EPM240, в надежде сделать генератор: avr задает — плис молотит, что получилось расскажу в ближайшее время. Стало понятно что 240 ячеек это совсем грустно, но даже овладев методом фоторезиста, сделать подобную плату без единого косяка и с первого раза, достаточно трудоемко. В планах было распаять EP3C5E144C8N и на ее основе пилить обзоры дальше. Камень закуплен, но на текущий момент, я отказался от этой затеи, возможно позже вернусь.

Нужно было найти какую то альтернативную готовую железяку, поэтому были прочесаны все возможные варианты, в качестве аргументов были — минимальная обвязка, наличие достаточного количества выходов-штырьков, наличие памяти и много, очень много логических элементов. Итого или Ebay, или Ebay, ничего приличного купить в здешних краях за разумную цену невозможно. В общем зная себя, я все таки решил купить у местных барыг, это личное решение, не следуйте ему. Собственно единственное, что было это DE0 nano. Платка мелкая, на борту Циклон4 с 22к ЛЭ, остальное лирика.
DE0-nano

Это вместо вступления. Теперь перейдем к самому интересному. Ранее мы пробовали делать какие то свои элементы UART, SPI, но на самом деле их не обязательно делать самостоятельно. Какие же варианты существуют? Некоторые вещи можно качать в интернете, желательно с сайта альтеры, примеров там много и они более менее годные. Есть проект OpenCores. Но кое что попроще есть и в комплекте квартуса. К сожалению это не Verilog модули, но об этом далее.

Если вам известно, то в квартусе можно пилить прошивку не только путем описания на Verilog или VHDL. Делается это так, создается новый файл схематика
shematic_quartus

Далее жмакаем правой кнопкой мыши
symbol

Появится окошко библиотеки, в котором нас ожидает куча всяких элементов, начиная от простых, заканчивая сложными.
lib

Например, можно вытащить сдвиговый регистр
595

Собственно можно навытаскивать кучу компонентов, соединить их как надо и все будет работать. Но не всегда это удобно. Если проект не большой, то работать со схемой может показаться удобным. Но вот пример обыкновенной мигалки из первого проекта. На мой взгляд 2 строчки кода понятнее, чем такая схема.
led

В итоге, у нас есть библиотеки, но они написаны не на верилоге. Выходов из этой ситуации несколько. Можно сделать так: ищем нужный нам элемент из схематика, далее жмакаем File — Create/Update — Create HDL Design From current file. Таким образом мы можем конвертнуть элемент в Verilog. Не очень удобно, кроме того зачастую криво конвертится, поэтому нужно тщательно проверять результат. Но главное возможность такая имеется.

Другой вариант — написать свой модуль на верилоге, а окончательно все модули в том числе и библиотечные, соединить в схематике. Это намного более удобно и быстро, но не забываем, что переносимости между разными семействами не будет.

Перед тем как рассказать про еще один способ, неплохо будет рассказать о том, как соединяются все это в «чистом» Verilog. Допустим вы реализовали некий led, с некой логикой, важно то что есть вход clk и выход pin, остальное не важно

module led(clk,pin);
 
input clk;
output reg pin;
 
always
   begin
     pin <= clk;
   end
 
endmodule

Также имеется главный модуль, в котором вы хотите объединить/соединить остальные.

module m_test(clock);
input clock;
 
endmodule

Допустим наша цель подключить ко входу clock вход clk. Делается это так:

module m_test(clock);
input clock;
 
led ld(.clk(clock));
 
endmodule

main

led — это имя исходного модуля, ld — это произвольное имя элемента, ибо если нужно будет подключить одинаковых модулей, их нужно как то различать, clk это нога led, clock это нога m_test т.е. куда соединяем.

Чтобы было совсем понятно, добавим еще один

module m_test(clock);
input clock;
 
led ld(.clk(clock));
led ldd(.clk(clock));
 
endmodule

ldd

Таким образом можно все упаковывать в одну кучу. Но вернемся к нашей проблеме. Есть еще один способ, если хочется юзать Verilog и либу схематика, находите имя символа схематика, запоминаете его ноги и тупо делаете так:

module m_test(clock, port);
input clock;
output port;
 
dff hc(.d(clock), .q(port));
 
endmodule

т.е. совершенно не парясь в верилоговский файл запихиваете символ из схематика, причем больше никаких телодвижений не нужно, все компилится как надо, dff это библиотечный триггер.
trig

Ну и пример совмещения. Используем нашу FPGA просто как обычную логику, допустим нам нужно подключить светодиоды через сдвиговый регистр. Для управления микроконтроллер Atmega8. Вставляем регистр без защелки 74164(можно конечно и 595). Увы цифры в именах использовать нельзя, поэтому сохраним его в папке проекта под именем hc74164.
74164

Дважды щелкаем по нему
74164_2

И на схемке подправим имя. Заодно можно выкинуть разрешающий вход B он не шибко нужен.
hc74164

Главный модуль напишем на Verilog, управлять будем по SPI, поэтому входные сигналы: data это MOSI, clock — CLK. ss — сброс регистра. Принимаем число по SPI от микроконтроллера, загоняем его в сдвиговый регистр. Выход регистра это восьмибитный порт со светодиодами.

module m_test(clock, led_port, data, ss);
input clock;
input data;
input ss;
output [7:0]led_port;
 
hc74164 hc(.CLK(clock), .A(data),
.QA(led_port[0]), .QB(led_port[1]), .QC(led_port[2]),
.QD(led_port[3]), .QE(led_port[4]), .QF(led_port[5]),
.QG(led_port[6]), .QH(led_port[7]), .CLRN(ss));
 
endmodule

sch

Со стороны микроконтроллера — посылаем число по SPI, ждем 0.5с увеличиваем число и так до 254, после начинаем заново с нуля. Перед каждой отправкой сбрасываем регистр.

#include <mega8.h>
#include <delay.h>
#include <spi.h>
 
void main(void)
{
// Declare your local variables here
char x=0;
 
// Input/Output Ports initialization
// Port B initialization
// Function: Bit7=In Bit6=In Bit5=Out Bit4=In Bit3=Out Bit2=Out Bit1=In Bit0=In 
DDRB=(0<<DDB7) | (0<<DDB6) | (1<<DDB5) | (0<<DDB4) | (1<<DDB3) | (1<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit7=T Bit6=T Bit5=0 Bit4=T Bit3=0 Bit2=0 Bit1=T Bit0=T 
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);
 
// SPI initialization
// SPI Type: Master
// SPI Clock Rate: 2000,000 kHz
// SPI Clock Phase: Cycle Start
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=(0<<SPIE) | (1<<SPE) | (0<<DORD) | (1<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (0<<SPR0);
SPSR=(0<<SPI2X);
 
 
while (1)
      {
        if(x <254) x++;
        else x = 0;
 
        spi(x);
        delay_ms(500); 
        PORTB.2=0;
        #asm("nop");
        PORTB.2=1;
 
      }
}

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

Результат:

Если подвести итог, лучше конечно все модули писать на Verilog, ибо сегодня Altera, завтра Xilinx или еще что то. Но если нужно побыстрому что то проверить, то можно скрестить бульдога с носорогом.

Один комментарий: Объединение модулей Verilog

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Последние комментарии
  • Загрузка...
Счетчик
Яндекс.Метрика