fpga项目 : 数码管显示 - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki

1)数码管静态显示

  • 每500ms切换一次显示内容
  • 注意我们的数码管极性与野火的相反,我们的sel为1表示灭,为0表示亮。因此我们的sel[3:0]初始化为4'b1111,然后从4'b1110开始shift。
module segment_static
(
    input sys_clk,
    input sys_rst,
	output reg [3:0] sel,
	output reg [7:0] seg
);

parameter FCLK=27_000_000;
//parameter FCLK=27_00;
parameter CNT_500MS=0.5*FCLK-1;
parameter   SEG_0 = 8'b1100_0000,   SEG_1 = 8'b1111_1001,
            SEG_2 = 8'b1010_0100,   SEG_3 = 8'b1011_0000,
            SEG_4 = 8'b1001_1001,   SEG_5 = 8'b1001_0010,
            SEG_6 = 8'b1000_0010,   SEG_7 = 8'b1111_1000,
            SEG_8 = 8'b1000_0000,   SEG_9 = 8'b1001_0000,
            SEG_A = 8'b1000_1000,   SEG_B = 8'b1000_0011,
            SEG_C = 8'b1100_0110,   SEG_D = 8'b1010_0001,
            SEG_E = 8'b1000_0110,   SEG_F = 8'b1000_1110;
parameter   IDLE  = 8'b1111_1111;   //不显示状态


assign sys_rst_n=~sys_rst;

reg [23:0] cnt;
reg cnt_flag;
reg [3:0] num;


//cnt
always @(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==0)
		cnt<=0;
	else if(cnt==CNT_500MS)
		cnt<=0;
	else
		cnt<=cnt+1;

//cnt_flag
always @(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==0)
		cnt_flag<=0;
	else if(cnt==CNT_500MS-1)
		cnt_flag<=1;
	else
		cnt_flag<=0;

//num
always @(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==0)
		num<=0;
	else if(cnt_flag) begin
		if(num==4'hf)
			num<=0;
		else
			num<=num+1;
	end

//sel
always @(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==0)
		sel<=4'b1111;
	else
		sel<=4'b0000;

//seg
always @(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==0)
		seg<=IDLE;
	else if(cnt_flag)
		case(num)
			0: seg<=SEG_0;
			1: seg<=SEG_1;
			2: seg<=SEG_2;
			3: seg<=SEG_3;
			4: seg<=SEG_4;
			5: seg<=SEG_5;
			6: seg<=SEG_6;
			7: seg<=SEG_7;
			8: seg<=SEG_8;
			9: seg<=SEG_9;
			10: seg<=SEG_A;
			11: seg<=SEG_B;
			12: seg<=SEG_C;
			13: seg<=SEG_D;
			14: seg<=SEG_E;
			15: seg<=SEG_F;
			default: seg<=IDLE;
	endcase

endmodule

2)数码管动态显示

1.刷新时间为1ms一个数码管
2.初始显示内容为1423
3.每200ms显示内容轮换1次
4.使用了函数
5.使用了2维数组
6.设计了通用计数器模块

//通用计数器模块
module counter
#(
	parameter CNT_MAX=27_000_000-1,
	parameter NBITS=24
)
(
    input sys_clk,
    input sys_rst,
	input cnt_flag_i,
	output reg cnt_flag_o,
	output reg [NBITS-1:0] cnt
);

assign sys_rst_n=~sys_rst;

//cnt
always @(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==0)
		cnt<=0;
	else if(cnt_flag_i) begin
		if(cnt==CNT_MAX)
			cnt<=0;
		else
			cnt<=cnt+1;
	end

//cnt_flag_o
always @(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==0)
		cnt_flag_o<=0;
	else if(cnt_flag_i && cnt==CNT_MAX)
		cnt_flag_o<=1;
	else
		cnt_flag_o<=0;

endmodule

//正式代码模块
module segment_dynamic
(
    input sys_clk,
    input sys_rst,
	output reg [3:0] sel,
	output reg [7:0] seg
);

parameter FCLK=27_000_000;
parameter CNT_200MS=0.2*FCLK-1;
parameter CNT_1MS=0.001*FCLK-1;

parameter   SEG_0 = 8'b1100_0000,   SEG_1 = 8'b1111_1001,
            SEG_2 = 8'b1010_0100,   SEG_3 = 8'b1011_0000,
            SEG_4 = 8'b1001_1001,   SEG_5 = 8'b1001_0010,
            SEG_6 = 8'b1000_0010,   SEG_7 = 8'b1111_1000,
            SEG_8 = 8'b1000_0000,   SEG_9 = 8'b1001_0000,
            SEG_A = 8'b1000_1000,   SEG_B = 8'b1000_0011,
            SEG_C = 8'b1100_0110,   SEG_D = 8'b1010_0001,
            SEG_E = 8'b1000_0110,   SEG_F = 8'b1000_1110;
parameter   IDLE  = 8'b1111_1111;   //不显示状态


assign sys_rst_n=~sys_rst;

reg [3:0] my_array [0:3];  //显示内容
//initial begin
//  my_array[0] = 3;
//  my_array[1] = 2;
//  my_array[2] = 4;
//  my_array[3] = 1;
//end

counter #(.CNT_MAX(CNT_200MS),.NBITS(24)) u_counter_200MS
(
    .sys_clk(sys_clk),
    .sys_rst(sys_rst),
	.cnt_flag_i(1'b1),
	.cnt_flag_o(cnt_flag_o1)
);

counter #(.CNT_MAX(CNT_1MS),.NBITS(16)) u_counter_1MS
(
    .sys_clk(sys_clk),
    .sys_rst(sys_rst),
	.cnt_flag_i(1'b1),
	.cnt_flag_o(cnt_flag_o2)
);

wire [1:0] num_1ms;
counter #(.CNT_MAX(3),.NBITS(2)) u_counter_1MS_NUM
(
    .sys_clk(sys_clk),
    .sys_rst(sys_rst),
	.cnt_flag_i(cnt_flag_o2),
	.cnt(num_1ms)
);

//sel
always @(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==0)
		sel<=4'b1111;
	else if(cnt_flag_o2)
		case(num_1ms)
			0:sel<=4'b0111;
			1:sel<=4'b1011;
			2:sel<=4'b1101;
			3:sel<=4'b1110;
			default: sel<=4'b1111;
		endcase

//seg
always @(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==0)
		seg<=IDLE;
	else if(cnt_flag_o2)
//		case(num_1ms)
//			0: seg<=SEG_0;
//			1: seg<=SEG_1;
//			2: seg<=SEG_2;
//			3: seg<=SEG_3;
//			default: seg<=IDLE;
//	endcase
        seg<=get_seg(my_array[num_1ms]);   //索引数组,再调用函数做映射(这里函数的作用:相当于hash表)

function [7:0] get_seg;
    input   [3:0] dec_in;
    case(dec_in)
        0: get_seg=SEG_0;
        1: get_seg=SEG_1;
        2: get_seg=SEG_2;
        3: get_seg=SEG_3;
        4: get_seg=SEG_4;
        5: get_seg=SEG_5;
        6: get_seg=SEG_6;
        7: get_seg=SEG_7;
        8: get_seg=SEG_8;
        9: get_seg=SEG_9;
    endcase
endfunction


//每200ms更新一次显示内容
always @(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n==0) begin
        my_array[0] = 3;
        my_array[1] = 2;
        my_array[2] = 4;
        my_array[3] = 1;
    end
    else if(cnt_flag_o1) begin
        my_array[0]<=my_array[3];
        my_array[1]<=my_array[0];
        my_array[2]<=my_array[1];
        my_array[3]<=my_array[2];
    end

endmodule
endmodule

3) tang nano-20k 扩展板引脚

IO_LOC "sys_clk" 10;
IO_LOC "sys_rst" 4;
//IO_LOC "sys_rst_n" 52;
//IO_PORT "sys_rst_n" PULL_MODE=UP

IO_LOC "sel[3]" 76;
IO_LOC "sel[2]" 80;
IO_LOC "sel[1]" 42;
IO_LOC "sel[0]" 41;
IO_LOC "seg[0]" 56;
IO_LOC "seg[1]" 54;
IO_LOC "seg[2]" 51;
IO_LOC "seg[3]" 48;
IO_LOC "seg[4]" 55;
IO_LOC "seg[5]" 49;
IO_LOC "seg[6]" 86;
IO_LOC "seg[7]" 79;