fpga學習之數碼管顯示
阿新 • • 發佈:2018-12-20
1、設計需求:
設計一個數碼管驅動電路,是數碼管能夠顯示任意六位數。
2、數碼管原理分析:
現在的數碼管基本都是八段式的,也就是說由八個發光二極體組成的。如圖一所示,這是單個數碼管的原理圖
我們需要二極體顯示數字,只需要控制二極體的亮滅就行。以共陽極數碼管為例(給二極體低電平為點亮二極體),如圖二所示顯示數字與段選關係
數碼管位選如圖三所示,Y0~Y7表示8位數碼管。1為數碼管有效
程式碼功能實現部分:
module seg_6(
Clk,
Rst_n,
En,
disp_data,
sel,
seg
);
input Clk; //50M
input Rst_n;
input En; //數碼管顯示使能,1使能,0關閉
input [23:0]disp_data;
output [5:0] sel;//數碼管位選(選擇當前要顯示的數碼管)
output reg [6:0] seg;//數碼管段選(當前要顯示的內容)
reg [14:0]divider_cnt;//25000-1
reg clk_1K;
reg [5:0]sel_r;
reg [3:0]data_tmp;//資料快取
// 分頻計數器計數模組
[email protected](posedge Clk or negedge Rst_n)
if(!Rst_n)
divider_cnt <= 15'd0;
else if(!En)
divider_cnt <= 15'd0;
else if(divider_cnt == 24999)
divider_cnt <= 15'd0;
else
divider_cnt <= divider_cnt + 1'b1;
//1K掃描時鐘生成模組
[email protected](posedge Clk or negedge Rst_n)
if(!Rst_n)
clk_1K <= 1'b0;
else if(divider_cnt == 24999)
clk_1K <= ~clk_1K;
else
clk_1K <= clk_1K;
//6位迴圈移位暫存器,實現數碼管的位選
[email protected](posedge clk_1K or negedge Rst_n)
if(!Rst_n)
sel_r <= 6'b00_0001;
else if(sel_r == 6'b10_0000)
sel_r <= 6'b00_0001;
else
sel_r <= sel_r << 1;
[email protected](*)
case(sel_r)
6'b00_0001:data_tmp = disp_data[3:0];
6'b00_0010:data_tmp = disp_data[7:4];
6'b00_0100:data_tmp = disp_data[11:8];
6'b00_1000:data_tmp = disp_data[15:12];
6'b01_0000:data_tmp = disp_data[19:16];
6'b10_0000:data_tmp = disp_data[23:20];
default:data_tmp = 4'b0000;
endcase
[email protected](*)
case(data_tmp)
4'h0:seg = 7'b1000000;
4'h1:seg = 7'b1111001;
4'h2:seg = 7'b0100100;
4'h3:seg = 7'b0110000;
4'h4:seg = 7'b0011001;
4'h5:seg = 7'b0010010;
4'h6:seg = 7'b0000010;
4'h7:seg = 7'b1111000;
4'h8:seg = 7'b0000000;
4'h9:seg = 7'b0010000;
4'ha:seg = 7'b0001000;
4'hb:seg = 7'b0000011;
4'hc:seg = 7'b1000110;
4'hd:seg = 7'b0100001;
4'he:seg = 7'b0000110;
4'hf:seg = 7'b0001110;
endcase
assign sel = (En)?sel_r:6'b00_0000;
endmodule
程式碼模擬部分
`timescale 1ns/1ns
`define clk_period 20
module seg_6_tb;
reg Clk; //50M
reg Rst_n;
reg En; //數碼管顯示使能,1使能,0關閉
reg [23:0]disp_data;
wire [5:0] sel;//數碼管位選(選擇當前要顯示的數碼管)
wire [6:0] seg;//數碼管段選(當前要顯示的內容)
seg_6 seg_6(
.Clk(Clk),
.Rst_n(Rst_n),
.En(En),
.disp_data(disp_data),
.sel(sel),
.seg(seg)
);
initial Clk = 1;
always#(`clk_period/2) Clk = ~Clk;
initial begin
Rst_n = 1'b0;
En = 1;
disp_data = 24'h123456;
#(`clk_period*20);
Rst_n = 1;
#(`clk_period*20);
#10000000;
disp_data = 24'h876543;
#10000000;
disp_data = 24'h89abcd;
#10000000;
$stop;
end
endmodule
模擬波形
大家在位選部分也可以使用狀態機來實現,歡迎大家來學習討論。