跨时钟域之全握手信号(Verilog)

微信公众号上线,搜索公众号小灰灰的FPGA,关注可获取相关源码,定期更新有关FPGA的项目以及开源项目源码,包括但不限于各类检测芯片驱动、低速接口驱动、高速接口驱动、数据信号处理、图像处理以及AXI总线等

跨时钟域之全握手信号(Verilog)

1、Verilog的实现
实现多位数据的跨时钟域传输,存在一定的数据延迟

module class_3_clka_clkb#(
    parameter    Width  =    31   	
	)(
    input        wire                               i_clk_a         ,
	input        wire                               i_clk_b         ,
	input        wire                               i_rst_n         ,
    input        wire            [Width-1:00]         i_data         , 
    input        wire                               i_data_sign     ,		
	output       reg             [Width-1:00]        o_data        ,     
    output       wire                               o_data_sign
);
    reg                          sign_a;
    wire                         sign_a_neg;
	reg          [01:00]          sign_a_tmp;	
/*****i_clk_a时钟域下i_data_sign发送数据信号下降沿*************/	
	always@(posedge i_clk_a or negedge i_rst_n)
    begin
	   if(!i_rst_n)
	       sign_a_tmp <= #1 2'b00;
	   else
	       sign_a_tmp <= #1 {sign_a_tmp[0],i_data_sign};
	end   
	assign  sign_a_neg = sign_a_tmp[1] & (~sign_a_tmp[0]);
/*****i_clk_a时钟域下i_data_sign发送数据信号下降沿*************/		
/*****i_clk_a时钟域下生成展宽信号sign_a*************/	
	always@(posedge i_clk_a or negedge i_rst_n)
    begin
	   if(!i_rst_n)
	       sign_a <= #1 1'b0;
	   else if(sign_a_neg)
	       sign_a <= #1 1'b1;
	   else if(sign_a_pos)
	       sign_a <= #1 1'b0;
	   else 
	       sign_a <= #1 sign_a;
	end
/*****i_clk_a时钟域下生成展宽信号sign_a*************/
/****i_clk_b时钟域下生成展宽信号sign_a,延展i_clk_b N个时钟此处为5个********/	
	reg        [04:00]           sign_b_tmp;
	wire                         sign_b_pos;	
	always@(posedge i_clk_b or negedge i_rst_n)
	begin
	   if(!i_rst_n)
	       sign_b_tmp <= #1 5'b00_000;
	   else 
	       sign_b_tmp <= #1 {sign_b_tmp[04:00],sign_a};
	end
/***i_clk_b时钟域下生成展宽信号sign_a,延展i_clk_b N个时钟此处为5个********/	
/*****i_clk_b时钟域下展宽信号中间数据输出*************/		
	assign  sign_b_pos = (~sign_b_tmp[4]) & sign_b_tmp[3];
    always@(posedge i_clk_b or negedge i_rst_n)	
	begin
	   if(!i_rst_n)
	        o_data <= #1 'd0;
	   else if(sign_b_pos)
	        o_data <= #1 i_data;
	end
/*****i_clk_b时钟域下展宽信号中间数据输出*************/	
/*****i_clk_a时钟域下展宽信号结束位置,同时生成输出应答信号*************/		
	reg         [01:00]          sign_a_ff;
	wire                         sign_a_pos;	
	always@(posedge i_clk_a or negedge i_rst_n)
	begin
	   if(!i_rst_n)
	       sign_a_ff <= #1 2'b00;
	   else 
	       sign_a_ff <= #1 {sign_a_ff[0],sign_b_tmp[4]};
	end	
	assign   sign_a_pos = (~sign_a_ff[1]) & sign_a_ff[0];
	assign   o_data_sign = sign_a_ff[1];
/*****i_clk_a时钟域下展宽信号结束位置,同时生成输出应答信号*************/		
endmodule
2、testbench仿真文件
`timescale 1ns/1ns
module tb_class_3#(
    parameter    Width        = 31    ,
    parameter    clk_a_period = 10    ,
    parameter    clk_b_period = 1000     	
	);
     reg                               i_clk_a         ;
	 reg                               i_clk_b         ;
	 reg                               i_rst_n         ;
	 reg                               i_data_sign     ;		   
     reg            [Width-1:00]       i_data          ;	                                                                
	 wire           [Width-1:00]       o_data          ;     
     wire                              o_data_sign     ;

class_3_clka_clkb#(
    .Width        (Width      )
     )u_class_3_clka_clkb(
    .i_clk_a      (i_clk_a    )   ,
	.i_clk_b      (i_clk_b    )   ,
	.i_data_sign  (i_data_sign)   ,
	.i_rst_n      (i_rst_n    )   ,
    .i_data       (i_data     )   ,	
	.o_data       (o_data     )   ,     
    .o_data_sign  (o_data_sign)
);
	
	initial  i_clk_a = 0 ;
	always #(clk_a_period/2)  i_clk_a = ~i_clk_a;
	
	initial  i_clk_b = 0 ;
	always #(clk_b_period/2)  i_clk_b = ~i_clk_b;
	
	initial begin
	i_rst_n = 0;
    #1000;
    i_rst_n = 1;	
	end
/************发送信号和应答信号形成回环******************************/	
	reg             sign_ff;	
	always@(posedge i_clk_a or negedge i_rst_n)
	begin
	   if(!i_rst_n)
	      begin
		   i_data_sign <= #1 1'b1;
	       sign_ff <= #1 1'b0;
		  end
	   else begin
	       sign_ff <= #1 o_data_sign;
		   i_data_sign <= #1 (~o_data_sign) & sign_ff;
	   end
	end
	
	always@(posedge i_clk_a or negedge i_rst_n)
	begin
	   if(!i_rst_n)
	       i_data <= #1  'd0;
	   else if(i_data_sign)
	       i_data <= #1 $random;
	end
/************发送信号和应答信号形成回环******************************/		
endmodule 

3、功能仿真验证
在这里插入图片描述

  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小灰灰的FPGA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值