0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Verilog HDL-同步技术你了解多少

OpenFPGA 来源:OpenFPGA 作者:碎碎思 2021-09-18 10:58 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

同步技术

在芯片设计中,数据同步和在不同时钟域之间进行数据传输会经常出现。为避免任何差错、系统故障和数据破坏,正确的同步和数据传输就显得格外重要。这些问题的出现往往比较隐蔽,不易被发现,因此正确进行跨时钟域处理就显得极为重要。实现数据同步有许多种方式,在不同的情况下进行恰当的同步方式选择非常重要。以计算机中的南桥芯片为例,它通过不同的接口(如PCIe USB 吉比特以太网等)与外部设备相连。南桥通过不同的接口与外围设备相连,它与北桥之间是一个通用数据接口。南桥芯片中需要使用数据同步技术,目前,常用的同步技术主要分为以下几类:

  • 在不同的时钟域之间使用FIFO
  • 在不同的时钟域之间使用握手信号
  • 相位差固定的同步域内部的数据传输
  • 准同步域之间的数据传输

使用FIFO进行的数据同步

当存在两个异步时钟域并且二者之间进行数据包传输时,双端口FIFO最为适合。FIFO有两个端口,一个端口写入输入数据,另一个端口读出数据,如图6.34所示。两个端口工作在相互独立的时钟域内,通过各自的指针(地址)来读写数据。由于每个端口工作在相互独立的时钟域内,因此读写操作可以独立实现并且不会出现任何差错。当FIFO变满时,应停止写操作,直到FIFO中出现空闲空间。同样,当FIFO为空时,应停止读操作,直到有新的数据被写入FIFO中。

握手同步方式

FIFO可用于在不同的时钟域之间进行数据包的传输,但是在一些应用中需要在不同时钟域之间进行少量数据传输。FIFO占用的硬件资源较大,此时可以考虑使用握手同步机制.

所谓握手,即通信双方使用了专用控制信号进行状态指示,这个控制信号既有发送域给接受域的也有接收域给控制域的,有别于单向控制信号方式。

使用握手协议方式处理跨时钟域数据传输时,只需要对双方的握手信号(req 和 ack)分别使用脉冲检测方法进行同步,在具体实现中,假设req ,ack, data,总线在初始化时都处于无效状态,发送域先把数据放入总线,随后发送有效的req信号给接收域;接收域在检测到有效的req信号后锁存数据总线,然后会送一个有效的ack信号表示读取完成应答;发送域在检测到有效ack信号后撤销当前的req信号,接收域在检测到req撤销后也相应撤销ack信号,此时完成一次正常握手通信,此后,发送域可以继续开始下一次握手通信,如此循环,该方式能够使接收到的数据稳定可靠,有效的避免了亚稳态的出现,但是控制信号握手检测会消耗通信双方较多的时间。

a30b850e-1498-11ec-8fb8-12bb97331649.png

以下是握手同步机制的工作步骤:

  • 用后缀_t表示发送端,用后缀_r表示接收端。发送时钟用tclk表示,接收时钟用rclk表示。数据从tclk域向rclk域传输;

  • 当需要发送的数据准备好后,发送端将t_rdy信号置为有效,该信号必须在tclk下降沿时釆样输出;

  • 在t_rdy有效期间,t_data必须保持稳定;

  • 接收端在rclk域中采用双同步器同步t_rdy控制信号,并把同步后的信号命名为t_rdy_rclk;

  • 接收端在发现t_rdy_rclk信号有效时,tdata已经安全地进入了rclk域,使用rclk对其进行采样,可以得到t_data_rclk。由于由于数据已经在rclk域进行了正确采样,所以此后在rclk域使用该数据是安全的;

  • 接收端将r_ack信号置位1,信号必须在rclk下降沿输出;

  • 发送端通过双同步器在tclk域内同步r_ack信号,同步后的信号称为r_ack_tclk;

  • 以上所有步骤称为半握手。tclk1,这是因为发送端在输出下一数据之前,不会等r_ack_tclk被置为0;

  • 半握手机制工作速度快,但是,使用半握手机制时需要谨慎,一旦使用不当,会导致操作错误;

  • 从低频时钟域向高频时钟域传输数据时,半握手机制较为适用,这是由于接收端可以更快地完成操作。然而,如果从高频时钟域向低频时钟域传输数据,则需要采用全握手机制;

  • 当r_ack_tclk为高电平时,发送端将t_rdy置为0;

  • 当t_rdy_rclk为低电平时,接收端将r_ack置为0;

  • 当发送端发现r_ack_tclk为低电平后,全握手过程结束,传输端可以发送新的数据;

  • 显然,全握手过程耗时较长,数据传输速度较慢。然而,全握手机制稳定可靠,可以在两个任意频率的时钟域内安全地进行数据传输。如图6.35所示为全握手机制工作波形。

上面过程比较绕口,因此我制作了一张流程图,如下所示:

a3294bc0-1498-11ec-8fb8-12bb97331649.png

全握手机制代码及仿真结果如下。

发送端:使用三个状态的状态机,其跳转关系如下:

a33ef6dc-1498-11ec-8fb8-12bb97331649.png

moduletransmit(tclk,reset_tclk,t_rdy,data_avail,transmit_data,t_data,r_ack);
inputtclk;
inputreset_tclk;
inputdata_avail;
input[31:0]transmit_data;
inputr_ack;
outputt_rdy;
outputt_data;

localparamIDLE_T=2'd0,
ASSERT_T_RDY=2'd1,
DEASSERT_T_RDY=2'd2;

reg[1:0]t_hndshk_state,t_hndshk_state_nxt;
regt_rdy,t_rdy_nxt;
reg[31:0]t_data,t_data_nxt;
regr_ack_tclk;

always@(*)begin

t_hndshk_state_nxt=t_hndshk_state;
t_rdy_nxt=1'b0;
t_data_nxt=t_data;

case(t_hndshk_state)
IDLE_T:begin
if(data_avail)begin
t_rdy_nxt=1'b1;
t_hndshk_state_nxt=ASSERT_T_RDY;
t_data_nxt=transmit_data;
end
end

ASSERT_T_RDY:begin
if(r_ack_tclk)begin
t_rdy_nxt=1'b0;
t_hndshk_state_nxt=DEASSERT_T_RDY;
t_data_nxt='d0;
end
elsebegin
t_rdy_nxt=1'b1;
t_data_nxt=transmit_data;
end
end

DEASSERT_T_RDY:begin
if(!r_ack_tclk)begin
if(data_avail)begin
t_rdy_nxt=1'b1;
t_hndshk_state_nxt=ASSERT_T_RDY;
t_data_nxt=transmit_data;
end
elsebegin
t_hndshk_state_nxt=IDLE_T;
end
end
end

endcase
end
always@(posedgetclkornegedgereset_tclk)begin
if(!reset_tclk)begin
t_rdy<= 1'b0;
t_hndshk_state<= IDLE_T;
  t_data <= 32'h00000000;
r_ack_tclk<= 1'b0;
end

elsebegin
t_rdy<= t_rdy_nxt;
  t_hndshk_state <= t_hndshk_state_nxt;
  t_data <= t_data_nxt;
  r_ack_tclk <= r_ack;
 end
 
end
endmodule 

接收端:使用两个状态的状态机,跳转关系如下:

a35318ba-1498-11ec-8fb8-12bb97331649.png

modulereceiver(rclk,reset_rclk,t_rdy,t_data,r_ack);
inputrclk,reset_rclk;
inputt_rdy;
input[31:0]t_data;
outputr_ack;

regr_hndshk_state,r_hndshk_state_nxt;
regt_rdy_rclk;
reg[31:0]t_data_rclk,t_data_rclk_nxt;
regr_ack,r_ack_nxt;

localparamIDLE_R=1'b0,
ASSERT_ACK=1'b1;

always@(*)begin
r_hndshk_state_nxt=r_hndshk_state;
r_ack_nxt=1'b0;
t_data_rclk_nxt=t_data_rclk;
case(r_hndshk_state)
IDLE_R:begin
if(t_rdy_rclk)begin
r_hndshk_state_nxt=ASSERT_ACK;
t_data_rclk_nxt=t_data;
r_ack_nxt=1'b1;
end
end

ASSERT_ACK:begin
if(!t_rdy_rclk)begin
r_hndshk_state_nxt=IDLE_R;
r_ack_nxt=1'b0;
end
elsebegin
r_ack_nxt=1'b1;
end
end

endcase
end

always@(posedgerclkornegedgereset_rclk)begin
if(!reset_rclk)begin
r_hndshk_state<= IDLE_R;
  t_data_rclk <= 1'b0;
t_rdy_rclk<= 1'b0;
r_ack<= 1'b0;
end

elsebegin
r_hndshk_state<= r_hndshk_state_nxt;
  t_data_rclk <= t_data_rclk_nxt;
  t_rdy_rclk <= t_rdy;
  r_ack <= r_ack_nxt;
 end
end

endmodule

测试代码

`timescale1ns/1ns
moduletestbench;
regtclk_tb,rclk_tb;
reg[31:0]transmit_data_tb;
regreset_tclk_tb,reset_rclk_tb;
regdata_avail_tb;
wiret_rdy_tb;
wire[31:0]t_data_tb;
wirer_ack_tb;

parameterCLK_HALF_PERIOD1=5;
parameterCLK_HALF_PERIOD2=8;
parameterRESET_DELAY=100;

initialbegin
tclk_tb=0;
rclk_tb=0;
end

always#CLK_HALF_PERIOD1tclk_tb=~tclk_tb;
always#CLK_HALF_PERIOD2rclk_tb=~rclk_tb;

initialbegin
reset_rclk_tb=0;
reset_tclk_tb=0;
#RESET_DELAYreset_rclk_tb=1;
reset_tclk_tb=1;
end

initialbegin
#500;
data_avail_tb=1;
transmit_data_tb=32'h96431346;
end

transmittransmit_test
(.tclk(tclk_tb),
.reset_tclk(reset_tclk_tb),
.t_rdy(t_rdy_tb),
.data_avail(data_avail_tb),
.transmit_data(transmit_data_tb),
.t_data(t_data_tb),
.r_ack(r_ack_tb));

receiverreceiver_test
(.rclk(rclk_tb),
.reset_rclk(reset_rclk_tb),
.t_rdy(t_rdy_tb),
.t_data(t_data_tb),
.r_ack(r_ack_tb));
endmodule

仿真结果

a3699504-1498-11ec-8fb8-12bb97331649.png

脉冲同步器

脉冲同步器在源时钟域内接收一个脉冲,在目的时钟域内产生一个脉冲。脉冲同步器内部通常采用全握手机制来产生输出脉冲。在讨论脉冲同步器工作原理之前,我们先讨论它的用途。有时状态机希望更新不同时钟域内寄存器的数值,它可以采用全握手同步机制来达到这一目的,但全握手同步机制存在同步延迟大的问题,在全握手完成之前,状态机都将处于等待对方响应的状态。

为了解决这一问题,可以引入脉冲同步器电路。引入脉冲同步器后,状态机在源时钟域内产生更新脉冲,此后继续执行其他操作。脉冲同步器可以接收脉冲并完成剩余的同步和输出脉冲产生工作。需要注意的是,脉冲同步器完成全握手操作需要消耗多个时钟周期,因此状态机发出的两个脉冲之间需要足够的时间间隔,否则就会出现逻辑错误。下面是脉冲同步器的工作步骤、Verilog代码及仿真结果。

步骤:

  • 当源脉冲(pulse_src)有效时,在源时钟域中生成一个信号,并且保持有效(该信号称为sig_stretched);

  • 使用同步器在目的时钟域中对sig_stretched信号进行同步,称为sig_stretched_dest;

  • sig_stretched_dest信号被送回到源时钟域并进行同步称为sig_stretched_ack;

  • 如果sig_stretched_ack=1,则产生一个脉冲,根据这一反馈脉冲来将sig_stretched置为0(完成全握手);

  • 基于sig_stretched_dest,在目的时钟域中产生一个脉冲称为pulse_dest。

modulepulse_synchronizer
(clksrc,
resetb_clksrc,
clkdest,
resetb_clkdest,
pulse_src,
pulse_dest);

//*******************************************************
inputclksrc;
inputresetb_clksrc;
inputclkdest;
inputresetb_clkdest;
inputpulse_src;//pulseinsourceclockdomain
outputpulse_dest;//pulseindestinationclockdomain


regsig_stretched;
wiresig_stretched_nxt;
regsig_stretched_syncl,sig_stretched_dest;
regsig_stretched_dest_dl;
regsig_stxetched_ack_pre,sig_stretched_ack,
regsig_stretched_ack_d1;
wiresig_stretched_ack_edge;
wirepulse_dest;


assignsig_stretched_nxt=sig_stretched_ack_edge?1'b0:(pulse_src?l'bl:sig_stretched);


always@(posedgeclksrcornegedgeresetb_clksrc)
begin
if(!resetb_clksrc)

sig_stretched<= 1'bO;

else
sig_stretched<= sig_stretched_nxt;
end

//First two flops for synchronizing and the third one for pulse generation
always @(posedge clkdest or negedge resetb_clkdcst)
begin
if (!resetb_clkdest)
begin
 sig_stretched_sync <= 1'b0;
sig_stretchcd_dest<= 1'b0;
sig_stretched_dest_d1<= 1'b0;
end
else
begin
sig_stretchcd_sync1<= sig_stretched;
sig_stretched_dest  <= sig_stretched_sync1;
sig_stretched_dest_d1 <= sig_stretched_dest;
end
end

// First two flops are forsynchronizingbacktosourceclockdomain.
//thirdflopisforedgedetection
always@(posedgeclksrcornegedgeresetb_clksrc)
begin
if(!resetb_clksrc)
begin
sig_strctched_ack_pre<= 1'b0;
sig_stretchecl_ack<= 1'b0;
sig_stretched_ack_d1<= 1'b0;
end
else
begin
sig_stretched_ack_pre<= sig_stretched_dest;
sig_stretched_ack     <= sig_stretched_ack_pre;
sig_stretchcd_ack_d1  <= sig_strctched_ack;
end
end
assign sig_stretched_ack_edge = sig_stretched_ack & !sig_stretched_ack_d1;

// Pulse generation in destination clock domain

assign pulse_dest = sig_stretched_dest & !sig_stxctched_dest_d1;

endmodule

a37a8d64-1498-11ec-8fb8-12bb97331649.png

相位、频率关系固定时的跨时钟域数据传输

如果两个时钟具有相同或者整数倍的频率关系,上升沿之间有固定、明确的相位关系,那么在不使用FIFO或者握手协议的情况下,可以进行数据传输。此时固定明确的相位关系非常重要,数据传递时的建立时间和保持时间必须满足要求,如果相位关系不固定、不明确,则无法采用这种机制进行跨时钟域数据传递。在系统复位之后,需要调整数据延迟值(使用延迟链电路),从而确保跨时钟域数据传递时可以进行正确采样。

这种机制与使用FIFO或者握手机制相比具有更小的延迟。例如,DDR数据总线上可以使用单倍的时钟实现双倍的数据传输。前面讲过的数据位宽调整电路,也要求双方的时钟频率和相位具有间定、明确的关系。

准同步时钟域

如果两个时钟具有相同的标称频率和指定范围内的时钟精度误差,那么我们说这两个时钟源是准同步的。在实际应用中,通常数据发送端的本地时钟和接收端的本地时钟是独立产生的,通常都使用晶体振荡器这类高精度时钟源,二者往往具有相同的标称值和规定范围内的精度误差。

例如,PCIe要求发送和接收时钟误差在300ppm以内。这就意味着在一个相对较长的时间里(例如,对PCIe来说,超过1300个时钟周期),两个时钟将产生1个时钟周期的偏差。下面我们将讨论此时如何进行数据传输同步。

PCIe,SATA等串行通信协议中广泛使用了准同步通信机制。在数据收发电路中,弹性缓冲区(FIFO)被用于进行跨时钟域数据传输。此时FIFO不仅用于跨时钟域的同步,还需要与一定的外部电路配合,解决长时间通信时,由于时钟偏差造成的FIFO内部数据上溢或下溢的问题。PCIe和SATA要求发送端周期性地将null字符插入传输数据流中;在接收端,根据FIFO内部的数据深度,这些null字符会被丢弃或添加到FIFO中。

编辑:jq
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • usb
    usb
    +关注

    关注

    60

    文章

    8372

    浏览量

    281723
  • fifo
    +关注

    关注

    3

    文章

    406

    浏览量

    45493
  • Verilog
    +关注

    关注

    30

    文章

    1370

    浏览量

    114141
  • HDL
    HDL
    +关注

    关注

    8

    文章

    331

    浏览量

    48814

原文标题:Verilog HDL-同步技术

文章出处:【微信号:Open_FPGA,微信公众号:OpenFPGA】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    网络接口:数字世界的“门铃”,了解多少?

    ,还能为选择适合的网络解决方案奠定基础。在万物互联的时代,这些基础知识显得愈发重要。 希望这篇简单的介绍能帮助大家对网络接口有基本的了解。我始终相信,了解技术细节能让客户做出更明智的选择。如果
    发表于 11-26 18:53

    【产品介绍】Modelsim:HDL语言仿真软件

    概述ModelSim是业界最优秀的HDL语言仿真软件,它能提供友好的仿真环境,是业界唯一的单内核支持VHDL和Verilog混合仿真的仿真器。它采用直接优化的编译技术、Tcl/Tk技术
    的头像 发表于 11-13 11:41 198次阅读
    【产品介绍】Modelsim:<b class='flag-5'>HDL</b>语言仿真软件

    觉得哪个软件写verilog体验最好?有什么优势?

    觉得哪个软件写verilog体验最好?有什么优势?请在评论区留言跟大家分享一下吧。
    发表于 11-10 07:47

    如何利用Verilog HDL在FPGA上实现SRAM的读写测试

    本篇将详细介绍如何利用Verilog HDL在FPGA上实现SRAM的读写测试。SRAM是一种非易失性存储器,具有高速读取和写入的特点。在FPGA中实现SRAM读写测试,包括设计SRAM接口模块
    的头像 发表于 10-22 17:21 3958次阅读
    如何利用<b class='flag-5'>Verilog</b> <b class='flag-5'>HDL</b>在FPGA上实现SRAM的读写测试

    使用Simulink自动生成浮点运算HDL代码(Part 1)

    引言 想要实现浮点运算功能,如果自己写Verilog代码,需要花费较多的时间和精力。好在Simulink HDL Coder工具箱提供了自动代码生成技术。下图展示了HDL Coder如
    发表于 10-22 06:48

    NTP时间同步技术:保证网络时间精确无比

    NTP是一种用于计算机和网络设备之间进行时间同步的协议,它能够确保所有设备都使用同一个时间源,从而实现全球范围内的时间精确同步。本文将详细介绍NTP时间同步技术的原理、应用以及优势。首
    的头像 发表于 10-21 14:45 324次阅读
    NTP时间<b class='flag-5'>同步</b><b class='flag-5'>技术</b>:保证网络时间精确无比

    FPGA Verilog HDL语法之编译预处理

    Verilog HDL语言和C语言一样也提供了编译预处理的功能。“编译预处理”是Verilog HDL编译系统的一个组成部分。Verilog
    的头像 发表于 03-27 13:30 1088次阅读
    FPGA <b class='flag-5'>Verilog</b> <b class='flag-5'>HDL</b>语法之编译预处理

    采购GUTOR UPS备品备件,隐藏的“雷区” 了解吗?

    在GUTOR UPS备品备件采购之路上,困难重重,选型、渠道甄别、成本把控、安装部署、售后保障,桩桩件件都是棘手难题。隐藏的“雷区” 了解吗?
    发表于 03-21 16:08

    一文详解Verilog HDL

    Verilog HDL(Hardware Description Language)是一种硬件描述语言,用于从算法级、门级到开关级的多种抽象设计层次的数字系统建模。现实生活中多用于专用集成电路
    的头像 发表于 03-17 15:17 3780次阅读
    一文详解<b class='flag-5'>Verilog</b> <b class='flag-5'>HDL</b>

    浅谈Verilog和VHDL的区别

    Verilog和VHDL是两种广泛使用的硬件描述语言(HDL),它们用于描述和模拟数字电路系统的行为和结构。这两种语言的主要作用是帮助工程师设计、仿真和验证集成电路(IC)和系统级芯片(SoC)中的硬件模块。
    的头像 发表于 02-17 14:20 2630次阅读
    浅谈<b class='flag-5'>Verilog</b>和VHDL的区别

    ptp时间同步技术的优势

    在现代通信和信息技术中,时间同步是一个至关重要的环节。无论是在金融交易、科学研究还是工业自动化领域,精确的时间同步都是确保系统稳定运行和数据准确性的关键。PTP(Precision Time
    的头像 发表于 12-29 09:33 1004次阅读

    Verilog 与 ASIC 设计的关系 Verilog 代码优化技巧

    Verilog与ASIC设计的关系 Verilog作为一种硬件描述语言(HDL),在ASIC设计中扮演着至关重要的角色。ASIC(Application Specific Integrated
    的头像 发表于 12-17 09:52 1439次阅读

    Verilog 测试平台设计方法 Verilog FPGA开发指南

    Verilog测试平台设计方法是Verilog FPGA开发中的重要环节,它用于验证Verilog设计的正确性和性能。以下是一个详细的Verilog测试平台设计方法及
    的头像 发表于 12-17 09:50 1561次阅读

    如何使用 Verilog 进行数字电路设计

    首先,需要清楚地了解的数字电路需要实现什么功能。这可能包括输入输出的数量、数据宽度、时钟频率、时序要求等。明确的需求是设计成功的关键。 2. 设计逻辑电路 在明确了需求之后,
    的头像 发表于 12-17 09:47 1757次阅读

    Verilog与VHDL的比较 Verilog HDL编程技巧

    Verilog 与 VHDL 比较 1. 语法和风格 VerilogVerilog 的语法更接近于 C 语言,对于有 C 语言背景的工程师来说,学习曲线较平缓。它支持结构化编程,代码更直观,易于
    的头像 发表于 12-17 09:44 2691次阅读