Судя по всему прошлый пример, не смотря на простоту идеи получился весьма не удачным. Суть идеи была поделить входную частоту кварца (100МГц), до воспринимаемых человеком 1-2Гц. Вроде как получилось, но осталось больше вопросов, чем ответов, поэтому я решил продолжить изыскания в этой области.

Начнем с вопросов. Оказалось самым сложным сформировать точную задержку. Попытаюсь донести идею. У нас в распоряжении только логика, никаких переменных, циклов и пр. В прошлой статье, я пытался донести, что можно использовать делитель частоты на D триггерах. Но если все время делить частоту пополам, после первого триггера 50Мгц, после второго 25 и т.д. В итоге у нас будет дробная частота, самое близкое к 1Гц это 1,49Гц, на это потребуется 26 D триггеров(делителей). Для компиляции прошлого проекта было «скушано» 62 логических элемента из 240, на мой взгляд это слишком круто, для того чтобы просто помигать диодом.

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

Реализовать это в виде схемы сложно, зато на Verilog написать легко: входная частота osc, счетчик count, выход clk

module reduced_osc (osc, clk);
 
input osc;               // Output of internal osc
output clk;              // Reduced frequency clock
 
reg [25:0] count;
reg clk;
 
initial
begin
count = 0;
clk = 0;
end
 
always @ (posedge osc) begin
count <= count + 1;
if(count == 100)begin
clk <= !clk;
end
end
endmodule

Сразу видно, чем ниже выходная частота, тем больше жрет ресурсов, а если посмотреть RTL схему, то волосы зашевелятся даже там где их нет. Но зато работает точно и исправно. Я запросто намутил себе меандр 1Гц, 10кГц, и 100кГц, поделив соответственно на 50 000 000, 5 000 и 500.
1hz

10khz

100khz

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

Для отсчета секундных промежутков можно тактироваться от часового кварца на 32768Гц, но на мой взгляд весь кайф в том, чтобы все реализовывать внутри плисины, при этом максимально уменьшая габариты конечного устройства. В общем, сделать можно, но следует несколько раз подумать, ибо формирование длинных промежутков времени не та задача, ради которой стоит юзать ПЛИС, микроконтроллер с этим явно справится лучше.

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

Очень важно!!! У платы марсоход 1, некоторые ножки объединены по схеме, по умолчанию не настроенные ножки сидят на земле. Таким образом когда вы включаете ножку и если она объединена с другой, можно устроить коротыш. В общем, не подключенные ножки нужно обязательно настроить как входы (Tri-z). Привязку ножек к сегментам можно посмотреть в Pin planner, резисторы на 100 Ом.

Теперь к прошивке. Если бы мы жили в средние века, инквизиторы наверняка сожгли бы меня на костре, за такой код. В общем понятно, что можно заюзать BCD, как скилл прокачаю, дополню статью. Пока как есть.

module test_timer (osc, clk, e, d, c, b, a, f, g);
 
input osc;               // Output of internal osc
output clk;              // Reduced frequency clock
output e;output d;output c;output b; //ножки сегментов
output a;output f;output g;
 
reg [26:0] count;
reg [3:0] sek;
reg clk;
reg e;reg d;reg c;reg b;reg a;reg f; reg g;
 
initial
begin
count = 0;
clk=0;
e=1;d=1;c=1; b=1;a=1;f=1; g=1;
end
 
always @ (posedge clk) begin
sek <= sek + 1;
if(sek==0)begin
e <= 0; d <= 0; c <= 0; b <= 0;
a <= 0; f <= 0; g <= 1;  
end
if(sek==1)begin
e <= 1; d <= 1; c <= 0; b <= 0;
a <= 1; f <= 1; g <= 1;  
end
if(sek==2)begin 
e <= 0; d <= 0; c <= 1; b <= 0;
a <= 0; f <= 1; g <= 0;  
end
if(sek==3)begin
e <= 1; d <= 0; c <= 0; b <= 0;
a <= 0; f <= 1; g <= 0;  
end
if(sek==4)begin
e <= 1; d <= 1; c <= 0; b <= 0;
a <= 1; f <= 0; g <= 0;  
end
if(sek==5)begin
e <= 1; d <= 0; c <= 0; b <= 1;
a <= 0; f <= 0; g <= 0;  
end
if(sek==6)begin
e <= 0; d <= 0; c <= 0; b <= 1;
a <= 0; f <= 0; g <= 0;  
end
if(sek==7)begin
e <= 1; d <= 1; c <= 0; b <= 0;
a <= 0; f <= 1; g <= 1;  
end
if(sek==8)begin
e <= 0; d <= 0; c <= 0; b <= 0;
a <= 0; f <= 0; g <= 0;  
end
if(sek==9)begin
e <= 1; d <= 0; c <= 0; b <= 0;
a <= 0; f <= 0; g <= 0;
sek<=0;  
end
end
 
always @ (posedge osc) begin  
count <= count + 1;
if(count == 50000000)
begin
clk <= !clk;
count <= 0;
end
end
endmodule

Пояснять тут особо нечего, если секунда 0, то включаем сегменты e, d, c, b, a, f. При этом g выключаем. Когда секунда равна 1, c и b включены, а остальные выключены и т.д. Второй блок это делитель частоты. Собственно все.

Проект кактуса

5 комментариев: Таймер на CPLD

  • Про tri-state на ножки и коротыш написано у марсохода в статье по сборке первого проекта.

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

  • Правильно, что написали про особенность, я не спорю. За плевок в сторону довольно неплохого проекта обидно.

  • Написал помягче дабы не обидеть никого) Мои претензии к первой плате, в моем видении она должна быть другой, вот и все.

  • Светодиодик мигает еще на плате =)

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

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

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