1. 程式人生 > >fpga學習之數碼管顯示

fpga學習之數碼管顯示

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

模擬波形
modelsim模擬波形圖
大家在位選部分也可以使用狀態機來實現,歡迎大家來學習討論。