校招Verilog——单bit跨时钟域(脉冲展宽法-握手法)
如何处理跨时钟域信号?
单bit:
- (1)双D触发器打拍同步;(只能慢到快)
- (2)脉冲展宽处理(握手法);
多bit:
- (1)格雷码+双D触发器打拍;(不推荐)
- (2)DMUX数据使能选通设计;(FIFO设计)
- (3)异步握手协议;(效率较低)
这里写一下单bit进行跨时钟域的代码设计,如果设计时知道一定是慢时钟域到快时钟域,那么该信号到快时钟域信号打两拍,检测上升沿就行。如果是快时钟域到慢时钟域,或者不知道两边时钟域情况,那么可以用【脉冲展宽处理】,如果脉冲展宽是有限的,就是说拉高的展宽信号后面还得拉低,那就是【握手法】。
基本思想是:
-
快时钟域对脉冲信号进行检测,检测为高电平时输出高电平信号 req。
-
慢时钟域对快时钟域的信号 req 进行延迟打拍采样。因为此时的脉冲信号被快时钟域保持拉高状态,延迟打拍肯定会采集到该信号。
-
慢时钟域确认采样得到高电平信号 req_r1 后,拉高反馈信号 ack 再反馈给快时钟域。
-
快时钟域对反馈信号进行延迟打拍采样得到 ack_r1。如果检测到反馈信号为高电平,证明慢时钟域已经接收到有效的高电平信号,信号恢复原来状态。
1、代码设计
module Sync_Pulse ( input clka, input clkb, input rst_n, input bit_a, output bit_b ); //-------------------------------------------------------- reg req_a; reg ack_a; reg ack_a_r1; reg req_b; reg req_b_r1; //-------------------------------------------------------- //-- a时钟域生成展宽信号 //-------------------------------------------------------- always @(posedge clka or negedge rst_n)begin if(!rst_n)begin req_a <= 1'b0; end else if(bit_a) begin //检测到脉冲 req_a <= 1'b1; //进行展宽 end else if(ack_a_r1) begin //同步到b时钟域后得到应答 req_a <= 1'b0; //展宽使命完成 end end //-------------------------------------------------------- //-- 展宽信号同步到b时钟域 //-------------------------------------------------------- always @(posedge clkb or negedge rst_n)begin if(!rst_n)begin req_b <= 1'b0; req_b_r1 <= 1'b0; end else begin req_b <= req_a; req_b_r1 <= req_b; end end //-------------------------------------------------------- //-- 展宽信号同步回b时钟域,作为应答 //-------------------------------------------------------- always @(posedge clka or negedge rst_n)begin if(!rst_n)begin ack_a <= 1'b0; ack_a_r1 <= 1'b0; end else begin ack_a <= req_b_r1; ack_a_r1 <= ack_a; end end //-------------------------------------------------------- //-- 脉冲信号输出,上升沿检测 //-------------------------------------------------------- assign bit_b = ~req_b_r1 & req_b; endmodule
2、Testbench
`timescale 1ns/1ps //时间精度 `define Clock_a 10 //时钟周期,数字越小时钟越快 `define Clock_b 100 //时钟周期,数字越大时钟越慢 module Sync_Pulse_tb; //========================< 端口 >========================================== reg clka ; reg clkb ; reg rst_n ; reg bit_a ; //========================================================================== //== 模块例化 //========================================================================== Sync_Pulse u_Sync_Pulse ( .clka (clka ), .clkb (clkb ), .rst_n (rst_n ), .bit_a (bit_a ), .bit_b (bit_b ) ); //========================================================================== //== 时钟信号和复位信号 //========================================================================== initial begin clka = 1; forever #(`Clock_a/2) clka = ~clka; end initial begin clkb = 1; forever #(`Clock_b/2) clkb = ~clkb; end initial begin rst_n = 0; #(`Clock_a*2+1); rst_n = 1; end //========================================================================== //== 设计输入信号 //========================================================================== initial begin bit_a = 0; #(`Clock_a*2+1); //初始化完成 bit_a = 1; #(`Clock_a); bit_a = 0; #(`Clock_b*100); $stop; end endmodule
3、波形展示
(1)快 -> 慢
(2)慢 -> 快
这个代码建议背出来,看不太懂就自己仿真看看吧!
如果是多bit跨时钟域处理,可以用参见异步FIFO的代码设计。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· 手把手教你更优雅的享受 DeepSeek
· AI工具推荐:领先的开源 AI 代码助手——Continue
· 探秘Transformer系列之(2)---总体架构
· V-Control:一个基于 .NET MAUI 的开箱即用的UI组件库
· 乌龟冬眠箱湿度监控系统和AI辅助建议功能的实现