芯动力——硬件加速设计方法学习笔记(第三章)电平/边沿检测/脉冲同步器


前言

学习打卡第五天,继续学习,每天进步一点点!
上一节介绍了跨时钟域传输的方法,从快时钟域到慢时钟域有脉冲同步器,但是该方法对输入信号要求较高,所以继续介绍跨时钟域传输的其他方法


在这里插入图片描述


一、单bit信号跨时钟域传输

1、双锁存器法/电平同步器

优点:结构简单、易于实现、面积消耗较少
缺点:增加了两个触发器的延时
条件:适合于慢时钟域到快时钟域,都可以

假设第一级触发器不满足其建立时间,产生亚稳态,在下一个时钟沿到来之前,它的亚稳态在一段时间后必须稳定下来,且满足第二级触发器的建立时间,因此第二级触发器就不会发生亚稳态。

三级以及更多级可以使亚稳态发生的概率降低更多,但是电路延时也会增加
该方法只是降低发生概率,不能从根本上进行去除亚稳态

在这里插入图片描述
同步器有效条件:

  • 第一级触发器进入亚稳态的恢复时间 + 第二级触发器建立时间 <= 时钟周期
  • 输入脉冲宽度 > 同步时钟周期 + 第一级触发器的保持时间
  • 更保险的说法:脉冲宽度 > 两倍同步时钟周期

在这里插入图片描述

2、边沿检测同步器(慢时钟域到快时钟域)

如果只是边沿检测,只需要一级触发器即可,由于这里介绍的是跨时钟域传输,所以前面加了一级/两级同步器。

边沿检测原因:慢时钟的一个周期信号在快时钟看来就是几个信号周期,所以检测边沿是最合理的,检测边沿的上升或者下降。

检测上升沿下降沿双边沿,并发出相应的脉冲。

适用条件: 输入数据宽度 > 同步时钟周期+Th(最安全的是大于两个同步时钟周期)

2.1 上升沿检测

下面这个图是out = a_r & ~a_rr;按道理输出脉冲应该滞后一个周期,不是下面波形图画的那样。
下面波形图应该是out = a & ~a_r;才是同步输出。
在这里插入图片描述

module pos(
	input clk,
	input a,
	input rst_n,
	output o_pos
);

	reg a_r;
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			a_r <= 0;
		else
			a_r <= a;
	end
	assign o_pos = a & ~a_r;
endmodule

2.2 下降沿检测

在这里插入图片描述

module neg(
	input clk,
	input a,
	input rst_n,
	output o_neg
);

	reg a_r;
	
	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			a_r <= 0;
		else
			a_r <= a;
	end
	assign o_pos = ~a & a_r;
endmodule

2.3 边沿检测同步器

前面两级用于同步,后一级用于边沿检测
在这里插入图片描述

module delay_clap(
	input clk1,
	input clk2,
	input rst_n,
	input sig,
	output sig_rise,
	output sig_down,
	output sig_dual,
	output sig_out
);
	reg [2:0] sig_r;   //3级缓存
	always@(posedge clk2 or negedge rst_n)begin //注意这里是clk2,目标时钟
		if(!rst_n)
			sig_r <= 0;
		else
			sig_r[1:0] <= {sir_r[0], sig};
	end
	
	assign sig_rise = sig_r[1] & !sig_r[2];
	assign sig_down = !sig_r[1] & sig_r[2];
	assign sig_dual = sig_r[1] ^ sig_r[2];   //双边沿检测,是同步前和同步后的信号进行异或
	assign sig_out = sig[1];   //信号直接输出   
endmodule

3、脉冲同步器/结绳法(快时钟域到慢时钟域)

在慢时钟域去采样快时钟域信号,可能会采样不到,所以采用翻转电路

将原时钟域下的脉冲信号,转化为电平信号(异或门或选择器),再进行同步,同步之后,再把新时钟域下的电平信号转化为脉冲信号(边沿检测的原理)。这样就从快时钟域取出一个单时钟宽度脉冲,在慢时钟域建立新的单时钟宽度脉冲。

  • 输入脉冲时间间隔必须大于两个接收时钟周期,否则新的脉冲会变宽,就不再是单时钟宽度脉冲了。
  • 如果输入脉冲相互过近,则新时钟域中的输出脉冲也紧密相邻,结果是输出脉冲宽度比一个时钟周期宽。

翻转电路:将快时钟域前后间隔多个周期的信号进行标定,形成了toggle的波形

优点:可以解决快时钟域到慢时钟域的信号传输问题,适用范围较广
缺点:较为复杂,效率不是太高

在这里插入图片描述

module pulse_detect(
	input clk1,
	input clk2,
	input rst_n,
	input data_in,
	output dataout
);
	reg [3:0] data_r;
	always@(posedge clk1 or negedge rst_n)begin  //注意这里为clk1
		if(!rst_n)
			data_r[0] <= 0;
		else  
		    //两种写法,选择器和异或门
			data_r[0] <= data_in ? ~data_r[0] : data_r[0];
			data_r[0] <= data_in ^ data_r[0];
	end
	always@(posedge clk2 or negedge rst_n)begin //注意这里为clk2
		if(!rst_n)
			data_r[3:1] <= 0;
		else
			data_r[3:1] <= {data_r[2:1], data_r[0]};
	end
	assign dataout = data_r[3] ^ data_r[2];
endmodule

4、三种同步器比较

在这里插入图片描述

慢时钟域到快时钟域快时钟域到慢时钟域
只考虑亚稳态问题考虑亚稳态问题,也要考虑慢时钟的采样速率问题(采样频率要高于信号最高频率的两倍)

二、verilog手撕代码,展宽1bit信号为32bit

对1bit的脉冲信号进行展宽,转为32bit位宽,并产生有效信号

module zhankuan(
    input           clk,
    input           rst_n,
    input           pulse_in,
    output    reg   pulse_out,
    output          p_flag
);

	reg in_r,in_rr;
	reg [4:0]   cnt;

	always @(posedge clk or negedge rst_n)
	    if(!rst_n) begin
	        in_r<=1'b0;
	        in_rr<=1'b0;
	    end
	    else begin
	        in_r<=pulse_in;
	        in_rr<=in_r;
	    end
	
	assign  p_flag=(~in_rr)&in_r;  //上升沿检测
		
	always @(posedge clk or negedge rst_n)
	    if(!rst_n)
	        pulse_out<=1'b0;    
	    else if(p_flag)
	        pulse_out<=1'b1;
	    else if(cnt==5'd31)
	        pulse_out<=1'b0; 
	    else 
	    	pulse_out<=pulse_out;  
	 
	 always @(posedge clk or negedge rst_n)
	    if(!rst_n)
	        cnt<=5'b0;
	    else if(pulse_out==1'b1)
	        cnt<=(cnt==5'd31)?0:cnt+1'b1;
	    else 
	    	cnt<=cnt;
endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值