1.原理
data_reg寄存,只寄存符号位和数据位不包含小数点位。
动态数码管每个显示1ms,所以计数到5*10^4-1
为了将sel和seg同步,把sel打了一拍。
6位都使用到了可以这么计算,6位都显示的是数据。或者最高位显示的是小数点,低5位是数据,
因为数码管是共阳数码管,低电平才能点亮。
2.代码
2.1 seg_dynamic.v
module seg_dynamic(input wire sys_clk ,input wire sys_rst_n ,input wire[19:0] data ,input wire[5:0] point ,input wire sign ,input wire seg_en ,output reg[7:0] seg ,//因为一个数码管包括小数点位有8位output reg[5:0] sel //因为总共有6个数码管需要显示
);parameter CNT_MAX=16'd499_99;wire [3:0] unit;
wire [3:0] ten;
wire [3:0] hun;
wire [3:0] tho;
wire [3:0] t_tho;
wire [3:0] h_hun; //999_999需要这6个位
reg [23:0] data_reg; //6个数码管,每个数码管是BCD码表示,一共有4位,因为上面的ten是4位
reg [15:0] cnt_1ms;//因为计数1ms
reg flag_1ms;
reg [2:0] cnt_sel; //因为要计数6个数码管表示一次扫描周期的结束
reg [5:0] sel_reg; //这个是位选信号,控制哪个数码管亮
reg [3:0] data_disp; //这是上面的data_reg的每个位数的拆分,控制它显示十六进制码
reg dot_disp;always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n==1'b0)data_reg<=24'd0;else if((h_hun)||(point[5]))data_reg<={h_hun,t_tho,tho,hun,ten,unit};else if(((t_tho)||(point[4]))&&(sign==1'b0)) //sign=0就是要使用符号位的意思data_reg<={4'd11,t_tho,tho,hun,ten,unit};else if(((t_tho)||(point[4]))&&(sign==1'b1))data_reg<={4'd10,t_tho,tho,hun,ten,unit}; else if(((tho)||(point[3]))&&(sign==1'b0))data_reg<={4'd11,4'd11,tho,hun,ten,unit}; else if(((tho)||(point[3]))&&(sign==1'b1))data_reg<={4'd11,4'd10,tho,hun,ten,unit};else if(((hun)||(point[2]))&&(sign==1'b0))data_reg<={4'd11,4'd11,4'd11,hun,ten,unit};else if(((hun)||(point[2]))&&(sign==1'b1)) data_reg<={4'd11,4'd11,4'd10,hun,ten,unit};else if(((ten)||(point[1]))&&(sign==1'b0))data_reg<={4'd11,4'd11,4'd11,4'd11,ten,unit}; else if(((ten)||(point[1]))&&(sign==1'b1)) data_reg<={4'd11,4'd11,4'd11,4'd10,ten,unit}; else if(((unit)||(point[0]))&&(sign==1'b0))data_reg<={4'd11,4'd11,4'd11,4'd11,4'd11,unit}; else data_reg<={4'd11,4'd11,4'd11,4'd11,4'd10,unit}; always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n==1'b0)cnt_1ms<=16'd0;else if(cnt_1ms==CNT_MAX)cnt_1ms<=16'd0;elsecnt_1ms<=cnt_1ms+1'b1;always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n==1'b0)flag_1ms<=1'b0;else if(cnt_1ms==CNT_MAX-1'b1)flag_1ms<=1'b1;elseflag_1ms<=1'b0;always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n==1'b0)cnt_sel<=3'd0;else if((flag_1ms==1'b1)&&(cnt_sel==3'd5))cnt_sel<=3'd0;else if(flag_1ms==1'b1)cnt_sel<=cnt_sel+1'b1;elsecnt_sel<=cnt_sel;always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n==1'b0)sel_reg<=6'd0;else if ((cnt_sel==3'd0)&&(flag_1ms==1'b1))sel_reg<=6'b000_001;else if(flag_1ms==1'b1)sel_reg<=sel_reg<<1;elsesel_reg<=sel_reg;always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n==1'b0)data_disp<=4'd0;else if((seg_en==1'b1)&&(flag_1ms==1'b1))case(cnt_sel)3'd0: data_disp<=data_reg[3:0];3'd1: data_disp<=data_reg[7:4];3'd2: data_disp<=data_reg[11:8];3'd3: data_disp<=data_reg[15:12];3'd4: data_disp<=data_reg[19:16];3'd5: data_disp<=data_reg[23:20];default: data_disp<=4'b0;endcaseelsedata_disp<=data_disp;always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n==1'b0)dot_disp<=1'b1;else if(flag_1ms==1'b1)dot_disp<=~point[cnt_sel];else dot_disp<=dot_disp;always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n==1'b0) seg<=8'd0;else case(data_disp)4'd0: seg<={dot_disp,7'b100_0000};4'd1: seg<={dot_disp,7'b111_1001};4'd2: seg<={dot_disp,7'b010_0100};4'd3: seg<={dot_disp,7'b011_0000};4'd4: seg<={dot_disp,7'b011_1001};4'd5: seg<={dot_disp,7'b001_0010};4'd6: seg<={dot_disp,7'b000_0010};4'd7: seg<={dot_disp,7'b111_1000};4'd8: seg<={dot_disp,7'b000_0000};4'd9: seg<={dot_disp,7'b001_0000};4'd10: seg<=8'b1011_1111;//10就是符号,只显示中间的那条杠,因此是4'd11: seg<=8'b1111_1111;//就是显示0default:seg<=8'b1100_0000;endcasealways@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n==1'b0) sel<=6'd0;elsesel<=sel_reg;bcd_8421 bcd_8421_inst(.sys_clk (sys_clk ) ,.sys_rst_n (sys_rst_n) ,.data (data ) ,.unit (unit ) ,.ten (ten ) ,.hun (hun ) ,.tho (tho ) ,.t_tho (t_tho ) ,.h_hun (h_hun )
);endmodule
2.2 tb_seg_dynamic.v
module tb_seg_dynamic();reg sys_clk ;
reg sys_rst_n ;
reg[19:0] data ;
reg[5:0] point ;
reg sign ;
reg seg_en ;wire[7:0] seg;
wire[5:0] sel;initial beginsys_clk=1'b1;sys_rst_n<=1'b0;data<=20'd0;point<=6'b000_000;sign<=1'b0;seg_en<=1'b0;#30sys_rst_n<=1'b1;data<=20'd98_76;point<=6'b000_010;sign<=1'b1;seg_en<=1'b1;endalways #10 sys_clk=~sys_clk;
defparam seg_dynamic_inst.CNT_MAX=20'd5;seg_dynamic seg_dynamic_inst(.sys_clk (sys_clk ) ,.sys_rst_n (sys_rst_n),.data (data ),.point (point ),.sign (sign ),.seg_en (seg_en ),.seg (seg ) ,.sel (sel )
);
endmodule