异步时钟域数据复用设计201122070345吴艳兵1,设计思路:在FIFO的输入端是两路数据同时输入,但要将第二路DIN的数据插入TS_IN的空帧当中,就需要将DIN进行存储,由于DIN的时钟频率比TS_IN的频率低,因此需要异步的FIFO来实现复用,而TS传输流中的空帧足够多,这就保证了能够将DIN的数据不丢失的插入到TS_IN的空帧中去,并输出,而且是按照TS传输流格式进行传输。这里因为TS_IN的空帧中有7个是空位,因此我选择FIFO的存储深度为16个8位的,这样能够保证在存到一半左右的数据时就会从FIFO中读取数据输出,而保证了FIFO不会被存满的情况。2,设计流程:本次设计分为3个模块。第一个模块,分为四种状态。1),CHECKOUTTWO(开始检测输出模式),此状态在SYNC高电平到来的时候就进入,然后检测后来数据是否是EE:是,则进入OUTTWO(模式二确定状态);不是,则进入OUTONE(输出模式一态),输出的是TS_IN的数据,并且FIFO继续存储DIN的数据。2),OUTTWO(模式二确定状态),检测后来数据是否是EE,如果不是,进入OUTONE(输出模式一态),输出TS_IN的数据,并输出!en低电平;如果是EE,进入OUT_TWO(输出模式二态),并输出en高电平,驱动FIFO输出,此时输出保存在FIFO中的数据。3),OUTONE(输出模式一态),输出TS_IN的数据,并持续保持在该状态,维持输出!En低电平,直到下一个SYNC高电平的到来。4),OUTTWO(输出模式二态),输出保存在FIFO中的数据,并持续保持该状态,未出输出en高电平,直到下一个SYNC高电平的到来。3,第二个模块,FIFO,我是直接调用的Quartus自带的异步时钟FIFO来处理DIN数据的存储。4,第三个模块,我编写的是一个两路选择模块,实现的是检测第一个模块的en输出,如果是高,则将通路切换到第二路,输出FIFO中存储的DIN数据。如果是低,则将通路切换到第一路,输出TS_IN的数据,这样进行两路的切换也就相当于是实现了两路异步时钟数据的插入操作。5,状态转移图:5),模块一MY状态转移:EEEESYNC!EE!EE2),模块三choose状态转移则比较简单:SYNC!enen6,Quartus硬件布局:CHECKOUTTWOOUTTWOOUTONEOUT_TWOSTART输出第一路TS_IN输出第二路DIN7,仿真结果,由于Quartus的观察长度有限,我在这里只能设定另外的clk和clk_w时钟。为了区别两路数据,我将第一路TS_IN都设置为有A-F的字母组成的16进制数据,第二路DIN都设置为有0-9组成的16进制数据。可以看到,TS_IN和d两路输入和各自在模块一和FIFO的处理之后的输出,以及经过choose选择模块选择通路之后的输出,当enr变高时,d路数据完全插进到TS_IN数据的空帧当中输出了。4,程序代码://***********模块一MY代码*************moduleMY(clk_in,ts_in,state,en_out,sync,ts_out);inputsync,clk_in;//同步表示及时钟input[7:0]ts_in;//输入数据流outputen_out;//使能输出output[7:0]ts_out;//数据输出口output[3:0]state;//状态寄存器//******状态定义******parameterCHECKOUTTWO=3'b001;//开始检测输出模式parameterOUTTWO=3'b010;//模式二确定态parameterOUT_TWO=3'b011;//输出模式二态parameterOUTONE=3'b100;//输出模式一态//regs&wiresreg[3:0]state;reg[7:0]ts_out;regen_out;//******状态转移部分******always@(negedgeclk_in)if(sync==1)beginstate=CHECKOUTTWO;en_out=0;ts_out=ts_in;endelsecase(state)//******开始检测输出模式******CHECKOUTTWO:begints_out=ts_in;if(ts_in==8'HEE)beginstate=OUTTWO;//当检测到第一个EE时,进入模式二确定态,并抑制FIFO,不让他输出存在其中的DIN数据。en_out=0;endelsestate=OUTONE;//当没有检测到EE时,立刻进入输出模式一态。end//******模式二确定态******OUTTWO:begints_out=ts_in;if(ts_in==8'HEE)beginstate=OUT_TWO;//搜索到第二个EE时,立刻进入输出模式二态。endelsestate=OUTONE;//第三个字不是EE时,进入输出模式一态。end//******输出模式二态******OUT_TWO:beginen_out=1;//输出一个使能,使能FIFO输出存储在其中的DIN数据,并维持在此状态直到下一个SYNC高的到来重新进行状态判断。state=OUT_TWO;end//******输出模式一态******OUTONE:beginstate=OUTONE;//此时输出TS_IN数据,并输出一个低的en,让FIFO不输出,继续存数据直到下一个SYNC高电平的到来再重新进行状态的判断。ts_out=ts_in;en_out=0;endendcaseendmodule//******模块三choose代码******modulechoose(en,input_one,input_two,clk,sync,data);inputen,clk,sync;//使能,时钟,同步标志input[7:0]input_one;//第一路输入数据input[7:0]input_two;//第二路输入数据output[7:0]data;//输出数据reg[7:0]data;//数据输出口//******通路选择部分******always@(negedgeclk)beginif(en)data=input_two;//当en有效的时候,输出的是第一路数据TS_IN送过来的数据。elsedata=input_one;//当en无效的时候,输出的是第二路存储在FIFO中的数据。endendmodule