在5.3章的蜂鸣器封装实验中,介绍了FIFO在封装中用于缓冲输入信息,从而使得该接口可以独立于上一层模块。相反的,在5.4章的PS2封装试验中,FIFO用于输出信息的缓冲。
本章实验基本上和上两章实验很类似,FIFO都是由于输入缓冲,和输出缓冲,从而使得接口独立于上一层模块。在这里笔者再重复一下:当我们在练习单片机的时候,常常会误会,串口发送和串口接收都是基于在一起,实际上它们是各自独立的。对于这件事情,串口发送和抽口接收,必须拥有各自的接口。
tx_interface.v 组合模块中的“串口发送模块”是在实验中完成建模的。此外在该组合模块中,最左方的是用于缓冲输入信息的FIFO模块(16个深度)。然而中间的控制模块,只用于“协调控制”FIFO模块和串口发送模块(哎~名字很囧)。
“图形”已经将tx_interface.v 表达的非常直接了,具体的操作我们还是直接看源码:
第21~45行是该控制模块的核心部分。当i步骤等于0的时候(31行),如果FIFO模块不为空的话,i就递增以示下一个步骤。
在34~38行,isRead 在步骤 1 被拉高,然后在步骤 2 又被拉低,该意思是从FIFO读取一个深度的数据。有一点,必须注意的是,在11行定义的TX_Data输出是直接由FIFO_Read_Data(7行)驱动(51行)。
在40行,步骤3将 isTX 标志寄存器拉高,以示使能(启动)串口发送模块(42行)。
当串口发送模块完成一次性的发送操作后,会反馈一个完成信号,然后if条件(41行)会成立,isTX被拉低,和i被赋予0,以示重复另一次发送操作。
完成后的扩展图:
上图是 rx_interface.v 的组合模块。串口接收模块是基于实验十建模而成的。rx_interface.v 的功能大致上如下:
该控制模块一开始就使能串口接收模块,当串口接收模块完成一次性的读取操作以后,就会反馈数据 RX_Data 和完成信号RX_Done_Sig。当串口接收顶层控制模块(名字依然很囧)接收到串口接收模块反馈的完成信号,就会不使能串口接收模块。然后该控制模块就会将 经RX_Data 反馈回来的数据缓冲致FIFO模块。
在21~44行是该控制模块的核心功能。在步骤0(31)行,isRX被拉高,此时串口接收模块就被使能(32行)。当串口接收模块完成一次性的读取操作,串口接收模块就会反馈一个完成信号。然而在32行 if条件就会成立,isRX被拉低,然后i递增以示下一个步骤。
在36行步骤1,如果FIFO不为满状态(Full_Sig拉低),i递增以示下一个步骤。
在38~42行,在步骤2,isWrite被拉高,然后在步骤3, isWrite被拉低。在这里需要注意一点 ,FIFO_Write_Data 信号直接由 RX_Data ,当串口接收模块反馈完成信号以后,RX_Data已经准备好FIFO_Write_Data 的输入数据。一旦 isWrite 被拉高又被拉低,RX_Data 信号已经就绪的数据会被写入 FIFO。
当完成一次性的数据读取操作,i会被赋予0,以示重新执行以上的所有步骤。
该组合模块和“图形”几乎是一样,哎笔者也懒得说什么了...
完成的扩展图:
补充:在这里读者可能会为“FIFO里信息卡住现象”而产生许多疑问。那么笔者反问读者先,串口是用来传输什么?对!串口是用来传输数据。我们可以这样想,如果某一波数据流的最后一个数据卡在FIFO里,那么这个数据就会被下一波的数据流给挤出。
说简单点,如果是单纯的“数据与数据之间的传输”对于“数据卡住现象”的影响是很小。因为数据流的传输,有如被开着的水龙头,水会源源不断的流着 ... 顶多在关起水龙头的前一个时间,再往水龙头开一下子(在数据流的传输完结之前再写入一个无关的数据,以达到挤出最后一个数据的效果)。
在这个演示中主要是演示如何调用串口接收接口和串口发送接口。实际上这个演示时没有实际的意义。当串口接收接口完成数据读取后,就会将数据缓冲在自己的FIFO里。然后中间控制模块就会判断该FIFO的状态,再从FIFO中读取数据,然后将数据写入串口发送节后的FIFO里。
在全部的操作中中间控制模块,如同中介的工作,将数据从一方移去另一方,完全没有介入串口接收|发送接口的操作之中。从另一个角度去看,在 rx_tx_interface_demo.v 中的接口(串口接收接口和串口发送接口)和中间模块控制模块,完全是独立的。
在29~50行是中间控制模块的主要功能。在步骤0,先判断 rx_interface.v 的FIFO是否为空,如果不为空 if条件就成立,i 就递增以示下一个步骤(32行)。
在34~38行,表示从 rx_interface.v 读取一个深度的数据。
当完成从 rx_interface.v 的FIFO读取一个深度的数据以后,数据在FIFO_Read_Data信号上已经就绪。在步骤3,先判断 tx_inerface.v 的FIFO是否为满状态?如果 tx_interface.v 的 FIFO 不为满状态,i会递增以示下一个步骤。
在这里请注意, FIFO_Write_Data 是直接由 FIFO_Read_Data 驱动。在43~47行,主要是将数据写入 tx_interface.v 的FIFO内。
最后i被赋予0,以示重复上述的动作。
演示的结果会是:当你从上位机发送 十六进制 的数据,该数据会经过 FPGA 然后传回至上位机显示。所以我说演示结果实际上是没有意义的 ...
完成后的扩展图:
该演示说白了,就是演示FIFO的调用。在实验十六至十八,FIFO几乎扮演着很重要的角色。FIFO用来缓冲数据,该目的本身是没有什么亮点,但是FIFO可以使某个模块封装后,拥有“独立性”的特性,这才是重点。从另一个角度来看,如果某个接口包含FIFO,那么该接口的调用方式都是清一色。
文章评论(0条评论)
登录后参与讨论