设计思路
w_clk与r_clk不同步,跨时钟域
需要模块:
1、读控制
2、写控制
3、双口RAM
4、Bin2Gray(跨时钟域---亚稳态---需要使用格雷码---减少亚稳态的概率)
5、SYN同步(将w_addr送到读控制模块----比较地址差判断空满,需要r_clk对w_addr同步)
(将r_addr送到写控制模块----比较地址差判断空满,需要w_clk对r_addr同步)
简单来说两级同步就是打两拍、用于跨时钟域设计
采样情况
只有1bit发生变化,采样时钟要么采到原地址,要么采到新地址
1、读时钟,最坏情况下,A--B,采样到A,若A为满,B为不满,则将“不满判断成了满”,禁止写操作,不会对逻辑产生影响,只是写操作被延迟
2、写时钟,最坏情况下,A--B,采样到A,若A为空,B为不空,则将“不空判断成了空”,禁止读操作,不会对逻辑产生影响,只是读操作被延迟
端口
1、w_rst、r_rst
2、r_clk、r_req、r_data
3、w_clk、w_req、w_data
4、w_full、r_empty
模块
1、写控制模块
输入:w_clk,rst_n,w_req,r_gaddr
输出:w_addr,w_gaddr,full,
写地址加:w_req&&(full==0)
产生full:读地址格雷码与写地址格雷码——高2 bit相反,其余相等
assign full={~w_gaddr[addr_width-1],~w_gaddr[addr_width-2],w_gaddr[addr_width-3:0]}==r_gaddr?1:0
bin2gray:从低往高,逐位异或,最高位不变
2、读控制模块
输入:r_clk,rst_n,r_req,w_gaddr
输出:r_addr,r_gaddr,empty
读地址加:r_req&&(empty==0)
产生empty:读地址格雷码与写地址格雷码相等
assign empty=(r_gaddr==w_gaddr)?1:0;
3、top模块
输入:w_clk,r_clk,rst_n,w_data,w_req,r_req
输出:r_data,full,empty
同步:
写地址同步到读控制:将w_gaddr先利用w_clk打一拍(不能组合逻辑输出),再利用r_clk打两拍
读地址同步到写控制:将r_gaddr先利用r_clk打一拍(不能组合逻辑输出),再利用w_clk打两拍