今天收到一个朋友的请求,帮忙看他们学校自制的一个Cyclone I 的古老的板子,仔细一看板子的电路原理图,没有按键、没有拨码开关、没有复位,整个板子的芯片外围电路只有四个共阴极的七段数码管和16个LED灯,需要编写一个代码测试一下。
功能要求如下:
(1)板子的输入端口之后一个时钟信号 clk ,输出信号为四位的位选信号 sel,八位的段选信号 seg;
(2)板子上电之后的最初状态是4个数码管显示 0000,随后,最左边两个数码管显示 59,表征 59 分钟,最右边两个数码管显示 59,表示 59 秒,每隔 1 秒,数码管秒计数减 1 ,直到最后显示为 0000 。其实质就是倒计时 1 小时,周而复始。
总结:
这个逻辑挺简单的,本质上就是计数器的应用,困难的地方在于没有复位,无论是同步复位还是异步复位都没有,所以就需要用到寄存器赋初值的知识点,这里用到了initial 语句来赋初值。如 initial count = 4‘d0;
实验结果证明,即便是没有复位也是可以实现逻辑控制的,initial 在一些场合也是可以被综合的。
Verilog HDL 程序如下:
1 // ********************************************************************************* 2 // Project Name : 3 // Email : 4 // Create Time : 2020// : 5 // Module Name : 6 // editor : Qing 7 // Version : Rev1.0.0 8 // ********************************************************************************* 9 10 11 module count_disp( 12 input clk , 13 14 output reg[3:0] sel , 15 output reg[7:0] seg 16 ); 17 18 //======================================================================== 19 // =========== Define Parameter and Internal signals =========== 20 //========================================================================/ 21 22 23 reg [27:0] cnt ; 24 reg [7:0] cnt_miao ; 25 reg [7:0] cnt_fen ; 26 reg [15:0] cnt_move ; 27 reg [2:0] cnt_sel ; 28 reg [3:0] disp_data ; 29 30 wire [3:0] l_miao ; 31 wire [3:0] h_miao ; 32 wire [3:0] l_fen ; 33 wire [3:0] h_fen ; 34 35 36 //============================================================================= 37 //**************************** Main Code ******************************* 38 //============================================================================= 39 40 initial cnt_move = 16‘d0; 41 always @(posedge clk) begin 42 if(cnt_move == 49999) // 49999 43 cnt_move <= 16‘d0; 44 else 45 cnt_move <= cnt_move + 1‘b1; 46 end 47 48 initial cnt_sel = 3‘d0; 49 always @(posedge clk) begin 50 if(cnt_move == 49999) begin 51 if(cnt_sel == 3‘d3) 52 cnt_sel <= 3‘d0; 53 else 54 cnt_sel <= cnt_sel + 1‘b1; 55 end 56 else 57 cnt_sel <= cnt_sel; 58 end 59 60 initial cnt = 28‘d0; 61 always @(posedge clk ) begin 62 if(cnt == 49999999) // 49999999 63 cnt <= 28‘d0; 64 else 65 cnt <= cnt + 1‘b1; 66 end 67 68 69 initial cnt_miao = 8‘d59; 70 always @(posedge clk) begin 71 if(cnt == 49999999) begin ////////////// 72 if(cnt_miao == 0) 73 cnt_miao <= 59; 74 else 75 cnt_miao <= cnt_miao - 1‘b1; 76 end 77 else 78 cnt_miao <= cnt_miao; 79 end 80 81 initial cnt_fen = 8‘d59; 82 always @(posedge clk ) begin 83 if((cnt_miao == 0) && (cnt == 49999999)) begin ////////// 84 if(cnt_fen == 0) 85 cnt_fen <= 8‘d59; 86 else 87 cnt_fen <= cnt_fen - 1‘b1; 88 end 89 else 90 cnt_fen <= cnt_fen; 91 end 92 93 assign l_miao = cnt_miao % 10; 94 assign h_miao = cnt_miao / 10 % 10; 95 96 assign l_fen = cnt_fen % 10; 97 assign h_fen = cnt_fen / 10 % 10; 98 99 100 initial sel = 4‘b1111; 101 initial disp_data = 4‘d0; 102 always @(posedge clk) begin 103 if(cnt_move == 49999) begin 104 case(cnt_sel) 105 0: begin sel <= 4‘b0001; disp_data <= l_miao; end // 共阴极 106 1: begin sel <= 4‘b0010; disp_data <= h_miao; end 107 2: begin sel <= 4‘b0100; disp_data <= l_fen ; end 108 3: begin sel <= 4‘b1000; disp_data <= h_fen ; end 109 default: begin sel <= 4‘b1111; disp_data <= 4‘d0; end 110 endcase 111 end 112 end 113 114 always @(posedge clk) begin 115 case(disp_data) 116 0: seg <= 8‘h3f; 117 1: seg <= 8‘h06; 118 2: seg <= 8‘h5B; 119 3: seg <= 8‘h4F; 120 4: seg <= 8‘h66; 121 5: seg <= 8‘h6D; 122 6: seg <= 8‘h7D; 123 7: seg <= 8‘h07; 124 8: seg <= 8‘h7F; 125 9: seg <= 8‘h6F; 126 default: seg <= 8‘h3f; 127 endcase 128 end 129 130 131 endmodule
testbench如下:
1 `timescale 1ns/1ps 2 3 module count_disp_tb; 4 reg clk ; // 时钟信号 5 6 wire [3:0] sel ; // 段选信号 7 wire [7:0] seg ; // 位选信号 8 9 count_disp count_disp_inst( 10 .clk ( clk ), 11 .sel ( sel ), 12 .seg ( seg ) 13 ); 14 15 initial 16 clk = 1‘b0; 17 always #10 clk = ~clk; 18 19 endmodule
原文:https://www.cnblogs.com/571328401-/p/14772801.html