原创 FPGA中跨时钟域的信号处理--握手协议方式

2010-11-14 22:56 8007 15 18 分类: FPGA/CPLD

“一种解决总线同步问题的方法是使用一个保持寄存器和握手信号”,这也就是“先异步暂存,后同步写入”的方法


下面介绍握手方式进行异步时钟域的通信。


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


9ece0637-24e1-4e22-963a-34accf108c0f.JPG



图2 握手通信原理


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


a2931cba-5c2e-476e-962e-a6c557e68304.JPG



图3 握手通信流程


我分别编写了发送时钟域和接收时钟域的代码进行测试,用到两组MEM,以便于观察实验结果,进一步加深对基本握手方式解决跨时钟域问题的认识。


发送端代码:


//接收域应答信号ack采用两级寄存器同步,便于时序收敛


always @ (negedge rst_n or posedge t_clk)


begin


  if(rst_n == 1'b0)


  begin


     ack_reg1 <= 1'b0;


     ack_reg2 <= 1'b0;


  end


  else


  begin


     ack_reg1 <= ack;


     ack_reg2 <= ack_reg1;


  end


end


 


//数据处理状态机


always @ (negedge rst_n or posedge t_clk)


begin


  if(rst_n == 1'b0)


  begin


     data_buf <= 'b0;


     tr_state <= TR_IDLE;


     TR_MEM_Addr <= 0;


  end


  else


     case(tr_state)


     TR_IDLE :     //初始化状态      


     begin


        req <= 1'b0;


        TR_MEM_Addr <= 0;


        tr_state <= SND_DATA_REQ;


     end


     SND_DATA_REQ: //送数据到总线上和发送请求信号     


     begin


        data_buf <= TR_MEM[TR_MEM_Addr];


        req <= 1'b1;//发送请求信号,请求信号为高,表示请求接收


        TR_MEM_Addr <= TR_MEM_Addr + 1;


        tr_state <= CHK_ACK_ACTIVE;


     end


     CHK_ACK_ACTIVE ://检测应答信号为高,释放请求信号


     begin


        if(ack_reg2 == 1'b1)  //便于时序收敛


        begin


           req <= 1'b0;        //释放请求信号


           tr_state <= CHK_COMM_END;


        end


        else


           tr_state <= CHK_ACK_ACTIVE;


     end


     CHK_COMM_END :   //检测握手通信结束,如果应答信号被释放,一次握手结束                    


     begin


        if(ack_reg2 == 1'b0)


           tr_state <= SND_DATA_REQ;


        else


           tr_state <= CHK_COMM_END;


     end


     default : tr_state <= TR_IDLE;


       


  endcase


end


 


assign dout = data_buf;


 


接收端代码:


//发送域请求信号req采用两级寄存器同步,便于时序收敛


always @ (negedge rst_n or posedge r_clk)


begin


  if(rst_n == 1'b0)


  begin


     req_reg1 <= 1'b0;


     req_reg2 <= 1'b0;


  end


  else


  begin


     req_reg1 <= req;


     req_reg2 <= req_reg1;


  end


end


 


//数据处理状态机


always @ (negedge rst_n or posedge r_clk)


begin


  if(rst_n == 1'b0)


  begin


     re_state <= RE_IDLE;


     ack <= 1'b0;


     RE_MEM_Addr <= 0;


  end


  else


     case(re_state)


     RE_IDLE :           //初始化状态


     begin


        RE_MEM_Addr <= 0;


        re_state <= CHK_REQ_ACTIVE;


     end


     CHK_REQ_ACTIVE :    //检测发送端的数据发送请求信号


     begin


        if(req_reg2 == 1'b1)     //如果有请求信号,接收数据


        begin


           RE_MEM[RE_MEM_Addr] <= din;//接收数据存放到MEM


           ack <= 1'b1;//检测到请求信号,发送接收端应答信号


           RE_MEM_Addr <= RE_MEM_Addr + 1;   //接收数据存储器地址累加


           re_state <= CHK_REQ_RELEASE;


        end


        else


           re_state <= CHK_REQ_ACTIVE;


     end


     CHK_REQ_RELEASE :     //检测请求信号释放,释放应答信号


     begin


        if(req_reg2 == 1'b0)


        begin


           ack <= 1'b0;  //释放应答信号,一次握手通信结束


           re_state <= CHK_REQ_ACTIVE;


        end


        else


           re_state <= CHK_REQ_RELEASE;


     end


     default : re_state <= RE_IDLE;


  endcase


end


具体方案 : 假设req,ack,data在初始化时都处于无效状态, 发送域先把数据放入总线,随后发送有效的req信号给接收域. 接收域在检测到有效的req信号后锁存数据总线,然后回送一个有效的ack信号表示读取完成应答. 发送域在检测到有效ack信号后撤销当前的req信号, 接收域在检测到req撤销后也相应撤销ack信号, 此时完成一次正常握手通信. 此后,发送域可以继续开始下一次握手通信.


验证 : 经过验证此模块可以实现数据从快时钟域发送至慢时钟域(发送端时钟:120M,接收端时钟:1M), 也可以实现数据从慢时钟域发送至快时钟域(发送端时钟:1M,接收端时钟120M),两个MEM中的数据完全一致。


b7a3115a-96e5-42b5-99af-7ea151984055.JPG

文章评论3条评论)

登录后参与讨论

用户1857338 2015-12-25 17:11

双触发器用来消除亚稳态,你可以借鉴这个例子先了解一下亚稳态

用户1831470 2015-3-12 12:01

你的ack,reg为什么打2拍呀???

用户1404666 2012-11-17 21:19

看看。借鉴下。
相关推荐阅读
用户211539 2015-09-28 16:21
FPGA采购和技术咨询:3044959554
Altera Xilinx  FPGA采购和技术咨询QQ:3044959554...
用户211539 2014-02-12 23:05
【博客大赛】Altera CycloneIV SerDes应用和仿真
Altera CycloneIV SerDes应用和仿真 KevinWan   基本原理 SerDes是SERializer和DESerializer的英文缩写,即串行收发器。 Altera SerD...
用户211539 2014-02-10 17:36
【博客大赛】基于FPGA的CIC以及补偿滤波器的设计
基于FPGA的CIC以及补偿滤波器的设计 KevinWan   CIC滤波器 CIC滤波器最早是由Hogenauer提出的,后来出现了不少改进的结构形式。CIC滤波器的特点: 只需要加法器,无需乘法器...
用户211539 2014-02-10 17:29
【博客大赛】SPWM的FPGA设计
SPWM的FPGA设计 KevinWan   SPWM:正弦波脉宽调制,将正弦半波N等分,把每一等分的正弦曲线与横轴所包围的面积用一个与此面积相等的等高矩形脉冲来替代。三角波载波信号U...
用户211539 2014-02-09 15:58
【博客大赛】Altera ALTMEPHY DDR2应用和仿真--基于QuartusII下例化的IP
Altera ALTMEPHY DDR2应用和仿真 --基于QuartusII下例化的IP KevinWan Modelsim仿真(本文是基于QuartusII下例化的IP,非Qsys) 编译如下库:...
用户211539 2014-02-09 15:55
Altera ALTMEPHY DDR2详细介绍(三)
Altera ALTMEPHY DDR2详细介绍(三) KevinWan 接口规则 配置DDR2 SDRAM控制器 DDR2 SDRAM的配置中的大部分参数都是相关数据手册中的参数,通常需要修改的包括...
我要评论
3
15
关闭 站长推荐上一条 /2 下一条