生成脉冲模块-clk_500ms

本文介绍了一种使用Verilog HDL实现500ms定时器的方法。该定时器基于50MHz的板载时钟,通过计数器达到预设阈值来产生周期性的脉冲信号。
原理是将板载时钟进行改变。
module timer_500ms(input clk,output reg clk_500ms);
reg [24:0] cnt;//要表示的最大的数是12500500
initial begin//initial语句:此语句只执行一次。
cnt [24:0] <=0;//<=是非阻塞性赋值
clk_500ms <= 0;
end
always@(posedge clk)//上升沿触发循环,板载时钟是50MHz
if(cnt>=12_500_000) begin//忽略下划线,12_500_000/50MHZ=0.25s
cnt<=0;
clk_500ms <= ~clk_500ms;//0.25S发生一次变化,产生脉冲信号
end
else begin
     cnt<=cnt+1;
end
endmodule
详细解释以下所有代码`timescale 1ns / 1ps module led_controller_top ( input wire clk100m, // 100MHz 主时钟 input wire rst_n, // 复位按钮(通常连接到BTNC) input wire [3:0] btn_c, // BTN0~BTN3,低有效 output wire [8:0] led // LED0~LED8 ); wire clk_1hz, clk_5hz, clk_10hz; wire [3:0] btn_debounced; // 分频模块 clk_divider u_clkdiv ( .clk_in(clk100m), .rst_n(rst_n), .clk_1hz(clk_1hz), .clk_5hz(clk_5hz), .clk_10hz(clk_10hz) ); // 四个按键分别消抖 genvar i; generate for (i = 0; i < 4; i = i + 1) begin : debouncer_gen debounce u_debounce ( .clk(clk100m), .rst_n(rst_n), .btn_in(btn_c[i]), .btn_out(btn_debounced[i]) ); end endgenerate // 状态机主控 led_fsm u_fsm ( .clk(clk100m), .rst_n(rst_n), .key1(btn_debounced[0]), .key2(btn_debounced[1]), .key3(btn_debounced[2]), .key4(btn_debounced[3]), .clk_1hz(clk_1hz), .clk_5hz(clk_5hz), .clk_10hz(clk_10hz), .led(led) ); endmodule `timescale 1ns / 1ps module clk_divider ( input wire clk_in, // 输入时钟:100MHz input wire rst_n, // 低电平复位(异步) output reg clk_1hz, // 输出:1Hz output reg clk_5hz, // 输出:5Hz output reg clk_10hz // 输出:10Hz ); // 定义主时钟频率 parameter CLK_FREQ = 100_000_000; // 100MHz // 各分频计数器(分别用于1Hz, 5Hz, 10Hz) reg [31:0] count_1hz; reg [26:0] count_5hz; // ~5Hz: 计数到 10,000,000 reg [24:0] count_10hz; // ~10Hz: 计数到 5,000,000 // ------------------------ // 生成 1Hz 时钟 // 周期 = 1s → 半周期 = 500ms → 计数 50,000,000 个 100MHz 周期 // ------------------------ always @(posedge clk_in or negedge rst_n) begin if (!rst_n) begin count_1hz <= 0; clk_1hz <= 0; end else begin if (count_1hz >= 50_000_000 - 1) begin clk_1hz <= ~clk_1hz; // 翻转输出 count_1hz <= 0; // 重载计数器 end else begin count_1hz <= count_1hz + 1; end end end // ------------------------ // 生成 5Hz 时钟 // 周期 = 200ms → 半周期 = 100ms → 计数 10,000,000 // ------------------------ always @(posedge clk_in or negedge rst_n) begin if (!rst_n) begin count_5hz <= 0; clk_5hz <= 0; end else begin if (count_5hz >= 10_000_000 - 1) begin clk_5hz <= ~clk_5hz; count_5hz <= 0; end else begin count_5hz <= count_5hz + 1; end end end // ------------------------ // 生成 10Hz 时钟 // 周期 = 100ms → 半周期 = 50ms → 计数 5,000,000 // ------------------------ always @(posedge clk_in or negedge rst_n) begin if (!rst_n) begin count_10hz <= 0; clk_10hz <= 0; end else begin if (count_10hz >= 5_000_000 - 1) begin clk_10hz <= ~clk_10hz; count_10hz <= 0; end else begin count_10hz <= count_10hz + 1; end end end endmodule `timescale 1ns / 1ps module led_fsm ( input wire clk, // 主时钟 input wire rst_n, // 复位(低有效) input wire key1, // 消抖后的按键信号(低有效 -> 高表示按下) input wire key2, input wire key3, input wire key4, input wire clk_1hz, // 1Hz 节拍 input wire clk_5hz, // 5Hz 节拍 input wire clk_10hz, // 10Hz 节拍 output reg [8:0] led // 9个LED输出 ); // 状态定义 parameter IDLE = 3'd0, LEFT_MOVE = 3'd1, RIGHT_MOVE= 3'd2, BLINK_ALL = 3'd3, LIGHT_8 = 3'd4; // 三段式:状态寄存器 reg [2:0] current_state, next_state; // 第一段:时序逻辑 - 当前状态更新 always @(posedge clk or negedge rst_n) begin if (!rst_n) current_state <= IDLE; else current_state <= next_state; end // 第二段:组合逻辑 - 下一状态判断 always @(*) begin case (current_state) IDLE: if (key1 == 0) next_state = LEFT_MOVE; else if (key2 == 0) next_state = RIGHT_MOVE; else if (key3 == 0) next_state = BLINK_ALL; else if (key4 == 0) next_state = LIGHT_8; else next_state = IDLE; LEFT_MOVE: if (key1 == 1 && key2 == 1 && key3 == 1 && key4 == 1) next_state = IDLE; else next_state = LEFT_MOVE; RIGHT_MOVE: if (key1 == 1 && key2 == 1 && key3 == 1 && key4 == 1) next_state = IDLE; else next_state = RIGHT_MOVE; BLINK_ALL: if (key1 == 1 && key2 == 1 && key3 == 1 && key4 == 1) next_state = IDLE; else next_state = BLINK_ALL; LIGHT_8: if (key1 == 1 && key2 == 1 && key3 == 1 && key4 == 1) next_state = IDLE; else next_state = LIGHT_8; default: next_state = IDLE; endcase end // 第三段:组合逻辑 - 输出解码(Moore型:只依赖当前状态) reg [8:0] shift_reg_left; reg [8:0] shift_reg_right; reg blink_counter; reg [2:0] pos; // 流水灯位置 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin shift_reg_left <= 9'b000000001; shift_reg_right <= 9'b100000000; blink_counter <= 0; pos <= 0; led <= 9'b0; end else begin case (current_state) IDLE: led <= 9'b0; LEFT_MOVE: begin if (clk_5hz) begin // 每次5Hz脉冲移动一次 shift_reg_left <= {shift_reg_left[7:0], shift_reg_left[8]}; led <= shift_reg_left; end end RIGHT_MOVE: begin if (clk_5hz) begin shift_reg_right <= {shift_reg_right[0], shift_reg_right[8:1]}; led <= shift_reg_right; end end BLINK_ALL: begin if (clk_1hz) begin blink_counter <= ~blink_counter; led <= blink_counter ? 9'b111111111 : 9'b000000000; end end LIGHT_8: begin led <= 9'b000001000; // 第8位点亮(索引从0开始,第8位是第9个LED?注意!) // 注意:Basys 3 的LED是LED0~LED8,共9个 // 如果"点亮第8个"是指编号为8的LED,则对应 bit[8] end default: led <= 9'b0; endcase end end endmodule `timescale 1ns / 1ps module debounce ( input wire clk, // 主时钟(如100MHz) input wire rst_n, // 复位 input wire btn_in, // 原始按键输入(低有效) output reg btn_out // 消抖后输出(仍为低有效) ); parameter DEBOUNCE_TIME = 50000; // 约5ms @ 100MHz reg [15:0] counter; reg btn_sync1, btn_sync2; // 同步双触发器防亚稳态 always @(posedge clk or negedge rst_n) begin if (!rst_n) begin btn_sync1 <= 1'b1; btn_sync2 <= 1'b1; end else begin btn_sync1 <= btn_in; btn_sync2 <= btn_sync1; end end always @(posedge clk or negedge rst_n) begin if (!rst_n) begin counter <= 0; btn_out <= 1'b1; end else begin if (btn_sync2 != btn_out) begin counter <= counter + 1; if (counter >= DEBOUNCE_TIME - 1) begin btn_out <= btn_sync2; counter <= 0; end end else begin counter <= 0; end end end endmodule set_property IOSTANDARD LVCMOS33 [get_ports] set_property PACKAGE_PIN U16 [get_ports {led[0]}]; set_property PACKAGE_PIN E19 [get_ports {led[1]}]; set_property PACKAGE_PIN U19 [get_ports {led[2]}]; set_property PACKAGE_PIN V19 [get_ports {led[3]}]; set_property PACKAGE_PIN W18 [get_ports {led[4]}]; set_property PACKAGE_PIN U15 [get_ports {led[5]}]; set_property PACKAGE_PIN U14 [get_ports {led[6]}]; set_property PACKAGE_PIN V14 [get_ports {led[7]}]; set_property PACKAGE_PIN V13 [get_ports {led[8]}]; # 可选:如果你真有一个 LED 接在 N4 上再启用 # set_property PACKAGE_PIN N4 [get_ports {led[8]}]; # === 按键输入(主动低电平)=== set_property PACKAGE_PIN U18 [get_ports {btn_c[0]}]; # BTNC set_property PACKAGE_PIN T18 [get_ports {btn_c[1]}]; # BTNU set_property PACKAGE_PIN W19 [get_ports {btn_c[2]}]; # BTNL set_property PACKAGE_PIN T17 [get_ports {btn_c[3]}]; # BTNR # === 复位输入 === set_property PACKAGE_PIN V17 [get_ports {rst_n}]; # 接 SW0 或独立按键 # === 主时钟输入 === set_property PACKAGE_PIN W5 [get_ports {clk100m}]; # 100MHz crystal # === 创建时钟约束 === create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} [get_ports clk100m] `timescale 1ns / 1ps module tb_led_controller; reg clk100m; reg rst_n; reg [3:0] btn_c; wire [8:0] led; // 实例化顶层 led_controller_top uut ( .clk100m(clk100m), .rst_n(rst_n), .btn_c(btn_c), .led(led) ); // 生成时钟 initial begin clk100m = 0; forever #5 clk100m = ~clk100m; // 100MHz end initial begin // 初始化 rst_n = 0; btn_c = 4'b1111; #100 rst_n = 1; // 按键1按下(左移) #1000 btn_c = 4'b1110; #500000000; // 等待几秒看效果 // 释放 btn_c = 4'b1111; #100000000; // 按键2按下(右移) btn_c = 4'b1101; #500000000; btn_c = 4'b1111; #100000000; // 按键3按下(闪烁) btn_c = 4'b1011; #800000000; btn_c = 4'b1111; #100000000; // 按键4按下(点亮LED8) btn_c = 4'b0111; #500000000; $stop; end endmodule
最新发布
12-08
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity freq_meter is Port ( sys_clk : in std_logic; -- 系统时钟 sys_rst_n : in std_logic; -- 异步复位,低有效 clk_test : in std_logic; -- 待测试时钟,需连接到 c1(可根据实际约束调整) shcp : out std_logic; -- 74HC595 移位时钟输出 stcp : out std_logic; -- 74HC595 存储时钟输出 ds : out std_logic; -- 74HC595 串行数据输出 oe : out std_logic -- 74HC595 输出使能输出 ); end freq_meter; architecture Behavioral of freq_meter is -- 声明 freq_meter_calc 模块 component freq_meter_calc is Port ( sys_clk : in std_logic; sys_rst_n : in std_logic; clk_test : in std_logic; freq : out std_logic_vector(33 downto 0) ); end component; -- 声明 seg_595_dynamic 模块 component seg_595_dynamic is Port ( sys_clk : in std_logic; sys_rst_n : in std_logic; seg_en : in std_logic; sign : in std_logic; data : in std_logic_vector(19 downto 0); point : in std_logic_vector(5 downto 0); shcp : out std_logic; stcp : out std_logic; ds : out std_logic; oe : out std_logic ); end component; -- 内部信号定义 signal freq : std_logic_vector(33 downto 0); signal seg_en : std_logic := '1'; -- 使能数码管显示,可根据需求动态控制 signal sign : std_logic := '0'; -- 符号位,初始为 0,可根据需求调整 signal data : std_logic_vector(19 downto 0); signal point : std_logic_vector(5 downto 0) := "001000"; -- 小数点位置,可根据需求调整 begin -- 实例化 freq_meter_calc 模块 uut_freq_meter_calc : freq_meter_calc Port map ( sys_clk => sys_clk, sys_rst_n => sys_rst_n, clk_test => clk_test, -- 按照要求连接到 clk_test 输入,该输入最终要接 c1(通过引脚约束实现) freq => freq ); -- 对 freq 进行处理,截取低 20 位给 seg_595_dynamic 的 data 端口(可根据实际需求调整处理逻辑) data <= freq(19 downto 0); -- 实例化 seg_595_dynamic 模块 uut_seg_595_dynamic : seg_595_dynamic Port map ( sys_clk => sys_clk, sys_rst_n => sys_rst_n, seg_en => seg_en, sign => sign, data => data, point => point, shcp => shcp, stcp => stcp, ds => ds, oe => oe ); end Behavioral;数码管只有一个亮修改代码
07-02
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity test is Port ( clk_50MHz : in STD_LOGIC; reset : in STD_LOGIC; freq_up : in STD_LOGIC; duty_up : in STD_LOGIC; led1 : out STD_LOGIC; seg : out STD_LOGIC_VECTOR(6 downto 0); an : out STD_LOGIC_VECTOR(3 downto 0) ); end test; architecture Behavioral of test is constant CLK_FREQ : integer := 50_000_000; constant DEBOUNCE_MS : integer := 20; constant DEBOUNCE_TICKS : integer := (CLK_FREQ/1000)*DEBOUNCE_MS; -- 20ms计数值 signal freq_reg : integer range 1 to 200 := 1; -- 1-200 kHz signal duty_reg : integer range 0 to 100 := 50; -- 0-100% signal wave_reg : STD_LOGIC := '0'; -- 按键消抖状态机信号 type debounce_state is (IDLE, WAIT_STABLE); signal freq_state, duty_state : debounce_state := IDLE; signal freq_cnt, duty_cnt : integer range 0 to DEBOUNCE_TICKS-1 := 0; signal freq_stable, duty_stable : STD_LOGIC := '0'; signal freq_prev, duty_prev : STD_LOGIC := '0'; -- 边沿检测信号 signal freq_pulse, duty_pulse : STD_LOGIC := '0'; signal display_num : integer range 0 to 9999 := 0; signal refresh_cnt : integer range 0 to (CLK_FREQ/1000)-1 := 0; signal seg_sel : integer range 0 to 3 := 0; signal period_cnt : integer := 0; signal period_max : integer := CLK_FREQ/1000; -- 1kHz default signal digit : integer range 0 to 9 := 0; begin -- 频率按键消抖状态机 process(clk_50MHz) begin if rising_edge(clk_50MHz) then if reset = '1' then freq_state <= IDLE; freq_cnt <= 0; freq_stable <= '0'; else case freq_state is when IDLE => if freq_up /= freq_stable then freq_state <= WAIT_STABLE; freq_cnt <= 0; end if; when WAIT_STABLE => if freq_cnt < DEBOUNCE_TICKS-1 then freq_cnt <= freq_cnt + 1; else freq_stable <= freq_up; -- 更新稳定信号 freq_state <= IDLE; end if; end case; end if; end if; end process; -- 占空比按键消抖状态机 process(clk_50MHz) begin if rising_edge(clk_50MHz) then if reset = '1' then duty_state <= IDLE; duty_cnt <= 0; duty_stable <= '0'; else case duty_state is when IDLE => if duty_up /= duty_stable then duty_state <= WAIT_STABLE; duty_cnt <= 0; end if; when WAIT_STABLE => if duty_cnt < DEBOUNCE_TICKS-1 then duty_cnt <= duty_cnt + 1; else duty_stable <= duty_up; -- 更新稳定信号 duty_state <= IDLE; end if; end case; end if; end if; end process; -- 边沿检测电路(生成单周期脉冲- 修复错误 process(clk_50MHz) begin if rising_edge(clk_50MHz) then freq_prev <= freq_stable; duty_prev <= duty_stable; -- 检测上升沿(使用if-else替代条件赋值) if (freq_stable = '1' and freq_prev = '0') then freq_pulse <= '1'; else freq_pulse <= '0'; end if; if (duty_stable = '1' and duty_prev = '0') then duty_pulse <= '1'; else duty_pulse <= '0'; end if; end if; end process; -- 频率和占空比控制 process(clk_50MHz) begin if rising_edge(clk_50MHz) then if reset = '1' then freq_reg <= 1; duty_reg <= 50; period_max <= CLK_FREQ/1000; -- 1kHz else -- 频率增加:检测单脉冲 if freq_pulse = '1' then if freq_reg >= 200 then freq_reg <= 1; else freq_reg <= freq_reg + 1; end if; -- 确保最小频率为1kHz if freq_reg > 0 then period_max <= CLK_FREQ / (freq_reg * 1000); else period_max <= CLK_FREQ/1000; end if; end if; -- 占空比增加:检测单脉冲(10%步进) if duty_pulse = '1' then if duty_reg >= 90 then duty_reg <= 0; else duty_reg <= duty_reg + 10; end if; end if; display_num <= freq_reg; -- 显示当前频率(kHz) end if; end if; end process; -- PWM生成 process(clk_50MHz) variable threshold : integer; begin if rising_edge(clk_50MHz) then -- 防止除以零错误 if period_max > 0 then threshold := (period_max * duty_reg) / 100; else threshold := 0; end if; if period_cnt < period_max-1 then period_cnt <= period_cnt + 1; else period_cnt <= 0; end if; if period_cnt < threshold then wave_reg <= '1'; else wave_reg <= '0'; end if; end if; end process; led1 <= wave_reg; -- 7段数码管显示 process(clk_50MHz) begin if rising_edge(clk_50MHz) then if refresh_cnt < (CLK_FREQ/1000)-1 then refresh_cnt <= refresh_cnt + 1; else refresh_cnt <= 0; seg_sel <= seg_sel + 1; if seg_sel = 3 then seg_sel <= 0; end if; end if; -- 使用单独的case语句处理每个分支 case seg_sel is when 0 => an <= "1110"; digit <= display_num mod 10; when 1 => an <= "1101"; digit <= (display_num / 10) mod 10; when 2 => an <= "1011"; digit <= (display_num / 100) mod 10; when 3 => an <= "0111"; digit <= display_num / 1000; end case; -- 单独处理段选信号 case digit is when 0 => seg <= "1000000"; when 1 => seg <= "1111001"; when 2 => seg <= "0100100"; when 3 => seg <= "0110000"; when 4 => seg <= "0011001"; when 5 => seg <= "0010010"; when 6 => seg <= "0000010"; when 7 => seg <= "1111000"; when 8 => seg <= "0000000"; when 9 => seg <= "0010000"; when others => seg <= "1111111"; end case; end if; end process; end Behavioral;要在显示屏上显示正在输出的频率怎么修改
06-28
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值