前次提出了一个处于异步时钟域的MCU与FPGA直接通讯的完成方法,其实在这之前,特权同学想罗列一个异步时钟域中呈现的很典型的问题。也便是要用一个反例来阐明没有满足注重异步通讯会给整个规划带来什么样的损害。
特权同学要举的这个反例是真真切切的在某个项目上产生过的,很具有代表性。它不只会触及运用组合逻辑和时序逻辑在异步通讯中的好坏、并且能把亚稳态的损害活生生的展示在你面前。
从这个模块要完成的功用说起吧,如图1所示,完成的功用其实很简略的,便是一个频率计,只不过FPGA除了脉冲收集进行计数外,还要呼应CPU的操控。
图1 功用模块
CPU的操控总线是指一个片选信号和一个读选通讯号,当二者都有用时,FPGA需求对CPU的地址总线进行译码,然后把采样脉冲值送到CPU的数据总线上。
图2 CPU读时序
关于这样“简略”的功用,不少人或许会给出相似下面的以组合逻辑为主的完成方法:
input clk;
input rst_n;
input pulse;
input cs_n;
input rd_n;
input[3:0] addr_bus;
output reg[15:0] data_bus;
reg[15:0] counter;
always @(posedge pulse or negedge rst_n)
if(!rst_n) counter 《= 16‘d0;
else if(pulse) counter 《= counter+1’b1;
wire dsp_cs = cs_n & rd_n;
always @(dsp_cs or addr_bus)
if(dsp_cs) data_bus 《= 16‘hzzzz;
else begin
case(addr_bus)
4’h0: data_bus 《= counter;
4‘h1: ……;
……
default: ;
endcase
end
咋一看,或许你会觉得这个代码也没什么问题,功用好像都完成了。并且你会觉得这个代码简练,也不需求消耗多少逻辑就能完成。可是,关于这种时钟满天飞的规划,存在着许多亚稳态损害迸发的或许。脉冲信号和由CPU操控总线产生的选通讯号是来自两个异步时钟域的信号。它们作为内部的时钟信号时,一个写寄存器counter,一个读寄存器counter。那么,很明显的,存在着产生抵触的或许。换句话说,假如寄存器正处于改动状况(被写)时被读取了,问题就跟着而来,如图3所示。
图3 数据抵触
脉冲信号pulse和CPU读选通讯号cpu_cs是异步信号,pulse什么时分呈现上升沿和cpu_cs什么时分呈现下降沿是不可控的。所以,假如它们很不幸的一同触发了,那么,成果可想而知。计数器counter[15:0]正在加一,这个自增的进程还在进行中,CPU数据总线data_bus[15:0]来读取counter[15:0],那么究竟读取的值是自增之前的值仍是自增之后的值呢?或者是其它的值呢?
所示,它是一个计数器的近似模型。当计数器自增一的时分,假如最低位为0,那么自增的成果只会使最低位翻转;当最低位为1,那么自增一的结果除了使最低位翻转,还有或许使其它任何位翻转,比方4’b1111自增一的结果会使4个位都翻转。因为每个位之间从产生翻转到翻转完成都需求通过一段逻辑延时和走线延时,关于一个16位的计数器,要想使这16位寄存器的翻转时刻共同,那是不或许做到的。所以,关于之前的规划中呈现了如图3的抵触时,被读取的脉冲值很或许是彻底过错的。
图4 计数器模型
上面的代码是最典型的组合逻辑完成方法,是很不可行的。或许许多朋友会提出异议,或许还会提出许多相似的组合逻辑计划。可是,假如没有同步规划的思维,不把这两个异步时钟域的信号同步到一个时钟域里进行处理,抵触的问题在无法得到有用处理的。
那么,这个规划该假如同步呢?完成的计划其实上一次说到FPGA与MCU通讯的文里现已给出了答案。它的规划思维能够如图5所示。图5先是运用脉冲检测法把脉冲信号与体系时钟信号clk同步,然后仍然运用脉冲检测法得到一个体系时钟宽度的使能脉冲作为数据锁存信号,也将CPU的操控信号和体系时钟信号clk同步了。如此处理后,两个异步时钟域的信号就不存在任何读写抵触的状况了。
图5 同步处理
这儿提出来的处理计划便是运用了脉冲检测法进行同步,还有一些其它的同步方法,比如专用握手信号同步、异步FIFO等等。
责任编辑:gt