当前位置: 首页 > wzjs >正文

网站建站侵权怎么办外贸网络推广的公司

网站建站侵权怎么办,外贸网络推广的公司,自己怎么做 优惠券网站,舞钢做网站FPGA学习(三)——数码管实现四位分秒计数器 目录 FPGA学习(三)——数码管实现四位分秒计数器一、实验要求二、实验思考三、四位分秒计数器实现1、代码实现2、添加按键消抖模块3、添加状态机思想4、模块化重构代码5、实现效果 四、总结 一、实验要求 1、用FPGA控制四个数码管&a…

FPGA学习(三)——数码管实现四位分秒计数器

目录

  • FPGA学习(三)——数码管实现四位分秒计数器
  • 一、实验要求
  • 二、实验思考
  • 三、四位分秒计数器实现
    • 1、代码实现
    • 2、添加按键消抖模块
    • 3、添加状态机思想
    • 4、模块化重构代码
    • 5、实现效果
  • 四、总结

一、实验要求

1、用FPGA控制四个数码管,分别显示分钟、秒钟,计数范围都是0~59。

2、按键控制复位和暂停。当复位时所有计数器归零,当启动/暂停按下,暂停计数,再次接下时继续。

3、采用状态机思想实现。

二、实验思考

1、数码管显示。为了在数码管上显示四位分秒计数器,在DE2-115开发板上使用四位共阳极的七段数码管,如hex3-hex0,分别作为分钟的十位、个位,秒的十位、个位。

2、计数逻辑。秒的计数器是0到59,当秒到59后,分钟加一,秒归零。分钟同样到59后归零。用一个4位的BCD计数器,每个单位用4位表示。例如,秒的个位和十位各用4位二进制码,组合成0-59的范围。

reg [3:0] sec_one; // 0-9
reg	[3:0] sec_ten; // 0-5
reg [3:0] min_one;
reg [3:0] min_ten;/*详细的计数逻辑*/

3、分频逻辑。将50MHz的时钟分频成1Hz的信号,这样每秒钟计数器加一。分频的话,50MHz等于50,000,000 Hz,要得到1Hz,需要计数50,000,000次,需要26位计数器

reg [DIV_WIDTH-1:0] counter;always @(posedge clk or posedge reset) beginif (reset) begincounter <= 0;clk_out <= 0;end else begincounter <= counter + 1;clk_out <= counter[DIV_WIDTH-1];  // 取最高位作为分频输出end
end

4、复位/暂停。可以采用按键作为控制信号,当按键按下时,复位/启动/暂停计数。

	if (reset) begin{sec_ones, sec_tens, min_ones, min_tens} <= 16'd0; // 全部清零end else if (!start_pause) begin // KEY1按下时暂停(低电平有效)

5、状态机。首先要定义系统可能达到的所有状态。可能的状态包有复位状态、运行状态、暂停状态以及空闲状态。此外考虑状态转移的条件和时机,将按键信号作为状态转移的触发条件,同时需要确保状态转移只在按键事件发生时进行一次切换,而不是持续切换。这可能需要边缘检测,即检测按键信号的上升沿或下降沿。同时,每个状态下的行为也需要明确,如:在RUNNING状态下,计数器每秒递增;在IDLE状态下,计数器保持不变,而复位信号无论当前处于什么状态,都应强制回到初始状态。

三、四位分秒计数器实现

1、代码实现

首先,在不考虑状态机的情况下,先来简单的实现一下这个分秒计数器。代码如下 :

module clock(input clk_50m,          // 50MHz系统时钟input reset_btn,        // 复位按键(直接连接)input pause_btn,        // 暂停按键(直接连接)output [7:0] HEX3,      // 分钟十位output [7:0] HEX2,      // 分钟个位output [7:0] HEX1,      // 秒十位output [7:0] HEX0       // 秒个位
);// 内部信号定义
wire clk_1hz;
wire [3:0] min_ten, min_one;
wire [3:0] sec_ten, sec_one;
wire carry;
reg pause_state;            // 暂停状态寄存器// 1Hz时钟生成(简化版)
reg [25:0] clk_div;
always @(posedge clk_50m or posedge reset_btn) beginif (reset_btn) beginclk_div <= 0;endelse beginclk_div <= clk_div + 1;end
end
assign clk_1hz = clk_div[25] & ~pause_state;  // 暂停时停止时钟// 暂停状态控制
always @(posedge clk_50m or posedge reset_btn) beginif (reset_btn) beginpause_state <= 1'b0;endelse if (pause_btn) beginpause_state <= ~pause_state;  // 每次按下切换暂停状态end
end// 秒计数器(0-59)
reg [3:0] sec_one, sec_ten;
always @(posedge clk_1hz or posedge reset_btn) beginif (reset_btn) beginsec_one <= 0;sec_ten <= 0;end else beginif (sec_one == 9) beginsec_one <= 0;if (sec_ten == 5) sec_ten <= 0;else sec_ten <= sec_ten + 1;end else beginsec_one <= sec_one + 1;endend
end
assign carry = (sec_one == 9) && (sec_ten == 5);// 分钟计数器(0-59)
reg [3:0] min_one, min_ten;
always @(posedge carry or posedge reset_btn) beginif (reset_btn) beginmin_one <= 0;min_ten <= 0;end else beginif (min_one == 9) beginmin_one <= 0;if (min_ten == 5) min_ten <= 0;else min_ten <= min_ten + 1;end else beginmin_one <= min_one + 1;endend
end// 数码管显示驱动
function [7:0] digit_to_seg;input [3:0] digit;input dot;begincase(digit)0: digit_to_seg = {dot, 7'b1000000};1: digit_to_seg = {dot, 7'b1111001};2: digit_to_seg = {dot, 7'b0100100};3: digit_to_seg = {dot, 7'b0110000};4: digit_to_seg = {dot, 7'b0011001};5: digit_to_seg = {dot, 7'b0010010};6: digit_to_seg = {dot, 7'b0000010};7: digit_to_seg = {dot, 7'b1111000};8: digit_to_seg = {dot, 7'b0000000};9: digit_to_seg = {dot, 7'b0010000};default: digit_to_seg = {dot, 7'b1111111};endcaseend
endfunctionassign HEX3 = digit_to_seg(min_ten, 1'b1);  // 分十位带小数点
assign HEX2 = digit_to_seg(min_one, 1'b0);
assign HEX1 = digit_to_seg(sec_ten, 1'b1);  // 秒十位带小数点
assign HEX0 = digit_to_seg(sec_one, 1'b0);endmodule

上述代码只是简单的实现,而在实际中,按键输入控制复位和启动/暂停,硬件会有机械抖动,可能导致误触发,因此我们要为上述代码添加上按键的消抖模块。

2、添加按键消抖模块

在编写消抖模块时,通常的做法是使用计数器来检测按键状态的稳定。当检测到按键状态变化时,启动一个计数器,如果在20ms内状态没有变化,则认为按键稳定,输出新的状态。

消抖模块代码如下:

module button_debounce(input clk,          // 50MHz时钟input button_in,    // 原始按键输入output reg button_out  // 消抖后的按键信号
);reg [19:0] counter;     // 20位计数器(50MHz/2^20 ≈ 21ms)
reg button_sync;
reg button_prev;always @(posedge clk) begin// 同步输入信号,防止亚稳态button_sync <= button_in;// 消抖处理逻辑if (button_sync != button_prev) beginbutton_prev <= button_sync;counter <= 0;end else if (counter[19]) begin  // 计数器满(约21ms)button_out <= button_prev;end else begincounter <= counter + 1;end
endendmodule

3、添加状态机思想

module fsm_controller(input clk,input reset,input pause,output reg running_o  // 明确输出端口命名
);// Verilog-2001兼容的状态定义
parameter [1:0] IDLE    = 2'b00,RUNNING = 2'b01,PAUSED  = 2'b10;reg [1:0] current_state, next_state;// 状态寄存器更新
always @(posedge clk or posedge reset) beginif (reset) begincurrent_state <= IDLE;end else begincurrent_state <= next_state;end
end// 状态转移逻辑
always @(*) begincase (current_state)IDLE:    next_state = RUNNING;RUNNING: next_state = pause ? PAUSED : RUNNING;PAUSED:  next_state = pause ? RUNNING : PAUSED;default: next_state = IDLE;endcase
end// 输出逻辑
always @(*) beginrunning_o = (current_state == RUNNING);
endendmodule

4、模块化重构代码

将上述按键消抖模块及状态机思想加入,并模块化代码。完整代码如下:

clock.v

/** 顶层模块:clock_mmss_static_top* 修改说明:明确声明running信号并统一连接*/
module clock(input clk_50m,          // 50MHz系统时钟input reset_btn,        // 按键1 - 复位(KEY0)input pause_btn,        // 按键2 - 暂停/恢复(KEY1)output [7:0] HEX3,      // 分钟十位(最左数码管)output [7:0] HEX2,      // 分钟个位(带小数点)output [7:0] HEX1,      // 秒十位output [7:0] HEX0       // 秒个位(最右数码管)
);// 内部信号定义
wire clk_1hz;
wire reset_pulse, pause_pulse;
wire running;  // 统一使用wire类型连接模块
wire [3:0] min_ten, min_one;
wire [3:0] sec_ten, sec_one;// 实例化时钟分频模块
clock_divider #(.DIV_WIDTH(25)  // 50MHz -> 1Hz (2^25 = 33,554,432)
) u_clock_div (.clk(clk_50m),.reset(reset_pulse),.clk_out(clk_1hz)
);// 实例化按键消抖模块
button_debounce u_reset_debounce (.clk(clk_50m),.button_in(reset_btn),.button_out(reset_pulse)
);button_debounce u_pause_debounce (.clk(clk_50m),.button_in(pause_btn),.button_out(pause_pulse)
);// 实例化状态机控制器(关键修改)
fsm_controller u_fsm (.clk(clk_50m),.reset(reset_pulse),.pause(pause_pulse),.running_o(running)  // 统一端口命名
);// 实例化秒计数器
second_counter u_sec_counter (.clk(clk_1hz),.reset(reset_pulse),.enable(running),  // 直接使用running信号.sec_ten(sec_ten),.sec_one(sec_one),.carry(carry_w)
);// 实例化分钟计数器
minute_counter u_min_counter (.clk(carry_w),.reset(reset_pulse),.enable(running),  // 直接使用running信号.min_ten(min_ten),.min_one(min_one)
);// 实例化静态显示驱动
static_display u_display (.min_ten(min_ten),.min_one(min_one),.sec_ten(sec_ten),.sec_one(sec_one),.HEX3(HEX3),.HEX2(HEX2),.HEX1(HEX1),.HEX0(HEX0)
);endmodule

clock_divider.v

/** 模块名称:clock_divider* 功能:将输入时钟分频为较低频率*/
module clock_divider #(parameter DIV_WIDTH = 25  // 分频计数器位宽
)(input clk,input reset,output reg clk_out
);reg [DIV_WIDTH-1:0] counter;always @(posedge clk or posedge reset) beginif (reset) begincounter <= 0;clk_out <= 0;end else begincounter <= counter + 1;clk_out <= counter[DIV_WIDTH-1];  // 取最高位作为分频输出end
endendmodule

button_debounce.v

/** 模块名称:button_debounce* 功能:对机械按键进行消抖处理(约20ms消抖时间)*/
module button_debounce(input clk,          // 50MHz时钟input button_in,    // 原始按键输入output reg button_out  // 消抖后的按键信号
);reg [19:0] counter;     // 20位计数器(50MHz/2^20 ≈ 21ms)
reg button_sync;
reg button_prev;always @(posedge clk) begin// 同步输入信号,防止亚稳态button_sync <= button_in;// 消抖处理逻辑if (button_sync != button_prev) beginbutton_prev <= button_sync;counter <= 0;end else if (counter[19]) begin  // 计数器满(约21ms)button_out <= button_prev;end else begincounter <= counter + 1;end
endendmodule

second_counter.v

module second_counter(input clk,input reset,input enable,output reg [3:0] sec_ten,output reg [3:0] sec_one,output carry  // 改为连续赋值方式
);// 进位条件:59秒时产生1个时钟周期高电平assign carry = (sec_one == 9) && (sec_ten == 5) && enable;always @(posedge clk or posedge reset) beginif (reset) {sec_ten, sec_one} <= 8'h0;else if (enable) beginif ({sec_ten, sec_one} == 8'h59) {sec_ten, sec_one} <= 8'h0;else if (sec_one == 9) beginsec_one <= 0;sec_ten <= sec_ten + 1;endelse sec_one <= sec_one + 1;endend
endmodule

minute_counter.v

/** 模块名称:minute_counter* 功能:实现0-59分钟计数*/
module minute_counter(input clk,          // 由秒进位驱动input reset,input enable,output reg [3:0] min_ten,  // 分十位(0-5)output reg [3:0] min_one   // 分个位(0-9)
);always @(posedge clk or posedge reset) beginif (reset) beginmin_ten <= 0;min_one <= 0;end else if (enable) beginif (min_one == 9) beginmin_one <= 0;if (min_ten == 5) beginmin_ten <= 0;end else beginmin_ten <= min_ten + 1;endend else beginmin_one <= min_one + 1;endend
endendmodule

static_display.v

/** 模块名称:static_display* 功能:驱动4位数码管静态显示MM:SS* DE2-115数码管为共阳极,低电平点亮*/
module static_display(input [3:0] min_ten,  // 分钟十位input [3:0] min_one,  // 分钟个位input [3:0] sec_ten,  // 秒钟十位input [3:0] sec_one,  // 秒钟个位output [7:0] HEX3,    // 分钟十位(最左)output [7:0] HEX2,    // 分钟个位(带小数点)output [7:0] HEX1,    // 秒钟十位output [7:0] HEX0     // 秒钟个位(最右)
);// 数字到7段码的转换(共阳极,低电平点亮)
function [7:0] digit_to_seg;input [3:0] digit;input dot;  // 小数点控制begincase(digit)0: digit_to_seg = {dot, 7'b1000000}; // 01: digit_to_seg = {dot, 7'b1111001}; // 12: digit_to_seg = {dot, 7'b0100100}; // 23: digit_to_seg = {dot, 7'b0110000}; // 34: digit_to_seg = {dot, 7'b0011001}; // 45: digit_to_seg = {dot, 7'b0010010}; // 56: digit_to_seg = {dot, 7'b0000010}; // 67: digit_to_seg = {dot, 7'b1111000}; // 78: digit_to_seg = {dot, 7'b0000000}; // 89: digit_to_seg = {dot, 7'b0010000}; // 9default: digit_to_seg = {dot, 7'b1111111}; // 灭endcaseend
endfunction// 数码管连接(使用HEX2的小数点作为冒号)
assign HEX3 = digit_to_seg(min_ten, 1'b1);  // 分钟十位,点亮小数点
assign HEX2 = digit_to_seg(min_one, 1'b0);  // 分钟个位
assign HEX1 = digit_to_seg(sec_ten, 1'b1);  // 秒钟十位,点亮小数点
assign HEX0 = digit_to_seg(sec_one, 1'b0);  // 秒钟个位endmodule

fsm_controller.v

/** 模块名称:fsm_controller*/
module fsm_controller(input clk,input reset,input pause,output reg running_o  // 明确输出端口命名
);// Verilog-2001兼容的状态定义
parameter [1:0] IDLE    = 2'b00,RUNNING = 2'b01,PAUSED  = 2'b10;reg [1:0] current_state, next_state;// 状态寄存器更新
always @(posedge clk or posedge reset) beginif (reset) begincurrent_state <= IDLE;end else begincurrent_state <= next_state;end
end// 状态转移逻辑
always @(*) begincase (current_state)IDLE:    next_state = RUNNING;RUNNING: next_state = pause ? PAUSED : RUNNING;PAUSED:  next_state = pause ? RUNNING : PAUSED;default: next_state = IDLE;endcase
end// 输出逻辑
always @(*) beginrunning_o = (current_state == RUNNING);
endendmodule

5、实现效果

分秒计数器

四、总结

在这次基于DE2-115开发板的四位分秒计数器设计实验中,我深刻体会到了数字系统设计的完整流程与工程思维的重要性。从最初简单的分频计数到最终的模块化重构,整个过程让我对FPGA开发有了更立体的认识。通过引入消抖模块并优化参数,最终实现了可靠的按键检测。而三段式状态机的设计,不仅让逻辑更清晰,调试效率也大幅提升。最让我受益的是最后的模块化重构过程,将系统拆分为功能独立的模块,提高了代码复用性。

http://www.dtcms.com/wzjs/542353.html

相关文章:

  • 招聘网站开发计划百度竞价排名服务
  • 涪陵建设工程信息网站dz网站标题
  • 网站竞争对手分析有限责任公司破产法人承担的责任
  • 宁波网站建设排名手机怎么制作网页
  • 建筑公司网站内容网站维护步骤
  • 做实验学编程的网站湘潭学校网站建设 磐石网络专注
  • 网站项目计划书模板范文网上商店网站设计
  • 阿里巴巴网站是怎么做的怎么搜索整个网站内容
  • 备案查询站长工具海口小程序制作公司
  • 电子商城网站建设 模板互联网产品设计网站
  • 网站推广制作有口碑的免费网站建设
  • 绵阳市公司网站建设wordpress301跳转插件
  • 做一个交易平台网站的成本合肥互联网公司
  • 网站开发属于什么科目wordpress linux 权限
  • 素马网站设计公司淘点金wordpress插件
  • 原创作文网站wordpress标签云添加
  • 网站优化改动怎么做每平每方设计家官网
  • 网站的开发建设费公司产品推广方案
  • 织梦网站手机页怎么做中国菲律宾南海开战
  • 襄樊北京网站建设兰州网新公司
  • 泰安网站建设公司排名郑州做网站首选九零后网络
  • 江苏省工程建设标准定额网站网站开发可以用gif吗
  • 网站让女友做网站模特网站内容与标题的区别
  • 制作企业网站公司排名珠海电脑自己建网站
  • 凡科网做网站能达到什么效果个人网站做跳转怎么弄
  • 做网站能接到项目工程吗建设企业网站是静态还是动态好
  • wordpress 角色和权限管理seo优化知识总结
  • 衡阳县专业做淘宝网站托管竞价账户哪家好
  • 网站vps广东专业网站开发
  • 网站招标书怎么做WordPress安卓APP不能绑定