跨时钟域信号传输(Verilog)

本篇着重讲解单bit信号由快时钟域到慢时钟域的转化。

对于跨时钟域信号的处理,方法我们都知道:
单bit:两级触发器同步(适用于慢到快)
多bit:采用异步FIFO,异步双口RAM 加握手信号 格雷码转换

对于多bit信号来说我们想要跨时钟域处理直接使用fifo就可以了。如果对于单bit信号来说,慢时钟域到快时钟域使用两级触发器就可以,代码如下图所示:

//---------慢时钟域到快时钟域----------//
module mul_clk(
	input clk,		//快时钟域时钟
	input rst_n,
	input pulse_a,
	output pulse_b
);

	reg [1:0]pulse_r;

	always@(posedge clk or negedge rst_n)begin
		if(!rst_n)
			pulse_r <= 2'b00;
		else
			pulse_r <= {pulse_r[0],pulse_a};
	end
	
	assign pulse_b = pulse_r[1];

endmodule

波形仿真:
在这里插入图片描述
跨时钟域处理从快时钟域到慢时钟域根据信号宽度可以分为两种情况,如第一个图所示,ckl_b则可以采样到signal_a_in,但是如第二个图所示,只有单脉冲,就不能确保可以采样到signal_a_in。这种情况用两级触发器同步是没有用的。
在这里插入图片描述
在这里插入图片描述
所以针对第二种情况需要特殊处理,如下所示为针对第二种跨时钟域的处理代码:

//----------------快时钟域到慢时钟域----------------//
module mul_clk(
	input clk_a,
	input clk_b,
	input rst_n,
	input pulse_a,
	output pulse_b
);

	reg signal_a;
	reg signal_b;
	reg [1:0]signal_a_r;
	reg [1:0]signal_b_r;
	
//----------时钟域A下进行脉冲pulse_a的展宽------------//
	always@(posedge clk_a or negedge rst_n)begin
		if(!rst_n)
			signal_a <= 1'b0;
		else if(pulse_a)
			signal_a <= 1'b1;
		else if(signal_a_r[1])
			signal_a <= 1'b0;
		else
			signal_a <= signal_a;
	end
	
//--------时钟域B下采集时钟域A拓展的脉宽信号signal_a-------//
	always@(posedge clk_b or negedge rst_n)begin
		if(!rst_n)
			signal_b <= 1'b0;
		else 
			signal_b <= signal_a;
	end
	
//-------时钟域B下缓存signal_b信号,生成时钟域B下的脉冲------//
	always@(posedge clk_b or negedge rst_n)begin
		if(!rst_n)
			signal_b_r <= 2'b00;
		else 
			signal_b_r <= {signal_b_r[0],signal_b};
	end
	
	assign pulse_b = ~signal_b_r[1] & signal_b_r[0];

//--------时钟域A下采集signal_b_r,反馈到时钟域A控制signal_a拉低------//	
	always@(posedge clk_a or negedge rst_n)begin
		if(!rst_n)
			signal_a_r <= 2'b00;
		else
			signal_a_r <= {signal_a_r[0],signal_b_r[1]};
	end
	
endmodule 

仿真代码:

`timescale 1ns/1ns
module mul_clk_tb;

//	reg clk;
//	reg rst_n;
//	reg pulse_a;
//	
//	wire pulse_b;
//	
//	mul_clk mul_clk_inst(
//		.clk			(clk		),		//快时钟域时钟
//		.rst_n		(rst_n	),
//		.pulse_a		(pulse_a	),
//		.pulse_b		(pulse_b	)
//);
	
	reg clk_a;
	reg clk_b;
	reg rst_n;
	reg pulse_a;
	
	wire pulse_b;
	
	mul_clk mul_clk_inst(
		.clk_a		(clk_a   ),
		.clk_b		(clk_b   ),
		.rst_n		(rst_n	),
		.pulse_a		(pulse_a	),
		.pulse_b		(pulse_b	)
);

	initial clk_a = 0;
	always#10 clk_a = ~clk_a;
	
	initial clk_b = 0;
	always#30 clk_b = ~clk_b;
	
	initial begin
		rst_n = 0;
		pulse_a = 0;
		#200;
		rst_n = 1;
		#200;
		pulse_a = 1;
		#30;
		pulse_a = 0;
		#500;
		$stop;
	end
	
endmodule


波形仿真:
在这里插入图片描述

  • 5
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Verilog中,跨时钟域信号传输可以通过使用双向异步FIFO(First-In-First-Out)实现。以下是一个例子: 首先,定义一个模块,包含两个时钟域的输入信号和一个双向异步FIFO: ```verilog module clock_domain_crossing ( input clk_fast, // 快时钟域 input clk_slow, // 慢时钟域 input reset, input data_in, output reg data_out ); reg [7:0] fifo [0:255]; // 双向异步FIFO reg wr_en, rd_en; reg [7:0] wr_ptr, rd_ptr; // 定义一个计数器,用于跟踪FIFO中的条目数 reg [7:0] count = 0; // 定义一个状态机来控制读写操作 // 在快时钟域下,每个时钟周期只执行一次操作 reg [1:0] state = 2'b00; always @(posedge clk_fast) begin case (state) 2'b00: begin // 空闲状态 wr_en <= 0; rd_en <= 0; if (reset) begin wr_ptr <= 0; rd_ptr <= 0; count <= 0; state <= 2'b00; end else if (data_in && count < 256) begin wr_en <= 1; wr_ptr <= wr_ptr + 1; count <= count + 1; state <= 2'b01; end else if (count > 0) begin rd_en <= 1; rd_ptr <= rd_ptr + 1; count <= count - 1; state <= 2'b10; end else begin state <= 2'b00; end end 2'b01: begin // 写入状态 wr_en <= 0; state <= 2'b00; end 2'b10: begin // 读取状态 data_out <= fifo[rd_ptr]; rd_en <= 0; state <= 2'b00; end endcase end // 在慢时钟域下,每个时钟周期只执行一次操作 always @(posedge clk_slow) begin if (reset) begin wr_ptr <= 0; rd_ptr <= 0; count <= 0; end else if (wr_en) begin fifo[wr_ptr] <= data_in; end else if (rd_en) begin data_out <= fifo[rd_ptr]; end end endmodule ``` 在上面的代码中,状态机控制了读写操作,并且在快时钟域下使用了一个双向异步FIFO来缓存数据。在慢时钟域下,数据从FIFO中读取或写入。由于双向异步FIFO可以同时处理读和写操作,因此可以实现跨时钟域信号传输。 需要注意的是,由于跨时钟域信号传输涉及到时序问题,因此需要特别小心。在实现时,应该尽可能使用同步方式,避免异步时序问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值