Часы на Verilog — различия между версиями
(→Pmod) |
(→Pmod) |
||
| (не показана 1 промежуточная версия 1 участника) | |||
| Строка 45: | Строка 45: | ||
[[File:Симисегментный индикатор.jpg|800px]] | [[File:Симисегментный индикатор.jpg|800px]] | ||
| − | <br/> На данном ниже рисунке показана схема подключения катодов и анодов. Из этой схемы наглядно видно, что для того, чтобы зажечь определенный сегмент на одном из индикаторов необходимо подать на соответствующий катод и соответствующий анод низкий уровень. | + | <br/> На данном ниже рисунке показана схема подключения катодов и анодов. Из этой схемы наглядно видно, что для того, чтобы зажечь определенный сегмент на одном из индикаторов необходимо подать на соответствующий катод и соответствующий анод низкий уровень.<br/> |
| − | [[File:Работа индикатора.jpg]] | + | [[File:Работа индикатора.jpg|350px]] |
<br/> На рисунке ниже показано, на какие выводы необходимо подать низкий уровень, чтобы зажечь необходимый сегмент | <br/> На рисунке ниже показано, на какие выводы необходимо подать низкий уровень, чтобы зажечь необходимый сегмент | ||
[[File:Индикатор.jpg]] | [[File:Индикатор.jpg]] | ||
| Строка 279: | Строка 279: | ||
<br/>Высокий уровень(на вход подана 1)<br/> | <br/>Высокий уровень(на вход подана 1)<br/> | ||
[[File:RTOScreenshot_2014-12-22_0_122926.png|500px]] | [[File:RTOScreenshot_2014-12-22_0_122926.png|500px]] | ||
| − | <br/>Низкий уровень(на вход | + | <br/>Низкий уровень(на вход подан 0)<br/> |
[[File:RTOScreenshot_2014-12-22_1_123056.png|500px]] | [[File:RTOScreenshot_2014-12-22_1_123056.png|500px]] | ||
<br/>--[[Участник:Belyanushkin|Belyanushkin]] ([[Обсуждение участника:Belyanushkin|обсуждение]]) 00:20, 25 ноября 2014 (MSK) | <br/>--[[Участник:Belyanushkin|Belyanushkin]] ([[Обсуждение участника:Belyanushkin|обсуждение]]) 00:20, 25 ноября 2014 (MSK) | ||
Текущая версия на 22:20, 22 декабря 2014
Содержание |
[править] Введение
Для освоения программирования ПЛИС на языке Verilog была поставлена задача написания программы смысл которой заключается в подсчете времени нажатия на кнопку.
[править] Подзадачи
1. Установка программы ISE Design Suite 14.7 на ОС Windows 8.1.
2. Написание простых программ для понимания языка Verilog:
- Счетчик нажатий, выполняющий вывод значений в двоичной системе на диоды;
- Программа для работы нескольких семисегментных индикаторов.
3. Синтез этих программ для того, чтобы решить поставленную задачу.
4. Для отработки навыков реализовать часы.
Реализация всех программ производилась на ПЛИС Xilinx Spartan-6 на отладочной плате DIGILENT NEXYS 3
[править] Проблемы в ходе выполнения подзадач
В ходе решения подзадач возникла проблема с установкой программы ISE Design Suite 14.7 на ОС Windows 8.1.
Проблема заключается в зависании программы при создании нового проекта.
Проблема была решается следующим путем:
Шаг 1: зайти в директорию: C:\Xilinx\14.5\ISE_DS\ISE\lib\nt64
Шаг 2: переименовать файл libPortability.dll в libPortability.dll.orig
Шаг 3: переименовать файл libPortabilityNOSH.dll в libPortability.dll
Шаг 4: скопировать файл libPortability.dll <ctrl+c>
Шаг 5: зайти в директорию C:\Xilinx\14.5\ISE_DS\common\lib\nt64
Шаг 6: вставить файл из шага 4 <libPortability.dll > в данную директорию
Оригинал статьи про проблемы с работой I SE Design Suite 14.7 на ОС Windows 8.1 находится по следующей ссылке
[1]
[править] Описание реализации счетчика времени нажатия кнопки
convert: no images defined `/tmp/transform_1579611d70de-1.jpg' @ error/convert.c/ConvertImageCommand/3044.
Основными частями реализации являются счетчики:
- счетчик суммы времени нажатия до одной секунды;
- счетчик времени нажатий в секундах;
- счетчики для работы семисегментного индикатора.
Алгоритм работы счетчика таков:
1. При нажатии на кнопку происходит начинается счет тактовых сигналов;
2. При достижении количества сигналов, равного 10^8 в счетчике суммы прибавляется одна секунда, счетчик импульсов сбрасывается в ноль;
3. Далее с регистра, содержащего информацию о количестве секунд, эти значению передаются на дальнейшую обработку для передачи на семисегментные индикаторы.
4. Реализация работы семисегментных индикаторов была произведена с помощью циклов.
Подробнее про работу с семисегментными индикаторами.
Так как индикаторов 4 а катоды к ним общие, то принято было работать по следующему алгоритму. Есть 2 счетчика. Один счетчик считает количество тактовых сигналов. Когда это количество становится равным 200000 то на втором счетчике прибавляется единица. В зависимости от значения на втором счетчике выбирается тот анод, на котором будет низкий уровень и значит загорится этот индикатор. Так как время циклов очень мало, то мы мы не замечаем мигание индикаторов. Второй счетчик в схеме имеет 2 разряда, поэтому сбрасывать его нет необходимости.
convert: no images defined `/tmp/transform_6ad196a76197-1.jpg' @ error/convert.c/ConvertImageCommand/3044.
На данном ниже рисунке показана схема подключения катодов и анодов. Из этой схемы наглядно видно, что для того, чтобы зажечь определенный сегмент на одном из индикаторов необходимо подать на соответствующий катод и соответствующий анод низкий уровень.
convert: no images defined `/tmp/transform_f9fd66b4830b-1.jpg' @ error/convert.c/ConvertImageCommand/3044.
На рисунке ниже показано, на какие выводы необходимо подать низкий уровень, чтобы зажечь необходимый сегмент
Текст реализации счетчика времени нажатия
module main(
input clk,
input BTNS, // кнопка
output [3:0] AN, // выводы к анодам для переключения семисегментных индикаторов
output [7:0] ind // выводы к катодам семисегментного индикатора
);
reg [3:0] assist_AN; // вспомогательный регистр для анодов семисегментных индикаторов
reg [7:0] assist_ind; // вспомогательный регистр для катодов семисегментного индикатора
reg [26:0] sum; // накапливаемое значение суммы для регистрации нажатия
reg [7:0] assist_ld; // сумматор времени нажатия кнопки
reg [3:0] nul_r; // младший сегмент индикатора
reg [3:0] first_r; // второй сегмент индикатора
reg [3:0] second_r; // третий сегмент индикатора
reg [17:0] counter; // регистр, хранящий время работы семисегментного индикатора
reg [1:0] c; // регистр указателя номера семисегментного индикатора
always @(posedge clk)
begin
if (BTNS) // нажатие кнопки
sum <= sum + 1'b1;
else
sum <= 27'd0;
if (sum >= 27'd100000000) // суммирование времени нажатия до 1 секунды
begin
assist_ld <= assist_ld + 1'b1; // счет количества секунд
sum <= 27'd0;
end
nul_r <= assist_ld % 10; // значение первого семисегментного индикатора
first_r <= (assist_ld % 100 - nul_r)/10; // значение второго индикатора
second_r <= assist_ld / 100; // значение третьего индикатора
counter <= counter + 1'b1;
if (counter == 17'd200000) // цикл работы семисегметных индикаторов
begin
c <= c + 1'b1;
counter <= 17'd0;
end
if (c == 2'b00) // первый семисегментный индикатор
begin
assist_AN <= 4'b1110; // значение анодов
case (nul_r)
4'd0: assist_ind <= 8'b00000011; // значения катодов
4'd1: assist_ind <= 8'b10011111;
4'd2: assist_ind <= 8'b00100101;
4'd3: assist_ind <= 8'b00001101;
4'd4: assist_ind <= 8'b10011001;
4'd5: assist_ind <= 8'b01001001;
4'd6: assist_ind <= 8'b01000001;
4'd7: assist_ind <= 8'b00011111;
4'd8: assist_ind <= 8'b00000001;
4'd9: assist_ind <= 8'b00001001;
default: assist_ind <= 8'b11111111;
endcase
end
if (c == 2'b01) // второй семисегментный индикатор
begin
assist_AN <= 4'b1101;
case (first_r)
4'd0: assist_ind <= 8'b00000011;
4'd1: assist_ind <= 8'b10011111;
4'd2: assist_ind <= 8'b00100101;
4'd3: assist_ind <= 8'b00001101;
4'd4: assist_ind <= 8'b10011001;
4'd5: assist_ind <= 8'b01001001;
4'd6: assist_ind <= 8'b01000001;
4'd7: assist_ind <= 8'b00011111;
4'd8: assist_ind <= 8'b00000001;
4'd9: assist_ind <= 8'b00001001;
default: assist_ind <= 8'b11111111;
endcase
end
if (c == 2'b10) // третий семисегментный индикатор
begin
assist_AN <= 4'b1011;
case (second_r)
4'd0: assist_ind <= 8'b00000011;
4'd1: assist_ind <= 8'b10011111;
4'd2: assist_ind <= 8'b00100101;
default: assist_ind <= 8'b11111111;
endcase
end
end
assign AN = assist_AN; // значение на выходах к аноду равно значению вспомогательных регистров
assign ind = assist_ind; // значение на выходах к катоду равно значению вспомогательных регистров
endmodule
ucf файл с описанием портов ввода-вывода
NET "clk" LOC = V10; NET "BTNS" LOC = B8; NET "AN[0]" LOC = N16; NET "AN[1]" LOC = N15; NET "AN[2]" LOC = P18; NET "AN[3]" LOC = P17; NET "ind[0]" LOC = M13; NET "ind[1]" LOC = L14; NET "ind[2]" LOC = N14; NET "ind[3]" LOC = M14; NET "ind[4]" LOC = U18; NET "ind[5]" LOC = U17; NET "ind[6]" LOC = T18; NET "ind[7]" LOC = T17;
[править] Реализация часов
Реализация часов отличается от счетчика времени нажатия незначительно. Здесь отсутствует кнопка. Отличие в подсчете времени здесь состоит в том, что здесь счетчик времени представляет собой счетчики минут и секунд. Счет происходит до 59 минут 59 секунд, после чего все сбрасывается. В предыдущем случае счет шел до 255 секунд.
Текст реализации
module main(
input clk,
output [3:0] AN,
output [7:0] ind
);
reg [3:0] assist_AN;
reg [7:0] assist_ind;
reg [26:0] sum;
reg [5:0] seconds;
reg [5:0] minutes;
reg [3:0] seconds_jr; // регистр хранения значения первой цифры в счетчике секунд
reg [3:0] seconds_sr; // регистр хранения значения второй цифры в счетчике секунд
reg [3:0] minutes_jr; // регистр хранения значения первой цифры в счетчике минут
reg [3:0] minutes_sr; // регистр хранения значения второй цифры в счетчике минут
reg [17:0] counter;
reg [1:0] c;
always @(posedge clk)
begin
sum <= sum + 1'b1;
if (sum >= 27'd100000000)
begin
seconds <= seconds + 1'b1; //счетчик секунд
sum <= 27'd0;
end
if (seconds == 6'd60)
begin
minutes <= minutes +1'b1; // счетчик минут
seconds <= 6'd0;
end
if (minutes == 6'd60)
minutes <= 6'd0;
seconds_jr <= seconds % 10; // вычисление значения первой цифры в счетчике секунд
seconds_sr <= seconds/10; // вычисление значения второй цифры в счетчике секунд
minutes_jr <= minutes % 10; // вычисление значения первой цифры в счетчике минут
minutes_sr <= minutes/10; // вычисление значения второй цифры в счетчике минут
counter <= counter + 1'b1;
if (counter == 17'd200000)
begin
c <= c + 1'b1;
counter <= 17'd0;
end
if (c == 2'b00)
begin
assist_AN <= 4'b1110;
case (seconds_jr)
4'd0: assist_ind <= 8'b00000011;
4'd1: assist_ind <= 8'b10011111;
4'd2: assist_ind <= 8'b00100101;
4'd3: assist_ind <= 8'b00001101;
4'd4: assist_ind <= 8'b10011001;
4'd5: assist_ind <= 8'b01001001;
4'd6: assist_ind <= 8'b01000001;
4'd7: assist_ind <= 8'b00011111;
4'd8: assist_ind <= 8'b00000001;
4'd9: assist_ind <= 8'b00001001;
default: assist_ind <= 8'b11111111;
endcase
end
if (c == 2'b01)
begin
assist_AN <= 4'b1101;
case (seconds_sr)
4'd0: assist_ind <= 8'b00000011;
4'd1: assist_ind <= 8'b10011111;
4'd2: assist_ind <= 8'b00100101;
4'd3: assist_ind <= 8'b00001101;
4'd4: assist_ind <= 8'b10011001;
4'd5: assist_ind <= 8'b01001001;
default: assist_ind <= 8'b11111111;
endcase
end
if (c == 2'b10)
begin
assist_AN <= 4'b1011;
case (minutes_jr)
4'd0: assist_ind <= 8'b00000010;
4'd1: assist_ind <= 8'b10011110;
4'd2: assist_ind <= 8'b00100100;
4'd3: assist_ind <= 8'b00001100;
4'd4: assist_ind <= 8'b10011000;
4'd5: assist_ind <= 8'b01001000;
4'd6: assist_ind <= 8'b01000000;
4'd7: assist_ind <= 8'b00011110;
4'd8: assist_ind <= 8'b00000000;
4'd9: assist_ind <= 8'b00001000;
default: assist_ind <= 8'b11111111;
endcase
end
if (c == 2'b11)
begin
assist_AN <= 4'b0111;
case (minutes_sr)
4'd0: assist_ind <= 8'b00000011;
4'd1: assist_ind <= 8'b10011111;
4'd2: assist_ind <= 8'b00100101;
4'd3: assist_ind <= 8'b00001101;
4'd4: assist_ind <= 8'b10011001;
4'd5: assist_ind <= 8'b01001001;
default: assist_ind <= 8'b11111111;
endcase
end
end
assign AN = assist_AN;
assign ind = assist_ind;
endmodule
Здесь ucf файл отличается только отсутствием кнопки BTNS
[править] Pmod
Для понимания того, какие уровни сигнала на выходе Pmod на один из его выходов были поданы высокий и низкий уровни, после чего к этому выходу был подключен осциллограф. Осциллограммы представлены ниже.
Pmod connectors
Высокий уровень(на вход подана 1)
Низкий уровень(на вход подан 0)
--Belyanushkin (обсуждение) 00:20, 25 ноября 2014 (MSK)