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