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;