牛客网Verilog刷题——VL49

牛客网Verilog刷题——VL49

  • 题目
  • 解析
  • 答案

题目

  从A时钟域提取一个单时钟周期宽度脉冲,然后在新的时钟域B建立另一个单时钟宽度的脉冲。A时钟域的频率是B时钟域的10倍;A时钟域脉冲之间的间隔很大,无需考虑脉冲间隔太小的问题。电路的接口如下图所示。data_in是脉冲输入信号,data_out是新的脉冲信号clk_fast是A时钟域时钟信号,clk_slow是B时钟域时钟信号;rst_n是异步复位信号。

牛客网Verilog刷题——VL49_第1张图片

  输入输出描述:

信号 类型 输入/输出 位宽 描述
clk_fast wire Intput 1 快时钟域时钟信号
clk_slow wire Intput 1 慢时钟域时钟信号
rst_n wire Intput 1 异步复位信号,低电平有效
data_in wire Intput 1 输入脉冲信号(快时钟域脉冲信号)
data_out wire Output 1 输出脉冲信号(慢时钟域脉冲信号)

解析

  本题要求设计一个脉冲同步电路,将快时钟域的脉冲信号同步到慢时钟域,得到慢时钟域的脉冲信号。本题考察的实际上就是单比特跨时钟域(脉冲信号从快到慢)。由于快时钟域clk_fast的时钟频率大于慢时钟域clk_slow的时钟频率,快时钟域的脉冲信号可能无法被慢时钟域采样到,因此需要把快时钟域clk_fast的脉冲信号进行展宽,然后再将展宽后的快时钟域下的脉冲信号用“打两拍”的方法同步到慢时钟域,这里存在一个问题:快时钟域的脉冲信号展宽要展宽为几个时钟宽度?什么时候拉低?展宽后的脉冲信号同步到慢时钟域后,需要再进行打拍,用于生成慢时钟域的脉冲信号。

  具体步骤如下:

(1)将快时钟域clk_fast下的脉冲信号signal_pulse_fast进行展宽,展宽后的快时钟域脉冲信号为signal_pulse_fast_extend;
(2)将展宽后的快时钟域脉冲信号signal_pulse_fast_extend同步到慢时钟域clk_slow(打两拍),得到signal_pulse_fast_extend_f2s_2;
(3)再对信号signal_pulse_fast_extend_f2s_2在慢时钟域打一拍后,用于生成慢时钟域脉冲信号signal_pulse_slow;
(4)将慢时钟域的脉冲信号同步到快时钟域(打两拍),得到signal_pulse_slow_s2f_2,用于控制快时钟域展宽脉冲信号signal_pulse_fast_extend的宽度(控制什么时候拉低);

答案

`timescale 1ns/1ns

module pulse_detect(
	input 				clk_fast	, 
	input 				clk_slow	,   
	input 				rst_n		,
	input				data_in		,

	output  		 	dataout
);

wire signal_pulse_fast; //快时钟域脉冲信号
reg  signal_pulse_fast_extend; //快时钟域脉冲信号展宽信号
reg  signal_pulse_fast_extend_f2s_1; //快时钟域脉冲信号展宽信号同步到慢时钟域(打一拍)
reg  signal_pulse_fast_extend_f2s_2; //快时钟域脉冲信号展宽信号同步到慢时钟域(打两拍)
reg  signal_pulse_fast_extend_f2s_2_r; //快时钟域脉冲信号展宽信号同步到慢时钟域(打三拍)

wire signal_pulse_slow; //慢时钟域脉冲信号
reg  signal_pulse_slow_s2f_1; //慢时钟域脉冲信号同步到快时钟域
reg  signal_pulse_slow_s2f_2; //慢时钟域脉冲信号同步到快时钟域

//快时钟域脉冲信号
assign signal_pulse_fast = data_in;

//快时钟域电平信号
always @(posedge clk_fast or negedge rst_n) begin
	if(!rst_n)
		signal_pulse_fast_extend <= 1'b0;
	else if(signal_pulse_fast)
		signal_pulse_fast_extend <= 1'b1;
	else if(signal_pulse_slow_s2f_2)
		signal_pulse_fast_extend <= 1'b0;
	else
		signal_pulse_fast_extend <= signal_pulse_fast_extend;
end

//快时钟域电平信号同步到慢时钟域
always @(posedge clk_slow or negedge rst_n) begin
	if(!rst_n) begin
		signal_pulse_fast_extend_f2s_1 <= 1'b0;
		signal_pulse_fast_extend_f2s_2 <= 1'b0;
	end
	else begin
		signal_pulse_fast_extend_f2s_1 <= signal_pulse_fast_extend;
		signal_pulse_fast_extend_f2s_2 <= signal_pulse_fast_extend_f2s_1;
	end
end

//慢时钟域电平信号打拍
always @(posedge clk_slow or negedge rst_n) begin
	if(!rst_n)
		signal_pulse_fast_extend_f2s_2_r <= 1'b0;
	else
		signal_pulse_fast_extend_f2s_2_r <= signal_pulse_fast_extend_f2s_2;
end

//慢时钟域脉冲信号
assign signal_pulse_slow = signal_pulse_fast_extend_f2s_2 && (~signal_pulse_fast_extend_f2s_2_r);

//慢时钟域脉冲信号同步到快时钟域
always @(posedge clk_fast or negedge rst_n) begin
	if(!rst_n) begin
		signal_pulse_slow_s2f_1 <= 1'b0;
		signal_pulse_slow_s2f_2 <= 1'b0;
 	end
	else begin
		signal_pulse_slow_s2f_1 <= signal_pulse_slow;
		signal_pulse_slow_s2f_2 <= signal_pulse_slow_s2f_1;
	end	
end

assign dataout = signal_pulse_slow;

//--------备注--------//
//本题考察的实际上就是单比特跨时钟域处理的方法(快时钟域到慢时钟域)

endmodule

你可能感兴趣的:(牛客刷题,fpga开发,Verilog,跨时钟域处理)