赞
踩
RTL代码:
- module seg_led_static(
- input sys_clk,
- input sys_rst,
- output [5:0] sel,
- output reg [7:0]seg_led
- );
-
- reg [24:0] cnt; //25M分频计数器 -> 0.5s
- reg [3:0] num; // 显示控制
- reg flag; // 增减标志位 1增
-
- assign sel = 6'd0;
- // 计时模块
- always @(posedge sys_clk or negedge sys_rst) begin
- if (!sys_rst)
- cnt <= 25'd0;
- else if (cnt == 25'd5)
- cnt <= 25'd0;
- else
- cnt <= cnt + 1'd1;
- end
- // 显示控制模块
- always @(posedge sys_clk or negedge sys_rst) begin
- if (!sys_rst) begin
- num <= 4'd0;
- flag <= 1'd1;
- end
- else begin
- if (flag == 1'd1) begin
- if (num >= 4'hf)
- flag <= 1'd0;
- else begin
- if (cnt == 25'd5)
- num <= num + 1'h1;
- else
- num <= num;
- end
- end
- else begin
- if (num <= 4'h0)
- flag <= 1'd1;
- else begin
- if (cnt == 25'd5)
- num <= num - 1'h1;
- else
- num <= num;
- end
- end
- end
- end
-
- // 显示模块
- always @(posedge sys_clk or negedge sys_rst) begin
- if (!sys_rst)
- seg_led <= 8'b11111111;
- else
- case (num)
- 4'h0: seg_led <= 8'b1100_0000;
- 4'h1: seg_led <= 8'b1111_1001;
- 4'h2: seg_led <= 8'b1010_0100;
- 4'h3: seg_led <= 8'b1011_0000;
- 4'h4: seg_led <= 8'b1001_1001;
- 4'h5: seg_led <= 8'b1001_0010;
- 4'h6: seg_led <= 8'b1000_0010;
- 4'h7: seg_led <= 8'b1111_1000;
- 4'h8: seg_led <= 8'b1000_0000;
- 4'h9: seg_led <= 8'b1001_0000;
- 4'hA: seg_led <= 8'b1000_1000;
- 4'hB: seg_led <= 8'b1000_0011;
- 4'hC: seg_led <= 8'b1100_0110;
- 4'hD: seg_led <= 8'b1010_0001;
- 4'hE: seg_led <= 8'b1000_0110;
- 4'hF: seg_led <= 8'b1000_1110;
- endcase
- end
- endmodule
- `timescale 1ns/1ns
- module seg_led_static_tb();
-
- reg sys_clk;
- reg sys_rst;
- wire [5:0] sel;
- wire [7:0] seg_led;
-
- always #10 sys_clk = ~ sys_clk;
- initial begin
- sys_clk <= 1'd0;
- sys_rst <= 1'd0;
- # 40 sys_rst <= 1'd1;
- end
- seg_led_static u1(
- sys_clk,
- sys_rst,
- sel,
- seg_led
- );
- endmodule
过程中有这么一个顾虑的问题:
当flag = 1,num = 4'hf 时,当前时钟下flag<=0,num锁存。在下个时钟上升沿到来时,flag取得0值,num取得锁存值4'hf,cnt取得新计数值,如果cnt达到上限值时,num<=num-1,即在接下来一个时钟上升沿时,num = 4'he. 不存在因为flag变化时导致num持续保持的问题。
基于modelsim的时序分析:
设计思路:
RTL代码:
1、Top module
- module seg_led_danymic_top(
- input sys_clk,
- input sys_rst,
- output [5:0] sel,
- output [7:0] seg_led
- );
-
- wire bcd_clk;
- wire sel_flag;
-
- wire [23:0] data;
- wire [3:0] data0;
- wire [3:0] data1;
- wire [3:0] data2;
- wire [3:0] data3;
- wire [3:0] data4;
- wire [3:0] data5;
-
-
- wire en0;
- wire en1;
- wire en2;
- wire en3;
- wire en4;
- wire en5;
-
- assign data = {data5,data4,data3,data2,data1,data0};
-
- assign en0 = 1'd1;
- assign en1 = (data0 == 4'd9) ? 1'd1 : 1'd0;
- assign en2 = ({data1, data0} == 8'h99) ? 1'd1 : 1'd0;
- assign en3 = ({data2, data1, data0} == 12'h999) ? 1'd1 : 1'd0;
- assign en4 = ({data3, data2, data1, data0} == 16'h9999) ? 1'd1 : 1'd0;
- assign en5 = ({data4,data3,data2,data1,data0}==20'h99999) ? 1'd1 : 1'd0;
-
-
- // 时钟模块
- count cnt1(sys_clk, sys_rst, bcd_clk, sel_flag);
-
- // 扫描显示模块
- scan_display scan1(
- .sys_clk(sys_clk),
- .sys_rst(sys_rst),
- .sel_flag(sel_flag),
- .data(data),
- .sel(sel),
- .seg_led(seg_led)
- );
-
- // 例化6个BCD计数器作为各个数码段的显示值
- bcd_cnt u1(bcd_clk, sys_rst, en0, data0);
- bcd_cnt u2(bcd_clk, sys_rst, en1, data1);
- bcd_cnt u3(bcd_clk, sys_rst, en2, data2);
- bcd_cnt u4(bcd_clk, sys_rst, en3, data3);
- bcd_cnt u5(bcd_clk, sys_rst, en4, data4);
- bcd_cnt u6(bcd_clk, sys_rst, en5, data5);
-
- endmodule
-
2、计时模块
- module count(
- input sys_clk,
- input sys_rst,
- output reg bcd_clk,
- output reg sel_flag
- );
-
- reg [22:0] cnt_seg;
- reg [18:0] cnt_sel;
- reg sel_clk;
-
- // 5M分频计数器 -> 10Hz(0.1s)用于bcd计数器的时钟信号
- always @(posedge sys_clk or negedge sys_rst) begin
- if (!sys_rst) begin
- cnt_seg <= 23'd0;
- bcd_clk <= 1'd0;
- end
- else if (cnt_seg == 23'd2_499_999) begin
- cnt_seg <= 23'd0;
- bcd_clk <= ~ bcd_clk;
- end
- else begin
- cnt_seg <= cnt_seg + 1'd1;
- bcd_clk <= bcd_clk;
- end
- end
- // 计时模块 6ms -> 用于位选
- always @(posedge sys_clk or negedge sys_rst) begin
- if (!sys_rst) begin
- cnt_sel <= 19'd0;
- sel_flag <= 1'd0;
- end
- else if (cnt_sel == 19'd29_999) begin
- cnt_sel <= 19'd0;
- sel_flag <= 1'd1;
- end
- else begin
- cnt_sel <= cnt_sel + 1'd1;
- sel_flag <= 1'd0;
- end
- end
- endmodule
3、BCD计数器模块
- module bcd_cnt(
- input clk,
- input rst,
- input en,
- output reg [3:0] data
- );
-
- always @(posedge clk or negedge rst) begin
- if (!rst)
- data <= 4'd0;
- else if (en == 1'd1) begin
- if (data == 4'd9)
- data <= 4'd0;
- else
- data <= data + 1'd1;
- end
- else
- data <= data;
- end
- endmodule
4、扫描显示模块
- module scan_display(
- input sys_clk,
- input sys_rst,
- input sel_flag,
- input [23:0]data,
- output reg [5:0] sel,
- output reg [7:0] seg_led
- );
-
- reg [2:0] cnt_sel_flag;
- reg [3:0] seg_reg; // 用于存放每位数码管的待翻译的数据
-
- // 位选状态控制计数器
- always @(posedge sys_clk or negedge sys_rst) begin
- if (!sys_rst)
- cnt_sel_flag <= 3'd0;
- else if (sel_flag == 1'd1) begin
- if (cnt_sel_flag == 3'd5)
- cnt_sel_flag <= 3'd0;
- else
- cnt_sel_flag <= cnt_sel_flag + 1'd1;
- end
- else
- cnt_sel_flag <= cnt_sel_flag;
- end
- // 位选控制器
- always @(posedge sys_clk or negedge sys_rst) begin
- if (!sys_rst)
- sel <= 6'b111111;
- else begin
- case (cnt_sel_flag)
- 3'd0: begin
- sel <= 6'b111110;
- seg_reg <= data[3:0];
- end
- 3'd1: begin
- sel <= 6'b111101;
- seg_reg <= data[7:4];
- end
- 3'd2: begin
- sel <= 6'b111011;
- seg_reg <= data[11:8];
- end
- 3'd3: begin
- sel <= 6'b110111;
- seg_reg <= data[15:12];
- end
- 3'd4: begin
- sel <= 6'b101111;
- seg_reg <= data[19:16];
- end
- 3'd5: begin
- sel <= 6'b011111;
- seg_reg <= data[23:20];
- end
- endcase
- end
- end
-
- // 段显控制器
- always @(posedge sys_clk or negedge sys_rst) begin
- if (!sys_rst)
- seg_led <= 8'b11111111;
- else begin
- case (seg_reg)
- 4'h0: seg_led <= 8'b1100_0000;
- 4'h1: seg_led <= 8'b1111_1001;
- 4'h2: seg_led <= 8'b1010_0100;
- 4'h3: seg_led <= 8'b1011_0000;
- 4'h4: seg_led <= 8'b1001_1001;
- 4'h5: seg_led <= 8'b1001_0010;
- 4'h6: seg_led <= 8'b1000_0010;
- 4'h7: seg_led <= 8'b1111_1000;
- 4'h8: seg_led <= 8'b1000_0000;
- 4'h9: seg_led <= 8'b1001_0000;
- endcase
- end
- end
- endmodule
-
Testbench:
- `timescale 1ns/1ns
- module seg_led_dynamic_tb();
- reg sys_clk;
- reg sys_rst;
- wire [5:0] sel;
- wire [7:0] seg_led;
-
- always #10 sys_clk = ~ sys_clk;
- initial begin
- sys_clk <= 1'd0;
- sys_rst <= 1'd0;
- # 40 sys_rst <= 1'd1;
- end
- seg_led_danymic_top a1(
- sys_clk,
- sys_rst,
- sel,
- seg_led
- );
- endmodule
基于Modelsim的时序分析:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。