FPGA学习日记(18)--数码管动态显示

 

数据生成模块

 

module data_gen
#(
   parameter CNT_MAX = 23'd4999_999 ,
   parameter DATA_MAX = 20'd999_999 
)
(   
    input    wire         sys_clk     ,
    input    wire         sys_rst_n   ,
           
    output   reg   [19:0] data        ,
    output   wire  [5:0]  point       ,
    output   wire         sign        ,
    output   reg          seg_en      
    
);

reg [22:0] cnt_100ms;
reg cnt_flag ;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_100ms <= 23'd0;
    else if(cnt_100ms == CNT_MAX)
        cnt_100ms <= 23'd0;
    else
        cnt_100ms <= 1'b1 + cnt_100ms;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_flag <= 1'b0;
    else if (cnt_100ms == 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 == 1'b0)
        data <= 20'd0;
    else if((data == DATA_MAX)&&(cnt_flag == 1'b1))
        data <= 20'd0;
    else if(cnt_flag == 1'b1)
        data <= data + 1'b1;
    else 
        data <= data;

assign point = 6'b000_000;
assign sign  = 1'b0;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        seg_en <= 1'b0;
    else 
        seg_en <= 1'b1;

endmodule         
`timescale 1ns/1ns
module tb_data_gen();

reg   sys_clk     ;
reg   sys_rst_n   ;
                    
wire [19:0] data   ;
wire [5:0]  point  ;
wire        sign   ; 
wire        seg_en ;


initial 
    begin 
        sys_clk =1'b1;
        sys_rst_n <= 1'b0;
        #20 
        sys_rst_n <= 1'b1;
    end
 
always #10 sys_clk = ~sys_clk;

data_gen
#(
  .CNT_MAX (9)   ,
  .DATA_MAX(9)   
)
data_gen_inst
(
   .sys_clk   (sys_clk  ) , 
   .sys_rst_n (sys_rst_n) ,
   .data  (data  ),
   .point (point ),
   .sign  (sign  ),
   .seg_en(seg_en)

);
endmodule

计数器 cnt_flag

data

加入BCD码模块

  

 

module bcd_8421
(
    input       sys_clk     ,
    input       sys_rst_n   ,
    input wire [19:0] data  ,
                        
    output reg [3:0] unit  ,
    output reg [3:0] ten   ,
    output reg [3:0] hun   , 
    output reg [3:0] tho   ,
    output reg [3:0] t_tho ,
    output reg [3:0] h_hun 
);
reg [4:0]   cnt_shift;
reg [43:0]  data_shift;
reg         shift_flag;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_shift <= 5'd0;
    else if ((cnt_shift == 5'd21)&&(shift_flag == 1'b1))
        cnt_shift <= 5'd0;
    else if(shift_flag == 1'b1)
        cnt_shift <= cnt_shift + 1'b1;
    else 
        cnt_shift <= cnt_shift ;
        
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0) 
        data_shift <= 44'b0;
    else if(cnt_shift == 5'd0)
        data_shift <= {24'b0,data};
    else if((cnt_shift <= 20)&&(shift_flag ==1'b0))
        begin
        data_shift[23:20] <= (data_shift[23:20] > 4) ? (data_shift[23:20] + 2'd3) : (data_shift[23:20]);
        data_shift[27:24] <= (data_shift[27:24] > 4) ? (data_shift[27:24] + 2'd3) : (data_shift[27:24]);
        data_shift[31:28] <= (data_shift[31:28] > 4) ? (data_shift[31:28] + 2'd3) : (data_shift[31:28]);
        data_shift[35:32] <= (data_shift[35:32] > 4) ? (data_shift[35:32] + 2'd3) : (data_shift[35:32]);
        data_shift[39:36] <= (data_shift[39:36] > 4) ? (data_shift[39:36] + 2'd3) : (data_shift[39:36]);
        data_shift[43:40] <= (data_shift[43:40] > 4) ? (data_shift[43:40] + 2'd3) : (data_shift[43:40]);
        end
    else if((cnt_shift <= 20)&&(shift_flag ==1'b1))
        data_shift <= data_shift << 1;
    else    
        data_shift <= data_shift ;
        
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)     
        shift_flag <= 1'b0;
    else 
        shift_flag <= ~shift_flag;

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)     
        begin
            unit   <= 4'b0;
            ten    <= 4'b0;
            hun    <= 4'b0;
            tho    <= 4'b0;
            t_tho  <= 4'b0;
            h_hun  <= 4'b0;
        end
    else if(cnt_shift == 5'd21)
        begin
            unit   <= data_shift[23:20];
            ten    <= data_shift[27:24];
            hun    <= data_shift[31:28];
            tho    <= data_shift[35:32];
            t_tho  <= data_shift[39:36];
            h_hun  <= data_shift[43:40];
        end    
endmodule
`timescale 1ns/1ns
module tb_bcd_8421();
reg     sys_clk;
reg     sys_rst_n;
reg [19:0] data;
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  ;
initial 
    begin 
        sys_clk =1'b1;
        sys_rst_n <= 1'b0;
        data <= 20'd0;
        #30 
        sys_rst_n <= 1'b1;
        data <= 20'd123_456;
        #3000
        data <= 20'd654_321;
        #3000
        data <= 20'd987_654;
        #3000
        data <= 20'd999_999;
    end
 
always #10 sys_clk = ~sys_clk;

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 

cnt_shift

 

 

动态显示模块

 

 

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 [5:0]   sel     ,
    output reg [7:0]   seg     
);

parameter CNT_MAX = 16'd49_999;

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;
reg     [23:0]  data_reg;
reg     [15:0]  cnt_1ms;
reg             flag_1ms;    
reg     [2:0]   cnt_sel;
reg     [5:0]   sel_reg;
reg     [3:0]   data_disp;
reg             dot_disp;    

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0) 
        data_reg <= 24'b0;
    else if((h_hun)||(point[5]))
        data_reg <= {h_hun,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(((t_tho)||(point[4]))&&(sign == 1'b0))
        data_reg <= {4'd11,t_tho,tho,hun,ten,unit};
    else if(((tho)||(point[3]))&&(sign == 1'b1))
        data_reg <= {4'd11,4'd10,tho,hun,ten,unit};
    else if(((tho)||(point[3]))&&(sign == 1'b0))
        data_reg <= {4'd11,4'd11,tho,hun,ten,unit};  
    else if(((hun)||(point[2]))&&(sign == 1'b1))
        data_reg <= {4'd11,4'd11,4'd10,hun,ten,unit};
    else if(((hun)||(point[2]))&&(sign == 1'b0))
        data_reg <= {4'd11,4'd11,4'd11,hun,ten,unit};  
    else if(((ten)||(point[1]))&&(sign == 1'b1))
        data_reg <= {4'd11,4'd11,4'd11,4'd10,ten,unit};
    else if(((ten)||(point[1]))&&(sign == 1'b0))
        data_reg <= {4'd11,4'd11,4'd11,4'd11,ten,unit};  
    else if(((unit)||(point[0]))&&(sign == 1'b1))
        data_reg <= {4'd11,4'd11,4'd11,4'd11,4'd10,unit};
    else
        data_reg <= {4'd11,4'd11,4'd11,4'd11,4'd11,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; 
    else    
        cnt_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;
    else 
        flag_1ms <= 1'b0;        
        
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0) 
        cnt_sel <= 3'd0;
    else if ((cnt_sel == 3'd5)&&(flag_1ms == 1'b1))
        cnt_sel <= 3'd0;
    else if (flag_1ms == 1'b1)
        cnt_sel <= cnt_sel + 1'b1;
    else 
        cnt_sel <= cnt_sel;
        
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0) 
        sel_reg <= 6'b000_000;
    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;
    else 
        sel_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'd0; 
        endcase
    else
        data_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'b111_111;
    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'b001_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;
            4'd11: seg <= 8'b111_111;
            default: seg <= 8'b1100_0000;
        endcase
       
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)  
        sel <= 6'b000_000;
    else 
        sel <= 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
`timescale 1ns/1ns
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  [5:0]   sel     ;
wire  [7:0]   seg     ;

initial 
    begin 
        sys_clk =1'b1;
        sys_rst_n <= 1'b0;
        data <= 20'd0;
        point <= 6'b0;
        sign <= 1'b0;
        seg_en <= 1'b0;
        #30 
        sys_rst_n <= 1'b1;
        data <= 20'd9876;
        point <= 6'b0;
        sign <= 1'b1;
        seg_en <= 1'b1;
    end

always #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   ) ,
 
  . sel      ( sel      ) ,
  . seg      ( seg      ) 
);
endmodule

 

 

 

b没有使用最高位 a符号位

 

 

 

数据显示

 

 

 

module hc595_ctrl
(
    input   wire    sys_clk     ,
    input   wire    sys_rst_n   ,
    input   wire [5:0]  sel     ,
    input   wire [7:0]  seg     ,
    
    output  reg        ds      ,
    output  reg        shcp    ,
    output  reg        stcp    ,
    output  wire        oe      
);

wire [13:0] data    ;
reg  [1:0]  cnt     ;
reg  [3:0]  cnt_bit ;

assign data = {seg[0],seg[1],seg[2],seg[3],seg[4],seg[5],seg[6],seg[7],sel};

always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt <= 2'd0;
    else if (cnt == 2'd3)
        cnt <= 2'd0;
    else 
        cnt <= cnt + 1'b1;
        
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        cnt_bit <= 4'd0;
    else if ((cnt_bit == 4'd13)&&(cnt == 2'd3))
        cnt_bit <= 4'd0;
    else if (cnt == 2'd3)
        cnt_bit <= cnt_bit + 1'b1;
    else    
        cnt_bit <= cnt_bit;
        
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        ds <= 1'b0;
    else if(cnt == 2'd0)
        ds <= data[cnt_bit];
    else
        ds <= ds;
//移位时钟
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0) 
        shcp <= 1'b0;
    else if (cnt == 2'd2)
        shcp <= 1'b1;
    else if (cnt == 2'd0)
         shcp <= 1'b0;
    else 
        shcp <= shcp;
//存储寄存器时钟
always@(posedge sys_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0) 
        stcp <= 1'b0;
    else if ((cnt_bit == 4'd0)&&(cnt == 2'd0))
        stcp <= 1'b1;
    else if ((cnt_bit == 4'd0)&&(cnt == 2'd2)) 
        stcp <= 1'b0;
    else 
        stcp <= stcp;
        
assign oe = 1'b0;

endmodule        
module seg_595_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  wire        ds      ,
    output  wire        oe      , 
    output   wire       shcp   ,
    output  wire        stcp
);
wire [5:0] sel;
wire [7:0] seg;

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   ) ,
 
  . sel      ( sel      ) ,
  . seg      ( seg      ) 
);
 
hc595_ctrl hc595_ctrl_inst
(
    .sys_clk  (sys_clk  )  ,
    .sys_rst_n(sys_rst_n)  ,
    .  sel    (  sel    )  ,
    .  seg    (  seg    )  ,
               
    .ds       (ds       )  ,
    .shcp     (shcp     )  ,
    .stcp     (stcp     )  ,
    . oe      ( oe      )   
);
endmodule

 

module top_seg_595
(
    input   wire    sys_clk     ,
    input   wire    sys_rst_n   ,
    output  wire       ds      ,
    output  wire       shcp    ,
    output  wire       stcp    ,
    output  wire        oe      

);
wire [19:0] data;
wire [5:0] point;
wire  sign;
wire seg_en;


data_gen 
#(
    .CNT_MAX(23'd9),
    .DATA_MAX(20'd999_999)
)
data_gen_inst
(
  .sys_clk   (sys_clk   ) ,
  .sys_rst_n (sys_rst_n ) ,
  . data     ( data     ) ,
  . point    ( point    ) ,
  . sign     ( sign     ) ,
  . seg_en   ( seg_en   ) ,
    
    
);
seg_595_dynamic seg_595_dynamic_inst
(
  .sys_clk   (sys_clk   ) ,
  .sys_rst_n (sys_rst_n ) ,
  . data     ( data     ) ,
  . point    ( point    ) ,
  . sign     ( sign     ) ,
  . seg_en   ( seg_en   ) ,
    .ds   (ds  ), 
    .shcp (shcp), 
    .stcp (stcp),    
    . oe  ( oe )
);

endmodule
`timescale 1ns/1ns
module tb_top_seg_595();

reg         sys_clk   ;
reg         sys_rst_n ;
 wire       ds        ;
 wire       shcp      ;
 wire       stcp      ;
 wire        oe       ;
 
initial 
    begin 
        sys_clk =1'b1;
        sys_rst_n <= 1'b0;
        #20 
        sys_rst_n <= 1'b1;
    end
 
always #10 sys_clk = ~sys_clk;
defparam top_seg_595_inst.data_gen_inst.CNT_MAX = 23'd49;
defparam top_seg_595_inst.seg_595_dynamic_inst.seg_dynamic_inst.CNT_MAX =16'd19;

top_seg_595 top_seg_595_inst
(
.sys_clk   (sys_clk   ), 
.sys_rst_n (sys_rst_n ), 
.ds        (ds        ), 
.shcp      (shcp      ), 
.stcp      (stcp      ), 
. oe       ( oe       )
);
endmodule

 

 

 

 

 

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值