【芯片设计】异步电路碎碎念(七)多比特DMUX同步器

乐活   2024-10-08 12:07   北京  

上一篇写了几个简单的打拍同步器,这一篇看下带有使能信号的多比特同步结构——DMUX同步器

DMUX的典型结构是这样的:

遵循的原则就是,数据不同步只对控制信号同步,这点其实和异步fifo里的思路一样,只不过异步fifo中的控制信号是多比特的格雷码,而这个场景下的控制信号是in_vld。继续观察结构可以发现,DMUX是将控制信号同步之后,在目的时钟域获取了控制信号的上升沿,以上升沿为使能信号采样数据。因此使用这个结构需要满足若干的要求:

1.数据和使能信号在源时钟域为同步到来的信号;

2.使能信号需要维持一段时间(目的时钟两拍),确保同步器能够稳定采样;

3.在目的时钟域对数据完成采样前,数据信号不能跳变;

如果不满足以上的要求,那么就可能造成数据漏同步、错同步等问题。接下来,完成代码,接口改了下名字和其他模块统一:

module async_nbit_dmux #(
parameter DL = 2,
parameter WD = 1,
parameter FF = 1
)( /*AUTOARG*/
// Outputs
o_data, o_en,
// Inputs
i_clk, i_rst_n, i_data, i_en, o_clk, o_rst_n
);

// ----------------------------------------------------------------
// Interface declare
// ----------------------------------------------------------------
input i_clk;
input i_rst_n;
input [WD -1:0]i_data;
input i_en;

input o_clk;
input o_rst_n;
output[WD -1:0]o_data;
output o_en;

入口处仍旧可以选择是否需要打拍后再进行同步操作:

// ----------------------------------------------------------------
// i_data dff
// ----------------------------------------------------------------
wire [WD -1:0]i_data_in;
wire i_en_in;
generate
if(FF == 0)begin: NO_IN_DFF
assign i_data_in = i_data;
assign i_en_in = i_en;
end //if(FF == 0)begin: NO_IN_DFF
else begin: IN_DFF
reg [WD -1:0]i_data_ff;
reg i_en_ff;
always @(posedge i_clk or negedge i_rst_n) begin
if(!i_rst_n)begin
i_data_ff <= {WD{1'b0}};
i_en_ff <= 1'b0;
end
else begin
i_data_ff <= i_data;
i_en_ff <= i_en;
end
end
assign i_data_in = i_data_ff;
assign i_en_in = i_en_ff;
end //else begin: IN_DFF
endgenerate

而后将控制信号同步到目的时钟域,并捕捉其上升沿:

// ----------------------------------------------------------------
// i_en_in async
// ----------------------------------------------------------------
wire i_en_sync;
reg i_en_sync_ff;
wire i_en_sync_pulse;
reg i_en_sync_pulse_ff;

async_1bit_delay #(.DL(DL), .FF(0))
u_i_en_sync(
.i_clk (i_clk),
.i_rst_n (i_rst_n),
.i_data (i_en_in),
.o_clk (o_clk),
.o_rst_n (o_rst_n),
.o_data (i_en_sync)
);

always @(posedge o_clk or negedge o_rst_n) begin
if(!o_rst_n)
i_en_sync_ff <= 1'b0;
else
i_en_sync_ff <= i_en_sync;
end

assign i_en_sync_pulse = (i_en_sync_ff == 1'b0) && (i_en_sync == 1'b1);

always @(posedge o_clk or negedge o_rst_n) begin
if(!o_rst_n)
i_en_sync_pulse_ff <= 1'b0;
else
i_en_sync_pulse_ff <= i_en_sync_pulse;
end

通过目的上升沿对数据进行采样,并输出结果:

// ----------------------------------------------------------------
// i_data_in sample
// ----------------------------------------------------------------
reg [WD -1:0]i_data_sync;
always @(posedge o_clk or negedge o_rst_n) begin
if(!o_rst_n)
i_data_sync <= {WD{1'b0}};
else if(i_en_sync_pulse)
i_data_sync <= i_data_in;
end

// ----------------------------------------------------------------
// out logic
// ----------------------------------------------------------------
assign o_en = i_en_sync_pulse_ff;
assign o_data = i_data_sync;

endmodule
// Local Variables:
// verilog-auto-inst-param-value:t
// verilog-library-directories:(".")
// verilog-library-extensions:(".v")
// End:

最后是仿真波形:

系列文章入口——

【芯片设计】SoC 101(一):绪论
【芯片设计】FIFO漫谈(零)从无处不在的FIFO开始说起
【芯片设计】计算机体系结构(一)虚拟内存

【芯片设计】深入理解AMBA总线(零)绪论

【芯片设计】握手协议的介绍与时序说明
【芯片设计】复位那些小事 —— 复位消抖
【芯片设计】快速入门数字芯片设计(一)Introduction
【芯片验证】UVM源码计划(零)下定决心读源码前的自测环节
【芯片设计】异步电路碎碎念(一) 到底什么是异步电路
【芯片设计】从RTL到GDS(一):Introduction
其他文章链接——
【芯片验证】sva_assertion: 15道助力飞升的断言练习
【芯片验证】可能是RTL定向验证的巅峰之作
【芯片验证】RTL仿真中X态行为的传播 —— 从xprop说起
【芯片验证】年轻人的第一个systemVerilog验证环境全工程与解析
【芯片设计】verilog中有符号数和无符号数的本质探究
【芯片设计】论RTL中always语法的消失术
【芯片设计】代码即注释,注释即代码
【芯片设计】700行代码的risc处理器你确实不能要求太多了
入职芯片开发部门后,每天摸鱼之外的时间我们要做些什么呢
如何计算系统的outstanding 和 burst length?
芯片搬砖日常·逼死强迫症的关键词不对齐事件
熟人社会里,一群没有社会价值的局外人

芯时代青年
专心数字前端全流程,芯时代有为青年的自我修养
 最新文章