1

Динамическая индикация на 7-сегментном индикаторе под управлением ПЛИС Altera

В качестве эксперимента у меня получилось написать динамическую индикацию для 6-разрядного 7-сегментного индикатора.

Подробнее читаем под катом…

Итак, что нужно для того, чтобы увидеть, как работает динамическая индикация? Правильно! Индикатор. Он есть на моей отладочной плате и уже подключен к ПЛИС. Чтобы им можно было управлять, нужно нарисовать и сконфигурировать пины ПЛИС. Как это сделано, видно на картинке выше.
Саму внутреннюю структуру ПЛИС я разбил на три блока: собственно, динамическая индикация; 24-разрядный двоичный счетчик; и предделитель для последнего.

Собственно сам блок динамической индикации на языке Verilog выглядит так:

module Dynamic (
       input clk,
       input [23:0] input_bus,     // Входная шина
       output reg [7:0] digit,     // Регистр значения разряда 7-сегментной матрицы
       output reg [5:0] selects    // Регистр  номера разряда 7-сегментной матрицы 
       );
	 
reg [3:0] current_digit;         // Регистр отображаемого разряда 
wire [3:0] digits [6];           // Шесть разрядов индикатора		
reg [19:0] div;                  // Делитель для строба динамической индикации
reg strob_100hz;                 // Строб динамической индикации

//=================================================================================
//               Разделение входной шины по разрядам
//=================================================================================
assign digits[0] = input_bus [23:20];
assign digits[1] = input_bus [19:16];
assign digits[2] = input_bus [15:12];
assign digits[3] = input_bus [11:8];
assign digits[4] = input_bus [7:4];
assign digits[5] = input_bus [3:0];
//=================================================================================
//               Сдвиг катодов для выборки разрядов для отображения 
//=================================================================================
always @ (posedge clk) begin
    if (strob_100hz) begin
        selects <= {selects [4:0], selects[5]};
    end
end
//=================================================================================
//                     Преобразование в 7-сегментный код
//=================================================================================
always @ (posedge clk) begin
case (current_digit)
0  : digit <= 8'b11000000;
1  : digit <= 8'b11111001;
2  : digit <= 8'b10100100;
3  : digit <= 8'b10110000;
4  : digit <= 8'b10011001;
5  : digit <= 8'b10010010;
6  : digit <= 8'b10000010;
7  : digit <= 8'b11111000;
8  : digit <= 8'b10000000;
9  : digit <= 8'b10010000;
10 : digit <= 8'b10001000;
11 : digit <= 8'b10000011;
12 : digit <= 8'b11000110;
13 : digit <= 8'b10100001;
14 : digit <= 8'b10000110;
15 : digit <= 8'b10001110;
endcase
end
//=================================================================================
//            Делитель на 100000 для тактирования динамической индикации
//=================================================================================
always @ (posedge clk) begin
    if (div == 100000) begin
        div <= 0;
        strob_100hz <= 1;
    end else begin
        strob_100hz <= 0;
        div <= div+1;
    end
end
//=================================================================================
//                   Последовательное отображение 6 разрядов
//=================================================================================
always @ (posedge clk) begin
	reg [2:0] i;
	for (i=0; i<6; i=i+1) if (!selects[i]) current_digit= digits[i];
end
//=================================================================================
//                     Инициализация при включени питания
//=================================================================================
initial begin
	selects <= 6'b011111;
	digit <= 8'b11111111;
end

endmodule


Небольшое лирическое отступление: не забываем, что в ПЛИС каждая строчка кода может выполняться одновременно еще с кучей таких же строчек. Не знаю, как кого, а меня это постоянно удивляет: слишком уж привык писать под микроконтроллеры, у которых выполнить одновременно несколько действий — сложно, а подчас, даже невозможно. :)

Описывать пошагово каждую строчку кода вряд ли имеет смысл: комментарии и так все говорят. Главный принцип работы блока:
на вход подаем 24-разрядную шину данных, которую потом разбиваем на 4-битные нибблы. Последние циклически отображаем на 7-сегментниках, преобразовав их в нужный код.

Чтобы было, что отображать, я написал примитивный 24-разрядный счетчик:


module Counter (
       input clk,
       input rst,
       output reg [23:0] output_bus
       );                                  

always@(posedge clk) begin
    if (!rst) begin
        output_bus <= 0;
    end else begin
        output_bus <= output_bus + 1;
    end
end


endmodule


Если подать на его вход тактовый сигнал (а он на моей плате 50МГц), то ничего путного мы не увидим — слишком уж большая частота. Поэтому в схему введен делитель частоты:


module Divider (
       input clk,
       output reg strobe
       );

reg [23:0] div;
		 
always @ (posedge clk) begin
    if (div == 10000000) begin
        div <= 0;
        strobe <= 1;
    end else begin
        strobe <= 0;
        div <= div+1;
    end
end

endmodule


Как собирать проект, компилировать его и зашивать в ПЛИС, можно прочесть в моем прошлом отчете.

Результат компиляции выглядит так:


Дальше буду играться с ModelSim и с логическим анализатором. По результатам будет очередной отчет.

0 comments

Only registered users can comment.