Часы на Verilog

Материал из SRNS
Перейти к: навигация, поиск

Содержание

Введение

Для освоения программирования ПЛИС на языке 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: unable to open image `/app/images/0/0d/_new.jpg': No such file or directory @ error/blob.c/OpenBlob/2641.
convert: no images defined `/tmp/transform_7395d1af657d-1.jpg' @ error/convert.c/ConvertImageCommand/3044.


Основными частями реализации являются счетчики:
- счетчик суммы времени нажатия до одной секунды;
- счетчик времени нажатий в секундах;
- счетчики для работы семисегментного индикатора.
Алгоритм работы счетчика таков:
1. При нажатии на кнопку происходит начинается счет тактовых сигналов;
2. При достижении количества сигналов, равного 10^8 в счетчике суммы прибавляется одна секунда, счетчик импульсов сбрасывается в ноль;
3. Далее с регистра, содержащего информацию о количестве секунд, эти значению передаются на дальнейшую обработку для передачи на семисегментные индикаторы.
4. Реализация работы семисегментных индикаторов была произведена с помощью циклов.

Подробнее про работу с семисегментными индикаторами.
Так как индикаторов 4 а катоды к ним общие, то принято было работать по следующему алгоритму. Есть 2 счетчика. Один счетчик считает количество тактовых сигналов. Когда это количество становится равным 200000 то на втором счетчике прибавляется единица. В зависимости от значения на втором счетчике выбирается тот анод, на котором будет низкий уровень и значит загорится этот индикатор. Так как время циклов очень мало, то мы мы не замечаем мигание индикаторов. Второй счетчик в схеме имеет 2 разряда, поэтому сбрасывать его нет необходимости.

Ошибка создания миниатюры: convert: unable to open image `/app/images/f/f1/_.jpg': No such file or directory @ error/blob.c/OpenBlob/2641.
convert: no images defined `/tmp/transform_66452eb814b3-1.jpg' @ error/convert.c/ConvertImageCommand/3044.


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


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 File:Pmod.jpg
Высокий уровень(на вход подана 1) File:RTOScreenshot_2014-12-22_0_122926.png
Низкий уровень(на вход подана 0) File:RTOScreenshot_2014-12-22_1_123056.png --Belyanushkin (обсуждение) 00:20, 25 ноября 2014 (MSK)

Персональные инструменты
Пространства имён

Варианты
Действия
SRNS Wiki
Рабочие журналы
Приватный файлсервер
QNAP Сервер
Инструменты