基于FPGA的数字秒表设计
硬件平台:DE2-115
软件环境:Quartus II 15.1
采样了较为简单的计数方法,详细代码就不讲解了,分为三个模块,一个是计数模块 count.v,一个是显示模块 disp.v,还有一个是顶层模块 miaobiao.v。有清零按键和暂停拨码开关。
顶层模块:
1 module miaobiao( 2 clk, 3 rst_n, 4 pause, 5 6 Hex0, 7 Hex1, 8 Hex2, 9 Hex3, 10 Hex4, 11 Hex5, 12 ); 13 14 input clk; 15 input rst_n; 16 input pause; 17 18 output[6:0] Hex0; 19 output[6:0] Hex1; 20 output[6:0] Hex2; 21 output[6:0] Hex3; 22 output[6:0] Hex4; 23 output[6:0] Hex5; 24 25 wire[3:0]h_sec_h; 26 wire[3:0]h_sec_l; 27 28 wire[3:0]sec_h; 29 wire[3:0]sec_l; 30 31 wire[3:0]fen_h; 32 wire[3:0]fen_l; 33 34 count u0( 35 .clk(clk), 36 .rst_n(rst_n), 37 .pause(pause), 38 39 .h_sec_h(h_sec_h), 40 .h_sec_l(h_sec_l), 41 42 .sec_h(sec_h), 43 .sec_l(sec_l), 44 45 .fen_h(fen_h), 46 .fen_l(fen_l) 47 ); 48 49 disp u1( 50 51 .h_sec_l(h_sec_l), 52 .h_sec_h(h_sec_h), 53 54 .sec_l(sec_l), 55 .sec_h(sec_h), 56 57 .fen_l(fen_l), 58 .fen_h(fen_h), 59 60 .Hex0(Hex0), 61 .Hex1(Hex1), 62 .Hex2(Hex2), 63 .Hex3(Hex3), 64 .Hex4(Hex4), 65 .Hex5(Hex5) 66 ); 67 68 endmodule
计数模块:
1 module count( 2 clk, 3 rst_n, 4 pause, 5 6 h_sec_h, 7 h_sec_l, 8 9 sec_h, 10 sec_l, 11 12 fen_h, 13 fen_l 14 ); 15 16 input clk; 17 input rst_n; 18 input pause; //pause为0时正常计数,为1时暂停计数 19 20 output reg[3:0] h_sec_h; //百分秒低位 21 output reg[3:0] h_sec_l; //百分秒高位 22 23 output reg[3:0] sec_h; //秒高位 24 output reg[3:0] sec_l; //秒低位 25 26 output reg[3:0] fen_h; //分低位 27 output reg[3:0] fen_l; //分高位 28 29 reg flag1; //flag1为百分秒向秒的进位 30 reg flag2; //flag2为秒向分的进位 31 reg[27:0] cnt; // 32 reg clk_100hz; 33 34 /* 100hz 分频 */ 35 always@(posedge clk or negedge rst_n) 36 if(!rst_n) 37 cnt <= 28'd0; 38 else if(cnt == 249999) 39 cnt <= 28'd0; 40 else 41 cnt <= cnt + 1'b1; 42 43 always@(posedge clk or negedge rst_n) 44 if(!rst_n) 45 clk_100hz <= 1'b0; 46 else if(cnt == 249999) 47 clk_100hz <= !clk_100hz; 48 else 49 clk_100hz <= clk_100hz; 50 51 /* 百分秒计数进程,每计满100,flag1产生一个进位 */ 52 always@(posedge clk_100hz or negedge rst_n) 53 begin 54 if(!rst_n) begin 55 {h_sec_h,h_sec_l} <= 8'h00; 56 flag1 <= 1'b0; 57 end 58 else if(!pause) begin 59 if(h_sec_l == 9) begin 60 h_sec_l <= 4'd0; 61 if(h_sec_h == 9) begin 62 h_sec_h <= 4'd0; 63 flag1 <= 1'b1; 64 end 65 else 66 h_sec_h <= h_sec_h + 1'b1; 67 end 68 else begin 69 h_sec_l <= h_sec_l + 1'b1; 70 flag1 <= 1'b0; 71 end 72 end 73 end 74 75 /* 秒计数进程,每计满60,flag2产生一个进位 */ 76 always@(posedge flag1 or negedge rst_n) 77 begin 78 if(!rst_n) begin 79 {sec_h,sec_l} <= 8'h00; 80 flag2 <= 0; 81 end 82 else if(sec_l == 9) begin 83 sec_l <= 4'd0; 84 if(sec_h == 5) begin 85 sec_h <= 4'd0; 86 flag2 <= 1'b1; 87 end 88 else 89 sec_h <= sec_h + 1'b1; 90 end 91 else begin 92 sec_l <= sec_l + 1'b1; 93 flag2 <= 1'b0; 94 end 95 end 96 97 /* 分计数进程,每计数满60,系统自动清零 */ 98 always@(posedge flag2 or negedge rst_n) 99 begin 100 if(!rst_n) begin 101 {fen_h,fen_l} <= 8'h00; 102 end 103 else if(fen_l == 9) begin 104 fen_l <= 4'd0; 105 if(fen_h == 5) 106 fen_h <= 4'd0; 107 else 108 fen_h <= fen_h + 1'b1; 109 end 110 else 111 fen_l <= fen_l + 1'b1; 112 end 113 endmodule 114 115 116 117 118
显示模块:
1 module disp( 2 3 h_sec_l, 4 h_sec_h, 5 6 sec_l, 7 sec_h, 8 9 fen_l, 10 fen_h, 11 12 Hex0, 13 Hex1, 14 Hex2, 15 Hex3, 16 Hex4, 17 Hex5, 18 ); 19 20 input[3:0] h_sec_h; 21 input[3:0] h_sec_l; 22 23 input[3:0] sec_h; 24 input[3:0] sec_l; 25 26 input[3:0] fen_h; 27 input[3:0] fen_l; 28 29 output reg[6:0] Hex0; 30 output reg[6:0] Hex1; 31 output reg[6:0] Hex2; 32 output reg[6:0] Hex3; 33 output reg[6:0] Hex4; 34 output reg[6:0] Hex5; 35 36 always@(*) //百分秒个位控制 37 begin 38 case(h_sec_l) 39 0:Hex0 <= 7'b1000000; //0 40 1:Hex0 <= 7'b1111001; //1 41 2:Hex0 <= 7'b0100100; //2 42 3:Hex0 <= 7'b0110000; //3 43 4:Hex0 <= 7'b0011001; //4 44 5:Hex0 <= 7'b0010010; //5 45 6:Hex0 <= 7'b0000010; //6 46 7:Hex0 <= 7'b1111000; //7 47 8:Hex0 <= 7'b0000000; //8 48 9:Hex0 <= 7'b0010000; //9 49 default:Hex0 <= 7'b1000000; //0 50 endcase 51 end 52 53 always@(*) //百分秒十位控制 54 begin 55 case(h_sec_h) 56 0:Hex1 <= 7'b1000000; //0 57 1:Hex1 <= 7'b1111001; //1 58 2:Hex1 <= 7'b0100100; //2 59 3:Hex1 <= 7'b0110000; //3 60 4:Hex1 <= 7'b0011001; //4 61 5:Hex1 <= 7'b0010010; //5 62 6:Hex1 <= 7'b0000010; //6 63 7:Hex1 <= 7'b1111000; //7 64 8:Hex1 <= 7'b0000000; //8 65 9:Hex1 <= 7'b0010000; //9 66 default:Hex1 <= 7'b1000000; //0 67 endcase 68 end 69 70 always@(*) // 71 begin 72 case(sec_l) 73 0:Hex2 <= 7'b1000000; //0 74 1:Hex2 <= 7'b1111001; //1 75 2:Hex2 <= 7'b0100100; //2 76 3:Hex2 <= 7'b0110000; //3 77 4:Hex2 <= 7'b0011001; //4 78 5:Hex2 <= 7'b0010010; //5 79 6:Hex2 <= 7'b0000010; //6 80 7:Hex2 <= 7'b1111000; //7 81 8:Hex2 <= 7'b0000000; //8 82 9:Hex2 <= 7'b0010000; //9 83 default:Hex2 <= 7'b1000000; //0 84 endcase 85 end 86 87 always@(*) // 88 begin 89 case(sec_h) 90 0:Hex3 <= 7'b1000000; //0 91 1:Hex3 <= 7'b1111001; //1 92 2:Hex3 <= 7'b0100100; //2 93 3:Hex3 <= 7'b0110000; //3 94 4:Hex3 <= 7'b0011001; //4 95 5:Hex3 <= 7'b0010010; //5 96 default:Hex3 <= 7'b1000000; //0 97 endcase 98 end 99 100 always@(*) // 101 begin 102 case(fen_l) 103 0:Hex4 <= 7'b1000000; //0 104 1:Hex4 <= 7'b1111001; //1 105 2:Hex4 <= 7'b0100100; //2 106 3:Hex4 <= 7'b0110000; //3 107 4:Hex4 <= 7'b0011001; //4 108 5:Hex4 <= 7'b0010010; //5 109 6:Hex4 <= 7'b0000010; //6 110 7:Hex4 <= 7'b1111000; //7 111 8:Hex4 <= 7'b0000000; //8 112 9:Hex4 <= 7'b0010000; //9 113 default:Hex4 <= 7'b1000000; //0 114 endcase 115 end 116 117 always@(*) // 118 begin 119 case(fen_h) 120 0:Hex5 <= 7'b1000000; //0 121 1:Hex5 <= 7'b1111001; //1 122 2:Hex5 <= 7'b0100100; //2 123 3:Hex5 <= 7'b0110000; //3 124 4:Hex5 <= 7'b0011001; //4 125 5:Hex5 <= 7'b0010010; //5 126 default:Hex5 <= 7'b1000000; //0 127 endcase 128 end 129 130 endmodule
仿真用的是Modelsim SE-64 10.4,只对计数模块进行了仿真,不是很直观,代码如下:
1 `timescale 1ns/1ns 2 `define clk_period 20 3 module count_tb; 4 reg clk; 5 reg rst_n; 6 reg pause; 7 wire[3:0] h_sec_h; 8 wire[3:0] h_sec_l; 9 wire[3:0] sec_l; 10 wire[3:0] sec_h; 11 wire[3:0] fen_h; 12 wire[3:0] fen_l; 13 count u0( 14 .clk(clk), 15 .rst_n(rst_n), 16 .pause(pause), 17 .h_sec_h(h_sec_h), 18 .h_sec_l(h_sec_l), 19 .sec_h(sec_h), 20 .sec_l(sec_l), 21 .fen_h(fen_h), 22 .fen_l(fen_l) 23 ); 24 25 initial 26 clk = 0; 27 always#(`clk_period/2) clk = ~clk; 28 29 initial 30 begin 31 rst_n = 1'b0; 32 #(`clk_period); 33 rst_n = 1'b1; 34 pause = 1'b1; 35 #(`clk_period*5); 36 pause = 1'b0; 37 #(`clk_period*1000000); 38 $stop; 39 end 40 endmodule
由于分频为100hz进行百分秒计数,Modelsim跑的比较慢,所以我将百分秒计数模块,秒计数模块,分计数模块一个个单独来进行仿真,这样速度较快,容易找到问题,功能上是可以完全实现的。
=========================================================================
版本更新:2020.12.07 15:22
=========================================================================
硬件平台:米联客 MA703FA
软件环境:Vivado 2019.2
功能设计:
三个按键,按键 1 控制清零,按键 2 控制 开始,按键 3 控制暂停,测时精度:0.01 S,测时范围:0 ~ 99.99 S。开发板上的按键悬空时都是高电平,按下之后为低电平,使用了 4 个七段数码管,理论上,至少需要 4 + 8 个 pin 与FPGA芯片相连,使用了 2 片74HC595芯片来节约引脚资源。
RTL 视图:
源码设计:
1、模块一
1 // ********************************************************************************* 2 // Project Name : data_generrate 3 // Email : 4 // Create Time : 2020/12/6 15:52 5 // Module Name : data_generrate 6 // editor : Qing 7 // Version : Rev1.0.0 8 // ********************************************************************************* 9 10 module data_generrate( 11 input sclk , 12 input s_rst_n , 13 14 input start , 15 input stop , 16 17 output reg[15:0] data_out 18 ); 19 20 //========================================================================\ 21 // =========== Define Parameter and Internal signals =========== 22 //========================================================================/ 23 24 parameter TIME_1MS = 499999 ; //99999 25 26 reg [23:0] cnt_ms = 24'd0 ; 27 reg flag_add = 1'b0 ; 28 29 //============================================================================= 30 //**************************** Main Code ******************************* 31 //============================================================================= 32 33 always @(posedge sclk) begin 34 if(!s_rst_n) 35 flag_add <= 1'b0; 36 else if(start == 1'b0) 37 flag_add <= 1'b1; 38 else if(stop == 1'b0) 39 flag_add <= 1'b0; 40 else 41 flag_add <= flag_add; 42 end 43 44 always @(posedge sclk) begin 45 if(!s_rst_n) 46 cnt_ms <= 24'd0; 47 else if(flag_add == 1'b1) begin 48 if(cnt_ms == TIME_1MS) 49 cnt_ms <= 24'd0; 50 else 51 cnt_ms <= cnt_ms + 1'b1; 52 end 53 else 54 cnt_ms <= cnt_ms; 55 end 56 57 always @(posedge sclk) begin 58 if(!s_rst_n) 59 data_out <= 16'd0; 60 else if(flag_add == 1'b1) begin 61 if(data_out == 16'd9999) 62 data_out <= 16'd0; 63 else if(cnt_ms == TIME_1MS) 64 data_out <= data_out + 1'b1; 65 else 66 data_out <= data_out; 67 end 68 else 69 data_out <= data_out; 70 end 71 72 endmodule
2、模块二
1 // ********************************************************************************* 2 // Project Name : bcd_8421 3 // Email : 4 // Create Time : 2020/12/05 22:14 5 // Module Name : bcd_8421 6 // editor : Qing 7 // Version : Rev1.0.0 8 // ********************************************************************************* 9 10 module bcd_8421( 11 input sclk , 12 input s_rst_n , 13 14 input [15:0] data_in , 15 16 output reg[ 3:0] unit , 17 output reg[ 3:0] ten , 18 output reg[ 3:0] hun , 19 output reg[ 3:0] tho 20 ); 21 22 //========================================================================\ 23 // =========== Define Parameter and Internal signals =========== 24 //========================================================================/ 25 26 reg [ 4:0] cnt_shift ; 27 reg [31:0] data_shift ; 28 reg shift_flag ; 29 30 //============================================================================= 31 //**************************** Main Code ******************************* 32 //============================================================================= 33 34 always @(posedge sclk or negedge s_rst_n) begin 35 if(!s_rst_n) 36 cnt_shift <= 5'd0; 37 else if((cnt_shift == 5'd17) && (shift_flag == 1'b1)) 38 cnt_shift <= 5'd0; 39 else if(shift_flag == 1'b1) 40 cnt_shift <= cnt_shift + 1'b1; 41 else 42 cnt_shift <= cnt_shift; 43 end 44 45 always @(posedge sclk or negedge s_rst_n) begin 46 if(!s_rst_n) 47 data_shift <= 32'd0; 48 else if(cnt_shift == 5'd0) 49 data_shift <= {16'b0,data_in}; 50 else if((cnt_shift <= 16) && (shift_flag == 1'b0)) begin 51 data_shift[19:16] <= (data_shift[19:16] > 4) ? (data_shift[19:16] + 2'd3) : (data_shift[19:16]); 52 data_shift[23:20] <= (data_shift[23:20] > 4) ? (data_shift[23:20] + 2'd3) : (data_shift[23:20]); 53 data_shift[27:24] <= (data_shift[27:24] > 4) ? (data_shift[27:24] + 2'd3) : (data_shift[27:24]); 54 data_shift[31:28] <= (data_shift[31:28] > 4) ? (data_shift[31:28] + 2'd3) : (data_shift[31:28]); 55 end 56 else if((cnt_shift <= 16) && (shift_flag == 1'b1)) 57 data_shift <= data_shift << 1; 58 else 59 data_shift <= data_shift; 60 end 61 62 always @ (posedge sclk or negedge s_rst_n) begin 63 if(s_rst_n == 1'b0) 64 shift_flag <= 1'b0; 65 else 66 shift_flag <= ~shift_flag; 67 end 68 69 always @(posedge sclk or negedge s_rst_n) begin 70 if(!s_rst_n) begin 71 unit <= 4'b0; 72 ten <= 4'b0; 73 hun <= 4'b0; 74 tho <= 4'b0; 75 end 76 else if(cnt_shift == 5'd17) begin 77 unit <= data_shift[19:16]; 78 ten <= data_shift[23:20]; 79 hun <= data_shift[27:24]; 80 tho <= data_shift[31:28]; 81 end 82 end 83 84 endmodule
3、模块三
1 // ********************************************************************************* 2 // Project Name : disp 3 // Email : 4 // Create Time : 2020/12/06 16:59 5 // Module Name : disp 6 // editor : Qing 7 // Version : Rev1.0.0 8 // ********************************************************************************* 9 10 module disp( 11 input sclk , 12 input s_rst_n , 13 14 input [3:0] unit , 15 input [3:0] ten , 16 input [3:0] hun , 17 input [3:0] tho , 18 19 output reg [3:0] sel , 20 output reg [7:0] seg 21 ); 22 23 //========================================================================\ 24 // =========== Define Parameter and Internal signals =========== 25 //========================================================================/ 26 27 parameter TIME_1MS = 49999 ; 28 parameter point = 4'b0100 ; 29 30 reg [15:0] cnt_ms = 16'd0 ; 31 reg [15:0] disp_reg = 16'd0 ; 32 reg [ 2:0] lsm_cnt = 3'd0 ; 33 reg [ 3:0] data_reg = 4'd0 ; 34 reg dot_point = 1'b0 ; 35 36 //============================================================================= 37 //**************************** Main Code ******************************* 38 //============================================================================= 39 40 always @(posedge sclk) begin 41 if(!s_rst_n) 42 cnt_ms <= 16'd0; 43 else if(cnt_ms == TIME_1MS) 44 cnt_ms <= 16'd0; 45 else 46 cnt_ms <= cnt_ms + 1'b1; 47 end 48 49 always @(posedge sclk) begin 50 if(!s_rst_n) 51 disp_reg <= 16'd0; 52 else if(tho != 4'd0) 53 disp_reg <= {tho,hun,ten,unit}; 54 else if((hun != 4'd0)) 55 disp_reg <= {4'd10,hun,ten,unit}; 56 else if((ten != 4'd0)) 57 disp_reg <= {4'd10,4'd10,ten,unit}; 58 else if(unit != 4'd0) 59 disp_reg <= {4'd10,4'd10,4'd10,unit}; 60 else 61 disp_reg <= {4'd10,4'd10,4'd10,4'd10}; 62 end 63 64 always @(posedge sclk) begin 65 if(!s_rst_n) 66 lsm_cnt <= 3'd0; 67 else if((lsm_cnt == 3'd3) && (cnt_ms == TIME_1MS)) 68 lsm_cnt <= 3'd0; 69 else if(cnt_ms == TIME_1MS) 70 lsm_cnt <= lsm_cnt + 1'b1; 71 else 72 lsm_cnt <= lsm_cnt; 73 end 74 75 always @(posedge sclk) begin 76 if(!s_rst_n) 77 sel <= 4'b1111; // 0000 78 else if((cnt_ms == TIME_1MS) && (lsm_cnt == 3'd0)) 79 sel <= 4'b0001; 80 else if(cnt_ms == TIME_1MS) 81 sel <= sel << 1; 82 else 83 sel <= sel; 84 end 85 86 always @(posedge sclk) begin 87 if(!s_rst_n) 88 dot_point <= 1'b0; 89 else if(cnt_ms == TIME_1MS) 90 dot_point <= ~point[lsm_cnt]; 91 else 92 dot_point <= dot_point; 93 end 94 95 always @(posedge sclk) begin 96 if(!s_rst_n) 97 data_reg <= 4'd0; 98 else if(cnt_ms == TIME_1MS) begin 99 case(lsm_cnt) 100 3'd0:data_reg <= disp_reg[3:0]; 101 3'd1:data_reg <= disp_reg[7:4]; 102 3'd2:data_reg <= disp_reg[11:8]; 103 3'd3:data_reg <= disp_reg[15:12]; 104 default:data_reg <= 4'd0; 105 endcase 106 end 107 else 108 data_reg <= data_reg; 109 end 110 111 always @(posedge sclk) begin 112 if(!s_rst_n) 113 seg <= 8'hc0; 114 else begin 115 case(data_reg) 116 4'd0: seg <= {dot_point,7'b100_0000}; // 8'hc0 117 4'd1: seg <= {dot_point,7'b111_1001}; // 8'hf9 118 4'd2: seg <= {dot_point,7'b010_0100}; // 8'ha4 119 4'd3: seg <= {dot_point,7'b011_0000}; // 8'hb0 120 4'd4: seg <= {dot_point,7'b001_1001}; // 8'h99 121 4'd5: seg <= {dot_point,7'b001_0010}; // 8'h92 122 4'd6: seg <= {dot_point,7'b000_0010}; // 8'h82 123 4'd7: seg <= {dot_point,7'b111_1000}; // 8'hf8 124 4'd8: seg <= {dot_point,7'b000_0000}; // 8'h80 125 4'd9: seg <= {dot_point,7'b001_0000}; // 8'h90 126 default:seg <= 8'hc0; 127 endcase 128 end 129 end 130 131 endmodule
4、模块四
1 // ********************************************************************************* 2 // Project Name : HC595_driver 3 // Email : 4 // Create Time : 2020/12/04 21:20 5 // Module Name : 74HC595_driver 6 // editor : Qing 7 // Version : Rev1.0.0 8 // ********************************************************************************* 9 10 module HC595_driver( 11 input sclk , 12 input s_rst_n , 13 14 input [7:0] seg , 15 input [3:0] sel , 16 17 output reg sh_cp , 18 output reg st_cp , 19 output reg ds , 20 output oe 21 ); 22 23 //========================================================================\ 24 // =========== Define Parameter and Internal signals =========== 25 //========================================================================/ 26 27 reg [2:0] cnt0 = 3'd0 ; 28 reg [3:0] lsm_cnt = 4'd0 ; 29 30 wire [11:0] data ; 31 32 33 //============================================================================= 34 //**************************** Main Code ******************************* 35 //============================================================================= 36 37 always @(posedge sclk) begin 38 if(!s_rst_n) 39 cnt0 <= 3'd0; 40 else if(cnt0 == 3) 41 cnt0 <= 3'd0; 42 else 43 cnt0 <= cnt0 + 1'b1; 44 end 45 46 always @(posedge sclk) begin 47 if(!s_rst_n) 48 lsm_cnt <= 4'd0; 49 else if((lsm_cnt == 11) && (cnt0 == 3)) 50 lsm_cnt <= 4'd0; 51 else if(cnt0 == 3) 52 lsm_cnt <= lsm_cnt + 1'b1; 53 else 54 lsm_cnt <= lsm_cnt; 55 end 56 57 always @(posedge sclk) begin // 移位时钟 58 if(!s_rst_n) 59 sh_cp <= 1'b0; 60 else if(cnt0 >= 4'd2) 61 sh_cp <= 1'b1; 62 else 63 sh_cp <= 1'b0; 64 end 65 66 always @(posedge sclk) begin 67 if(!s_rst_n) 68 st_cp <= 1'b0; 69 else if((lsm_cnt == 4'd11) && (cnt0 == 3)) 70 st_cp <= 1'b1; 71 else 72 st_cp <= 1'b0; 73 end 74 75 assign data = {seg[0],seg[1],seg[2],seg[3],seg[4],seg[5],seg[6],seg[7],sel}; 76 77 always @ (posedge sclk) begin 78 if(s_rst_n == 1'b0) 79 ds <= 1'b0; 80 else if(cnt0 == 3'd0) 81 ds <= data[lsm_cnt]; 82 else 83 ds <= ds; 84 85 end 86 87 assign oe = 1'b1; 88 89 endmodule
5、模块五(顶层模块)
1 // ********************************************************************************* 2 // Project Name : stop_watch 3 // Email : 4 // Create Time : 2020/12/06 20:00 5 // Module Name : stop_watch 6 // editor : Qing 7 // Version : Rev1.0.0 8 // ********************************************************************************* 9 10 module stop_watch( 11 input sclk , 12 input s_rst_n , 13 14 input start , 15 input stop , 16 17 output sh_cp , 18 output st_cp , 19 output ds , 20 output oe 21 ); 22 23 wire [15:0] data_in ; 24 wire [ 3:0] unit ; 25 wire [ 3:0] ten ; 26 wire [ 3:0] hun ; 27 wire [ 3:0] tho ; 28 wire [ 3:0] sel ; 29 wire [ 7:0] seg ; 30 31 data_generrate u0( 32 .sclk ( sclk ), 33 .s_rst_n ( s_rst_n ), 34 .start ( start ), 35 .stop ( stop ), 36 .data_out ( data_in ) 37 ); 38 39 bcd_8421 u1( 40 .sclk ( sclk ), 41 .s_rst_n ( s_rst_n ), 42 .data_in ( data_in ), 43 .unit ( unit ), 44 .ten ( ten ), 45 .hun ( hun ), 46 .tho ( tho ) 47 ); 48 49 disp u2( 50 .sclk ( sclk ), 51 .s_rst_n ( s_rst_n ), 52 .unit ( unit ), 53 .ten ( ten ), 54 .hun ( hun ), 55 .tho ( tho ), 56 .sel ( sel ), 57 .seg ( seg ) 58 ); 59 60 HC595_driver u3( 61 .sclk ( sclk ), 62 .s_rst_n ( s_rst_n ), 63 .seg ( seg ), 64 .sel ( sel ), 65 .sh_cp ( sh_cp ), 66 .st_cp ( st_cp ), 67 .ds ( ds ), 68 .oe ( oe ) 69 ); 70 71 endmodule
仿真代码:
数据生成模块的 testbench:
1 `timescale 1ns/1ps 2 module data_generrate_tb; 3 reg sclk ; 4 reg s_rst_n ; 5 reg start ; 6 reg stop ; 7 wire [15:0] data_out ; 8 9 data_generrate data_generrate_inst( 10 .sclk ( sclk ), 11 .s_rst_n ( s_rst_n ), 12 .start ( start ), 13 .stop ( stop ), 14 .data_out ( data_out ) 15 ); 16 17 initial 18 sclk = 1'b0; 19 always #10 sclk = ~sclk; 20 21 initial 22 begin 23 #1; 24 s_rst_n = 1'b0; 25 start = 1'b1; 26 stop = 1'b1; 27 #21; 28 29 s_rst_n = 1'b1; 30 #31; 31 start = 1'b0; 32 #31; 33 start = 1'b1; 34 35 #100000; 36 37 stop = 1'b0; 38 #31; 39 stop = 1'b1; 40 end 41 42 endmodule
bcd_8421 模块的 testbench:
1 `timescale 1ns/1ps 2 module bcd_8421_tb; 3 reg sclk ; 4 reg s_rst_n ; 5 reg [15:0] data_in ; 6 7 wire [ 3:0] unit ; 8 wire [ 3:0] ten ; 9 wire [ 3:0] hun ; 10 wire [ 3:0] tho ; 11 12 bcd_8421 bcd_8421_inst( 13 .sclk ( sclk ), 14 .s_rst_n ( s_rst_n ), 15 .data_in ( data_in ), 16 .unit ( unit ), 17 .ten ( ten ), 18 .hun ( hun ), 19 .tho ( tho ) 20 ); 21 22 initial 23 sclk = 1'b0; 24 always #10 sclk = ~sclk; 25 26 initial 27 begin 28 #1; 29 data_in = 16'b0; 30 s_rst_n = 1'b0; 31 #21; 32 s_rst_n = 1'b1; 33 34 #31; 35 data_in = 16'd1234; 36 #30000; 37 data_in = 16'd4321; 38 #30000; 39 data_in = 16'd0; 40 end 41 endmodule
disp 显示模块的 testbench:
1 `timescale 1ns/1ps 2 module disp_tb; 3 reg sclk ; 4 reg s_rst_n ; 5 6 reg [3:0] unit ; 7 reg [3:0] ten ; 8 reg [3:0] hun ; 9 reg [3:0] tho ; 10 11 wire [3:0] sel ; 12 wire [7:0] seg ; 13 14 disp disp_inst( 15 .sclk ( sclk ), 16 .s_rst_n ( s_rst_n ), 17 .unit ( unit ), 18 .ten ( ten ), 19 .hun ( hun ), 20 .tho ( tho ), 21 .sel ( sel ), 22 .seg ( seg ) 23 ); 24 25 initial 26 sclk = 1'b0; 27 always #10 sclk = ~sclk; 28 29 initial 30 begin 31 #1; 32 s_rst_n = 1'b0; 33 unit = 4'd0; 34 ten = 4'd0; 35 hun = 4'd0; 36 tho = 4'd0; 37 38 #21; 39 s_rst_n = 1'b1; 40 #51; 41 42 unit = 4'd1; 43 ten = 4'd2; 44 hun = 4'd3; 45 tho = 4'd4; 46 end 47 48 endmodule
HC595驱动模块的testbench:
1 `timescale 1ns/1ps 2 module HC595_driver_tb; 3 reg sclk ; 4 reg s_rst_n ; 5 6 reg [7:0] seg ; 7 reg [3:0] sel ; 8 9 wire sh_cp ; 10 wire st_cp ; 11 wire ds ; 12 13 HC595_driver HC595_driver_inst( 14 .sclk ( sclk ), 15 .s_rst_n ( s_rst_n ), 16 .seg ( seg ), 17 .sel ( sel ), 18 .sh_cp ( sh_cp ), 19 .st_cp ( st_cp ), 20 .ds ( ds ) 21 ); 22 23 initial 24 sclk = 1'b0; 25 always #10 sclk = ~sclk; 26 27 initial 28 begin 29 #1; 30 s_rst_n = 1'b0; 31 seg = 8'd0; 32 sel = 4'd0; 33 #21; 34 35 s_rst_n = 1'b1; 36 #20; 37 seg = 8'b1010_1010; 38 sel = 4'b1111; 39 end 40 41 endmodule
=========================================================================
版本更新:2021.05.01 20 : 10
=========================================================================
硬件平台:友晶DE1-SOC
软件环境:Quartus II 15.1 Modelsim 10.4 SE
功能描述:利用开发板实现了一个类似于数字秒表的设计,一个复位按键(KEY0),一个启动按键(KEY1),一个暂停按键(KEY2),测时精度1秒,通过4个七段数码管表示时间,左边两个数码管表示分钟的计时,右边两个数码管表示秒钟的计时,板卡代码烧录成功之后,数码管显示为4个0,最大计数值为2021,即最大计数时间为20分21秒,代码比较简单。其RTL视图如下:
1. 分频模块:div_clk的源码如下:
Verilog HDL 源码:
1 module div_clk( 2 input clk , 3 input rst_n , 4 5 output reg clk_1Hz 6 ); 7 8 reg [27:0] cnt ; 9 10 always @(posedge clk or negedge rst_n) begin 11 if(!rst_n) 12 cnt <= 28'd0; 13 else if(cnt == 49_999999) // 49_999999 14 cnt <= 28'd0; 15 else 16 cnt <= cnt + 1'b1; 17 end 18 19 always @(posedge clk or negedge rst_n) begin 20 if(!rst_n) 21 clk_1Hz <= 1'b0; 22 else if(cnt == 49_999999) // 49_999999 23 clk_1Hz <= ~clk_1Hz; 24 else 25 clk_1Hz <= clk_1Hz; 26 end 27 28 endmodule
仿真代码testbench:
1 `timescale 1ns/1ps 2 module div_clk_tb; 3 4 reg clk ; 5 reg rst_n ; 6 7 wire clk_1Hz ; 8 9 div_clk div_clk_inst( 10 .clk ( clk ), 11 .rst_n ( rst_n ), 12 .clk_1Hz ( clk_1Hz ) 13 ); 14 15 initial 16 clk = 1'b0; 17 always #10 clk = ~clk; 18 19 initial 20 begin 21 #1; 22 rst_n = 1'b0; 23 #21; 24 rst_n = 1'b1; 25 end 26 27 endmodule
2. 计数模块:count的源码如下:
1 module count( 2 input clk , 3 input rst_n , 4 input start , 5 input stop , 6 7 output wire[3:0] s_l , 8 output wire[3:0] s_h , 9 output wire[3:0] f_l , 10 output wire[3:0] f_h , 11 12 output reg LED 13 14 ); 15 16 reg flag ; 17 reg [15:0] count ; 18 19 always @(posedge clk or negedge rst_n) begin 20 if(!rst_n) 21 flag <= 1'b0; 22 else if(!start) 23 flag <= 1'b1; 24 else if(!stop) 25 flag <= 1'b0; 26 else 27 flag <= flag; 28 end 29 30 always @(posedge clk or negedge rst_n) begin 31 if(!rst_n) 32 count <= 16'd0; 33 else if(flag == 1'b1) begin 34 if(count == 2021) 35 count <= count; 36 else 37 count <= count + 1'b1; 38 end 39 else 40 count <= count; 41 end 42 43 always @(posedge clk or negedge rst_n) begin 44 if(!rst_n) 45 LED <= 1'b0; 46 else if(count == 2021) 47 LED <= 1'b1; 48 else 49 LED <= LED; 50 51 end 52 53 assign s_l = count % 10; // 个位 54 assign s_h = count / 10 % 10; // 十位 55 assign f_l = count / 100 % 10; // 百位 56 assign f_h = count / 1000 % 10; // 千位 57 58 59 endmodule
仿真代码testbench:
1 `timescale 1ns/1ps 2 3 module count_tb; 4 reg clk ; 5 reg rst_n ; 6 reg start ; 7 reg stop ; 8 9 wire [3:0] s_l ; 10 wire [3:0] s_h ; 11 wire [3:0] f_l ; 12 wire [3:0] f_h ; 13 14 count count_inst( 15 .clk ( clk ), 16 .rst_n ( rst_n ), 17 .start ( start ), 18 .stop ( stop ), 19 .s_l ( s_l ), 20 .s_h ( s_h ), 21 .f_l ( f_l ), 22 .f_h ( f_h ) 23 ); 24 25 initial 26 clk = 1'b0; 27 always #10 clk = ~clk; 28 29 initial 30 begin 31 #1; 32 rst_n = 1'b0; 33 start = 1'b1; 34 stop = 1'b1; 35 #21; 36 rst_n = 1'b1; 37 #50; 38 start = 1'b0; 39 #30; 40 start = 1'b1; 41 #1000; 42 stop = 1'b0; 43 #30; 44 stop = 1'b1; 45 end 46 47 endmodule
3. 显示模块:disp 的源码如下:
1 module disp( 2 input clk , 3 input rst_n , 4 5 input [3:0] s_l , 6 input [3:0] s_h , 7 input [3:0] f_l , 8 input [3:0] f_h , 9 10 output reg[6:0] HEX0 , 11 output reg[6:0] HEX1 , 12 output reg[6:0] HEX2 , 13 output reg[6:0] HEX3 14 15 ); 16 17 18 always@(s_l) begin 19 case(s_l) 20 4'b0000:HEX0[6:0]=7'b100_0000; 21 4'b0001:HEX0[6:0]=7'b111_1001; 22 4'b0010:HEX0[6:0]=7'b010_0100; 23 4'b0011:HEX0[6:0]=7'b011_0000; 24 4'b0100:HEX0[6:0]=7'b001_1001; 25 4'b0101:HEX0[6:0]=7'b001_0010; 26 4'b0110:HEX0[6:0]=7'b000_0010; 27 4'b0111:HEX0[6:0]=7'b111_1000; 28 4'b1000:HEX0[6:0]=7'b000_0000; 29 4'b1001:HEX0[6:0]=7'b001_1000; 30 default:HEX0[6:0]=7'b000_1110; 31 endcase 32 end 33 34 always@(s_h) begin 35 case(s_h) 36 4'b0000:HEX1[6:0]=7'b100_0000; 37 4'b0001:HEX1[6:0]=7'b111_1001; 38 4'b0010:HEX1[6:0]=7'b010_0100; 39 4'b0011:HEX1[6:0]=7'b011_0000; 40 4'b0100:HEX1[6:0]=7'b001_1001; 41 4'b0101:HEX1[6:0]=7'b001_0010; 42 4'b0110:HEX1[6:0]=7'b000_0010; 43 4'b0111:HEX1[6:0]=7'b111_1000; 44 4'b1000:HEX1[6:0]=7'b000_0000; 45 4'b1001:HEX1[6:0]=7'b001_1000; 46 default:HEX1[6:0]=7'b000_1110; 47 endcase 48 end 49 50 always@(f_l) begin 51 case(f_l) 52 4'b0000:HEX2[6:0]=7'b100_0000; 53 4'b0001:HEX2[6:0]=7'b111_1001; 54 4'b0010:HEX2[6:0]=7'b010_0100; 55 4'b0011:HEX2[6:0]=7'b011_0000; 56 4'b0100:HEX2[6:0]=7'b001_1001; 57 4'b0101:HEX2[6:0]=7'b001_0010; 58 4'b0110:HEX2[6:0]=7'b000_0010; 59 4'b0111:HEX2[6:0]=7'b111_1000; 60 4'b1000:HEX2[6:0]=7'b000_0000; 61 4'b1001:HEX2[6:0]=7'b001_1000; 62 default:HEX2[6:0]=7'b000_1110; 63 endcase 64 end 65 66 always@(f_h) begin 67 case(f_h) 68 4'b0000:HEX3[6:0]=7'b100_0000; 69 4'b0001:HEX3[6:0]=7'b111_1001; 70 4'b0010:HEX3[6:0]=7'b010_0100; 71 4'b0011:HEX3[6:0]=7'b011_0000; 72 4'b0100:HEX3[6:0]=7'b001_1001; 73 4'b0101:HEX3[6:0]=7'b001_0010; 74 4'b0110:HEX3[6:0]=7'b000_0010; 75 4'b0111:HEX3[6:0]=7'b111_1000; 76 4'b1000:HEX3[6:0]=7'b000_0000; 77 4'b1001:HEX3[6:0]=7'b001_1000; 78 default:HEX3[6:0]=7'b000_1110; 79 endcase 80 end 81 82 83 endmodule
仿真代码testbench:
1 `timescale 1ns/1ps 2 module disp_tb; 3 reg clk ; 4 reg rst_n ; 5 reg [3:0] s_l ; 6 reg [3:0] s_h ; 7 reg [3:0] f_l ; 8 reg [3:0] f_h ; 9 wire [6:0] HEX0 ; 10 wire [6:0] HEX1 ; 11 wire [6:0] HEX2 ; 12 wire [6:0] HEX3 ; 13 14 disp disp_inst( 15 .clk ( clk ), 16 .rst_n ( rst_n ), 17 .s_l ( s_l ), 18 .s_h ( s_h ), 19 .f_l ( f_l ), 20 .f_h ( f_h ), 21 .HEX0 ( HEX0 ), 22 .HEX1 ( HEX1 ), 23 .HEX2 ( HEX2 ), 24 .HEX3 ( HEX3 ) 25 ); 26 27 initial 28 clk = 1'b0; 29 always #10 clk = ~clk; 30 31 initial 32 begin 33 #1; 34 rst_n = 1'b0; 35 s_l = 4'd0; 36 s_h = 4'd0; 37 f_l = 4'd0; 38 f_h = 4'd0; 39 #31; 40 rst_n = 1'b1; 41 #50; 42 s_l = 4'd4; 43 s_h = 4'd5; 44 f_l = 4'd6; 45 f_h = 4'd7; 46 #100; 47 s_l = 4'd1; 48 s_h = 4'd2; 49 f_l = 4'd3; 50 f_h = 4'd4; 51 #1005; 52 end 53 54 endmodule 55
4. 顶层模块:shuzizhong 的源码如下:
1 module shuzizhong( 2 input clk , 3 input rst_n , 4 5 input start , 6 input stop , 7 8 output LED , 9 10 output [6:0] HEX0 , 11 output [6:0] HEX1 , 12 output [6:0] HEX2 , 13 output [6:0] HEX3 14 ); 15 16 wire clk_1Hz ; 17 18 wire[3:0] s_l ; 19 wire[3:0] s_h ; 20 wire[3:0] f_l ; 21 wire[3:0] f_h ; 22 23 24 div_clk u0( 25 .clk ( clk ), 26 .rst_n ( rst_n ), 27 .clk_1Hz ( clk_1Hz ) 28 ); 29 30 count u1( 31 .clk ( clk_1Hz ), 32 .rst_n ( rst_n ), 33 .start ( start ), 34 .stop ( stop ), 35 .s_l ( s_l ), 36 .s_h ( s_h ), 37 .f_l ( f_l ), 38 .f_h ( f_h ), 39 .LED ( LED ) 40 ); 41 42 disp u2( 43 .clk ( clk_1Hz ), 44 .rst_n ( rst_n ), 45 .s_l ( s_l ), 46 .s_h ( s_h ), 47 .f_l ( f_l ), 48 .f_h ( f_h ), 49 .HEX0 ( HEX0 ), 50 .HEX1 ( HEX1 ), 51 .HEX2 ( HEX2 ), 52 .HEX3 ( HEX3 ) 53 ); 54 endmodule
仿真代码testbench:
1 `timescale 1ns/1ps 2 module shuzizhong_tb; 3 reg clk ; 4 reg rst_n ; 5 6 reg start ; 7 reg stop ; 8 9 wire LED ; 10 11 wire [6:0] HEX0 ; 12 wire [6:0] HEX1 ; 13 wire [6:0] HEX2 ; 14 wire [6:0] HEX3 ; 15 16 shuzizhong shuzizhong_inst( 17 .clk ( clk ), 18 .rst_n ( rst_n ), 19 .start ( start ), 20 .stop ( stop ), 21 .LED ( LED ), 22 .HEX0 ( HEX0 ), 23 .HEX1 ( HEX1 ), 24 .HEX2 ( HEX2 ), 25 .HEX3 ( HEX3 ) 26 ); 27 28 initial 29 clk = 1'b0; 30 always #10 clk = ~clk; 31 32 initial 33 begin 34 #1; 35 rst_n = 1'b0; 36 start = 1'b1; 37 stop = 1'b1; 38 #21; 39 rst_n = 1'b1; 40 #50; 41 start = 1'b0; 42 #300; 43 start = 1'b1; 44 #1000000000; 45 stop = 1'b0; 46 #300; 47 stop = 1'b1; 48 end 49 50 endmodule
注:
(1)将代码移植到其他平台也是可以的;
(2)按键控制部分没有添加消抖;