赞
踩
用拨码开关的开闭充当1与0,总的使用4个拨码开关,将其所组成二进制,使用六位数码管最高位进行十进制显示,后四位显示拨码开关所对应的BCD码。
8421码 | 十进制数 |
0000 | 0 |
0001 | 1 |
0010 | 2 |
0011 | 3 |
0100 | 4 |
0101 | 5 |
0110 | 6 |
0111 | 7 |
1000 | 8 |
1001 | 9 |
数码管显示分为静态显示和动态显示,静态显示所有数码管显示相同的数值,动态显示不同数码管显示不同数值。
静态显示:控制数码管需要控制两个信号,位选信号和段选信号。位选信号是独立控制的,用来控制单个数码管的亮灭。段选信号控制数码管显示数值,在电路中六个数码管的段选信号连接在一起,所以在同一时间,位选信号控制点亮的数码管显示的值是相同的。
动态显示:由“人眼视觉暂留”和“数码管余晖效应”,当我们让每个数码管快速轮流显示,当速度快到人眼无法分辨时,我们所看到的数码管就是同时显示了不同的数值。
整个系统分为三个模块:
Top_seg | 顶层模块,连接各模块对应信号 |
data_change | 数据转化模块,将拨码开关对应二进制转化为数字信号 |
Seg_dynamic | 动态数码管扫描模块 |
Data_BCD信号将四个输入转为二进制编码,seg_en信号为控制数码管动态扫描信号,在此次项目中可一直拉高。
在编写过程中,想到时序逻辑,数据会延迟一拍,为了保证数据同步需要编写寄存器,用来寄存数据。
顶层模块
- module top_seg(
- input wire sys_clk ,
- input wire sys_rst_n ,
- input wire key_in_0 ,
- input wire key_in_1 ,
- input wire key_in_2 ,
- input wire key_in_3 ,
-
- output wire [5:0] sel ,
- output wire [7:0] seg
- );
-
- wire [3:0] data_bcd ;
- wire seg_en ;
-
-
- data_change data_change_inst(
- .sys_clk (sys_clk ) ,
- .sys_rst_n (sys_rst_n ),
- .key_in_0 (key_in_0 ),
- .key_in_1 (key_in_1 ),
- .key_in_2 (key_in_2 ),
- .key_in_3 (key_in_3 ),
-
- .data_bcd (data_bcd ),
- .seg_en (seg_en )
- );
-
- seg_dynamic seg_dynamic_inst(
- .sys_clk (sys_clk ),
- .sys_rst_n (sys_rst_n ),
- .data_bcd (data_bcd ),
- .seg_en (seg_en ),
-
- .sel (sel ),
- .seg (seg )
- );
-
- endmodule
数据转化模块:
- module data_change(
- input wire sys_clk ,
- input wire sys_rst_n ,
- input wire key_in_0 ,
- input wire key_in_1 ,
- input wire key_in_2 ,
- input wire key_in_3 ,
-
- output reg [3:0] data_bcd ,
- output reg seg_en
- );
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)begin
- data_bcd <= 4'd0;
- seg_en <= 1'b0;
- end
- else begin
- data_bcd <= {key_in_0,key_in_1,key_in_2,key_in_3};
- seg_en <= 1'b1;
- end
- endmodule
数码管动态扫描模块:
- module seg_dynamic(
- input wire sys_clk ,
- input wire sys_rst_n ,
- input wire [3:0] data_bcd,
- input wire seg_en ,
-
- output reg [5:0] sel ,
- output reg [7:0] seg
- );
- parameter CNT_MAX = 16'd49_999;
-
- reg [24:0] cnt_1ms ;
- reg cnt_flag ;
- reg [2:0] cnt_sel ;
- reg [5:0] sel_reg ;
- reg [3:0] data_reg ;
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- cnt_1ms <= 16'd0;
- else if(cnt_1ms==CNT_MAX)
- cnt_1ms <= 16'd0;
- else
- cnt_1ms <= cnt_1ms + 1'b1;
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- cnt_flag <= 1'b0;
- else if(cnt_1ms==CNT_MAX-1)
- cnt_flag <= 1'b1;
- else
- cnt_flag <= 1'b0;
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- cnt_sel <= 3'd0;
- else if(cnt_flag==1'b1)
- cnt_sel <= cnt_sel + 1'b1;
- else if((cnt_sel==3'd5)&&(cnt_flag==1'b1))
- cnt_sel <= 3'd0;
- else
- cnt_sel <= cnt_sel;
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- sel_reg <= 6'd0 ;
- else case(cnt_sel)
- 3'b000 : sel_reg <= 6'b111_110 ;
- //3'b001 : sel_reg <= 6'b111_101 ;
- 3'b010 : sel_reg <= 6'b111_011 ;
- 3'b011 : sel_reg <= 6'b110_111 ;
- 3'b100 : sel_reg <= 6'b101_111 ;
- 3'b101 : sel_reg <= 6'b011_111 ;
- default sel_reg <= 6'b111_111 ;
- endcase
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- data_reg <= 3'd0 ;
- else case(cnt_sel)
- 3'b000 : data_reg <= data_bcd ;
- //3'b001 : data_reg <= 6'b000_010 ;
- 3'b010 : data_reg <= {4'b00,data_bcd[3]} ;
- 3'b011 : data_reg <= {4'b00,data_bcd[2]} ;
- 3'b100 : data_reg <= {4'b00,data_bcd[1]} ;
- 3'b101 : data_reg <= {4'b00,data_bcd[0]} ;
- default data_reg <= 4'b0000 ;
- endcase
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- seg <= 8'h79 ;
- else case(data_reg)
- 4'd0 : seg <= 8'h3f;
- 4'd1 : seg <= 8'h06;
- 4'd2 : seg <= 8'h5b;
- 4'd3 : seg <= 8'h4f;
- 4'd4 : seg <= 8'h66;
- 4'd5 : seg <= 8'h6d;
- 4'd6 : seg <= 8'h7d;
- 4'd7 : seg <= 8'h07;
- 4'd8 : seg <= 8'h7f;
- 4'd9 : seg <= 8'h6f;
- default seg <= 8'h79 ;
-
- endcase
-
-
- always@(posedge sys_clk or negedge sys_rst_n)
- if(!sys_rst_n)
- sel <= 6'd0;
- else
- sel <= sel_reg;
-
- endmodule
由RTL视图发现该代码有待改进,多路选择部分没有写完整。
- module tb_seg();
-
- reg sys_clk ;
- reg sys_rst_n ;
- reg key_in_0 ;
- reg key_in_1 ;
- reg key_in_2 ;
- reg key_in_3 ;
-
- wire [5:0] sel ;
- wire [7:0] seg ;
-
- initial
- begin
- sys_clk <= 1'b1;
- sys_rst_n <= 1'b0;
- key_in_0 <= 1'b0;
- key_in_1 <= 1'b0;
- key_in_2 <= 1'b0;
- key_in_3 <= 1'b0;
- #20
- sys_rst_n <= 1'b1;
- end
- always#10 sys_clk <= ~sys_clk;
- always#100_0007 key_in_1 <= {$random} % 2;
- always#100_0007 key_in_2 <= {$random} % 2;
- always#100_0007 key_in_3 <= {$random} % 2;
- top_seg top_seg_inst(
- .sys_clk (sys_clk ) ,
- .sys_rst_n (sys_rst_n),
- .key_in_0 (key_in_0),
- .key_in_1 (key_in_1),
- .key_in_2 (key_in_2),
- .key_in_3 (key_in_3),
- .sel (sel) ,
- .seg (seg)
- );
- endmodule
仿真波形主要查看动态数码管扫描模块部分是否正确。
如图所示,用左下方四个拨码开关进行输入,数码管进行输出。
没有系统的跟谁学习,每次做完一个项目不知道下个项目学什么,每次都提前想好吧!
下个项目FPGA部分最后一个项目——摄像头驱动,可以学到:IIC通信协议、SPI通信协议、UART通信、FIFO、SDRAM 等等。
行而不辍,未来可期。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。