该单稳态verilog模块,要求触发当输入收到由低变高后,输出一个高电平。高电平的时间根据五个输入离散量值delaycount延时,总延时时间等于90us乘delaycount。模块输入包括reset#异步复位,clk为50Mhz。
Monostable,Verilog模块。该模块在检测到输入信号的上升沿后,会输出一个固定宽度的脉冲,脉冲宽度由delaycount参数控制。
```verilog
module monostable_pulse (
input wire clk, // 50MHz时钟
input wire rst_n, // 异步低电平复位
input wire trigger, // 触发信号输入
input wire [4:0] delaycount, // 延时计数(0-31)
output reg pulse_out // 脉冲输出
);
// ============================
// 参数定义
// ============================
// 50MHz时钟周期 = 20ns
// 90us = 90,000ns = 4500个时钟周期 (20ns * 4500 = 90us)
parameter CLK_PERIOD_NS = 20; // 时钟周期20ns
parameter BASE_DELAY_US = 90; // 基本延时90us
parameter BASE_CYCLES = 4500; // 90us对应的时钟周期数 (90,000ns / 20ns)
// ============================
// 内部信号定义
// ============================
reg trigger_d1, trigger_d2; // 触发器用于边沿检测
wire trigger_rising; // 上升沿检测信号
reg [15:0] counter; // 计数器(最大支持31*4500=139500 < 2^17)
reg state; // 状态机:0=空闲,1=脉冲输出
// ============================
// 上升沿检测
// ============================
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
trigger_d1 <= 1'b0;
trigger_d2 <= 1'b0;
end else begin
trigger_d1 <= trigger;
trigger_d2 <= trigger_d1;
end
end
assign trigger_rising = trigger_d1 && !trigger_d2;
// ============================
// 状态机和控制逻辑
// ============================
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
state <= 1'b0;
counter <= 16'd0;
pulse_out <= 1'b0;
end else begin
case (state)
// 空闲状态,等待触发
1'b0: begin
pulse_out <= 1'b0;
if (trigger_rising && (delaycount != 5'd0)) begin
state <= 1'b1;
counter <= BASE_CYCLES * delaycount - 1'b1; // 计算总延时周期数
pulse_out <= 1'b1;
end
end
// 脉冲输出状态
1'b1: begin
if (counter == 16'd0) begin
state <= 1'b0;
pulse_out <= 1'b0;
end else begin
counter <= counter - 1'b1;
pulse_out <= 1'b1;
end
end
default: begin
state <= 1'b0;
pulse_out <= 1'b0;
end
endcase
end
end
// ============================
// 断言(用于仿真调试)
// ============================
// synthesis translate_off
always @(posedge clk) begin
if (trigger_rising && (delaycount == 5'd0)) begin
display("\[WARNING\] %t: trigger received with delaycount=0, no pulse will be generated", time);
end
end
// synthesis translate_on
endmodule
```
模块功能说明:
- 输入输出接口
· clk:50MHz系统时钟(周期20ns)
· rst_n:异步低电平复位
· trigger:触发信号输入,检测上升沿
· delaycount[4:0]:延时倍数输入(0-31)
· pulse_out:脉冲输出信号
- 延时计算
· 基本延时单位:90us
· 50MHz时钟周期:20ns
· 90us对应的时钟周期数:90,000ns / 20ns = 4500个周期
· 总延时时间 = 90us × delaycount
· 总时钟周期数 = 4500 × delaycount
-
工作流程
-
在空闲状态(state=0)等待触发信号的上升沿
-
检测到上升沿后,检查delaycount是否为0:
· 如果为0,不产生脉冲(有警告信息)
· 如果非0,进入脉冲输出状态(state=1)
-
在脉冲输出状态,计数器从(4500×delaycount-1)递减到0
-
计数器归零后,返回空闲状态
-
使用示例
```verilog
// 实例化示例
monostable_pulse u_monostable (
.clk(clk_50m), // 50MHz时钟
.rst_n(sys_rst_n), // 系统复位
.trigger(btn_press), // 触发信号
.delaycount(5'd10), // 10倍延时 = 900us
.pulse_out(pulse) // 输出脉冲
);
```
- 仿真测试模块(可选)
```verilog
module tb_monostable_pulse;
reg clk;
reg rst_n;
reg trigger;
reg [4:0] delaycount;
wire pulse_out;
// 实例化被测模块
monostable_pulse dut (
.clk(clk),
.rst_n(rst_n),
.trigger(trigger),
.delaycount(delaycount),
.pulse_out(pulse_out)
);
// 时钟生成(50MHz)
initial begin
clk = 0;
forever #10 clk = ~clk; // 20ns周期
end
// 测试激励
initial begin
// 初始化
rst_n = 0;
trigger = 0;
delaycount = 5'd0;
// 复位释放
#100 rst_n = 1;
// 测试1:延时1倍(90us)
#200;
delaycount = 5'd1;
trigger = 1;
#40 trigger = 0;
// 测试2:延时5倍(450us)
#500000; // 等待500us
delaycount = 5'd5;
trigger = 1;
#40 trigger = 0;
// 测试3:delaycount=0的情况
#500000;
delaycount = 5'd0;
trigger = 1;
#40 trigger = 0;
#1000000;
$finish;
end
// 波形输出
initial begin
$dumpfile("monostable.vcd");
$dumpvars(0, tb_monostable_pulse);
end
endmodule
```
注意事项:
-
当delaycount=0时,模块不会产生脉冲输出(仿真时会显示警告)
-
最大延时时间:31 × 90us = 2.79ms
-
模块使用同步设计,适合在Zynq FPGA中实现
-
可根据需要调整BASE_DELAY_US参数来改变基本延时单位