如何在结构化Verilog中引入延迟?含ADDR与WR时序约束实现问询
嗨,咱们一步步拆解你关于结构化Verilog中引入延迟,以及实现特定建立时间需求的这两个问题:
1. 结构化Verilog中引入延迟的常用方法
结构化Verilog主要基于门级原语、模块实例化和数据流描述搭建电路,引入延迟的方式主要有以下几种,需要注意的是:这些延迟主要用于仿真验证,大部分综合工具会忽略它们——实际硬件的延迟由工艺、布局布线决定,不能依赖代码延迟实现硬件功能:
门级原语自带延迟:在实例化与门、或门、触发器等基础门原语时,直接添加延迟参数。比如:
// 定义时间尺度:1ns为单位,1ps为精度 `timescale 1ns/1ps // 与门实例,信号从输入到输出延迟2ns and #(2) and_inst(output_wire, input1, input2); // 也可以分别指定上升、下降、关断延迟:#(上升延迟, 下降延迟, 关断延迟) nand #(1, 2, 3) nand_inst(out, a, b);线网延迟:直接给线网类型变量定义延迟,信号在这条线上传播时会延迟指定时间:
// data_wire上的信号变化会延迟3ns才传递到连接的模块/门 wire #(3) data_wire;数据流延迟(assign语句):在assign的数据流描述中添加延迟,属于结构化Verilog的范畴,适合组合逻辑的延迟建模:
// input信号经过1ns延迟后赋值给output assign #1 output_wire = input1 & input2;
2. 实现ADDR相对于WR上升沿1ns的建立时间需求
根据你的需求:时钟周期10ns,每个周期内先给ADDR赋值,1ns后将WR从0置为1,同时满足ADDR在WR上升沿前1ns稳定的建立时间约束。以下是两种可行的实现方式:
方式1:结合时钟的行为建模(符合结构化设计逻辑)
这种方式用时钟触发的always块控制时序,清晰贴合需求:
`timescale 1ns/1ps module addr_wr_controller( input clk, input [7:0] addr_in, output reg [7:0] ADDR, output reg WR ); // 每个时钟上升沿触发,对应10ns的周期 always @(posedge clk) begin // 时钟上升沿立即为ADDR赋值,保证信号稳定 ADDR <= addr_in; // 延迟1ns后将WR从0置为1,刚好满足ADDR的建立时间要求 #1 WR <= 1'b1; // 为了让WR在下一个周期可以重新触发,在周期结束前(第9ns时)拉低WR #8 WR <= 1'b0; end endmodule
解释:时钟上升沿(周期起点)时ADDR先完成赋值,1ns后WR触发上升沿,此时ADDR已经稳定了1ns,完美满足建立时间约束。之后再过8ns(离下一个时钟上升沿还有1ns)将WR拉回0,确保下一个周期的时序可以正常触发。
方式2:门级延迟组合实现
如果更偏向纯结构化门级设计,可以用延迟线和触发器组合:
`timescale 1ns/1ps module addr_wr_controller( input clk, input [7:0] addr_in, output [7:0] ADDR, output WR ); // 用D触发器(结构化原语)实现ADDR的时钟同步赋值 dff addr_dff( .clk(clk), .d(addr_in), .q(ADDR) ); // 生成WR信号:时钟上升沿延迟1ns后输出高电平 wire clk_delayed; assign #1 clk_delayed = clk; // 用与门和寄存器控制WR的电平,确保每个周期内WR只在1ns后变高并保持 reg wr_reg; always @(posedge clk) begin wr_reg <= 1'b1; end always @(negedge clk_delayed) begin wr_reg <= 1'b0; end assign WR = wr_reg; // 简单D触发器原语定义(如果工具自带可以不用写) module dff(input clk, input d, output reg q); always @(posedge clk) begin q <= d; end endmodule
注意:代码中的延迟是为了在仿真中复现这个时序关系,实际硬件项目中,建立时间约束需要通过综合工具的时序约束命令(比如set_setup)来指定,由工具自动布局布线保证时序合规。
内容的提问来源于stack exchange,提问作者user2524261




