fpga 存储器有三大部分,RAM、ROM、FIFO,下面还有分支小部分DRAM、SRAM、Flash、CAM等,但是只对三大部分说明,实际使用的也是最多。
一、FIFO
1、FIFO:first in first out ,顺序存取,先入先出,是一种数据缓存器。
应用场景:
1不同的时钟域:数据的生成速率,与数据的使用读取速率不相等,使用FIFO作为数据的临时缓存。(异步时钟)
2不同位宽/相同位宽:数据的接收与发送位宽不等,这个时候用FIFO来缓存,使数据收发正确。(同步时钟)
重要参数:FIFO 位宽,深度,写满,读空,剩余数据个数,复位信号
看到网上的比喻很形象,FIFO例如隧道,位宽就是隧道里有几条车道,深度就是每条车道有几辆车,当隧道内车停满时,就是写满标志置1;当隧道内车走完时就是读空,隧道出口每条车道同时出车也就是位宽。如图
同步FIFO设计原则:空满判断
FIFO 的设计原则是任何时候都不能向满FIFO中写入数据(写溢出),任何时候都不能从空FIFO中读取数据(读溢出)。FIFO 设计的核心是空满判断。FIFO设置读,写地址指针,FIFO初始化的时候 读指针和写指针都指向地址为0的位置, 当往FIFO里面每写一个数据,写地址指针自动加1指向下一个要写入的地址。当从FIFO里面每读一个数据,读地址指针自动加1指向下一个要读出的地址,最后通过比较读地址指针和写地址指针的大小来确定空满状态.
注意:FIFO指针自动增加,指针不要出问题,不可以指定地址更改数据(RAM可以)。
代码:FIFO的设计可以通过IP核设计,也可以直接用代码设计同步时钟FIFO。
1、代码设计FIFO:
module fifo_savemod
#(
//FIFO 存储数据的宽度数据位 16
parameter FIFO_WIDTH = 16,
//FIFO 存储数据的深度16 16 x 16 = 256位数据
parameter FIFO_DEPTH = 16,
parameter FIFO_CNT_WIDTH = 5 //log_2_FIFO_DEPTH + 1
)
(
input clk, rst,
input [1:0]iEn,
input [FIFO_WIDTH - 1 : 0] iData,//写入的数据
output [FIFO_WIDTH - 1 : 0] oData,//读出的数据
output [1:0]oTag
);
//parameter FIFO_DEPTH = 16'd1 << FIFO_CNT_WIDTH - 1;
reg [FIFO_WIDTH - 1 : 0] RAM [FIFO_DEPTH - 1 : 0];
reg [FIFO_WIDTH - 1:0] D1;
reg [FIFO_CNT_WIDTH - 1 : 0] C1,C2; // N+1
always @ ( posedge clk or negedge rst )
if( !rst ) begin
C1 <= 0; end
//iEn[1] == 1 从地址1开始写入数据
//写入数据 像是一个二位数组
else if( iEn[1] ) begin
RAM[ C1[FIFO_CNT_WIDTH - 2 : 0] ] <= iData;
C1 <= C1 + 1'b1;
end
always @ ( posedge clk or negedge rst )
if( !rst ) begin
D1 <= 0;
C2 <= 0; end
//iEn[0] == 1 读出从地址1开始读出数据
//读出数据到D1也就是oDAta 二维数组
else if( iEn[0] ) begin
D1 <= RAM[ C2[FIFO_CNT_WIDTH - 2 : 0] ];
C2 <= C2 + 1'b1;
end
assign oData = D1;
assign oTag[1] = ((C1[FIFO_CNT_WIDTH - 1] ^ C2[FIFO_CNT_WIDTH - 1]) & (C1[FIFO_CNT_WIDTH - 2 : 0] == C2[FIFO_CNT_WIDTH - 2 : 0]) ); // Full
assign oTag[0] = ( C1 == C2 ); // Empty
endmodule
2、FIFO 读写测试
module uart_fifo_send(
input sys_clk,
input sys_rst_n,
input [1:0]tis_tx_otag,
input AT_OK_STATE_buffer,
input [232-1:0] tis_tx_fifo,
input uart_tx_busy,
output reg [1:0] tis_tx_ien,
output reg uart_send_en,
output reg [7:0]uart_send_data,
output reg AT_OK_DOWN,
output reg [232-1:0] tis_tx_dat
);
reg [3:0] irtf;
reg [15:0] i;
//fifo 数据发送
reg [7:0] tis_tx_buf [39:0];
reg [232-1:0] sa_tx_buf [15:0];
reg en_flga;
reg uart_en_d0;
reg uart_en_d1;
/*
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
tis_tx_ien[1]<= 1'b0;
sa_tx_buf[0] <= {8'hff,16'hffff,{64{1'b1}},{{8'd232-8'd64-8'd24}{1'b1}}};
end
else
tis_tx_ien[1]<= 1'b1;
tis_tx_dat <= sa_tx_buf[0];
end
*/
//捕获uart_tx_busy下降沿,得到一个时钟周期的脉冲信号
assign en_flag = uart_en_d1 & (~uart_en_d0);
//对发送使能信号uart_en延迟两个时钟周期
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
uart_en_d0 <= 1'b0;
uart_en_d1 <= 1'b0;
end
else begin
uart_en_d0 <= uart_tx_busy;
uart_en_d1 <= uart_en_d0;
end
end
reg tx_ready;
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
i <= 16'b0;
irtf <= 4'd0;
tx_ready <= 1'b0;
AT_OK_DOWN <= 1'b0;
tis_tx_ien[1]<= 1'b0;
sa_tx_buf[0] <= {8'h00,16'h1122,{64{1'b1}},{{8'd232-8'd64-8'd40}{1'b1}},8'h0D,8'h0A};
end
else if((AT_OK_STATE_buffer == 1'b1) && (i <= 16'd33))begin
case(irtf)
0:
begin
tis_tx_ien[1]<= 1'b1;
tis_tx_dat <= sa_tx_buf[0];
irtf <= irtf + 1'b1;
end
1:
begin
tis_tx_ien[1]<= 1'b0;
irtf <= irtf + 1'b1;
end
2:
if(!tis_tx_otag[0]) begin
// tis_tx_ien[1] <= 1'b0;
tis_tx_ien[0] <= 1'b1;
//faf0
tis_tx_buf[0] <= 8'hfa;
//faf0
tis_tx_buf[1] <= 8'hf0;
//8'h1b 8'd37
tis_tx_buf[2] <= 8'hf1;
//8'ha4
tis_tx_buf[3] <= 8'ha4;
tis_tx_buf[4] <= 8'ha5;
tis_tx_buf[5] <= 8'ha6;
//8'd37-3'd4=33
// tis_tx_data_len <= COM_PTL_LEN_AX_VEL-3'd4;
//状态机到下一状态
irtf <= irtf + 1'b1; end
else begin
tis_tx_ien[0] <= 1'b0;
irtf <= irtf + 1'b1;
end
3: begin
tis_tx_ien[0] <= 1'b0;
irtf <= irtf + 1'b1; end
4:
begin
for(i=16'd4;i<16'd33;i=i+1'b1) begin
tis_tx_buf[i] <= tis_tx_fifo[(16'd37-16'd4-i)*8-1 -:8];
end
irtf <= irtf + 1'b1;
i <= 1'b0;
end
5:
begin
uart_send_data <= tis_tx_buf[i];
tx_ready <= 1'b1;
if(tx_ready && (~uart_tx_busy)) begin //检测串口发送模块空闲
tx_ready <= 1'b0; //准备过程结束
uart_send_en <= 1'b1; //拉高发送使能信号
//i <= i + 1'b1;
irtf <= 4'd5;
end
else if(uart_send_en == 1'b1)begin
i <= i + 1'b1;
tx_ready <= 1'b0;
uart_send_en <= 1'b0;
irtf <= 4'd5;
if(i > 16'd33)begin
i <= 16'b0;
end
end
else if(i == 16'd33)begin
i <= 16'b0;
irtf <= 4'd5;
AT_OK_DOWN <= 1'b1;
end
end
default: begin
irtf <= 4'd5;
i <= i;
//AT_OK_STATE_buffer <= 1'b0;
end
endcase
end
else if(tx_ready && (~uart_tx_busy)) begin //检测串口发送模块空闲
//tx_ready <= 1'b0; //准备过程结束
//uart_send_en <= 1'b1; //拉高发送使能信号
i <= i;
if(i == 16'b0)begin
i <= 16'b0;
AT_OK_DOWN <= 1'b0;
end
end
else if(i == 16'b0)begin
i <= 16'b0;
AT_OK_DOWN <= 1'b0;
end
end
endmodule
3、顶层模块
module uart_loop_test(
input sys_clk,
input sys_rst_n,
input uart_rxd,
output uart_txd
);
//parameter
parameter CLK_FREQ = 50000000;
parameter UART_BPS = 115200;
//fifo
parameter TIS_OUT_FIFO_BIT_WIDTH = 9'd232; //8'd64;
parameter TIS_OUT_FIFO_CNT = 4'd8;//5;3;7;
parameter TIS_OUT_FIFO_DEPTH = 8'd128;//16;4;64;
//wire define
wire uart_recv_done;
wire [7:0] uart_recv_data;
wire uart_send_en;
wire AT_OK_STATE;
wire [7:0] uart_send_data;
wire uart_tx_busy;
wire clk_100m_0;
wire clk_150m;
//
wire [1:0] tis_tx_otag;
wire [232-1:0] tis_tx_fifo;
//reg//
reg [232-1:0] sa_tx_dat;
wire [1:0]tis_tx_ien;
wire [232-1:0] tis_tx_dat;
wire AT_OK_DOWN;
//************************************
//*** main code
//************************************
//模块例化时对应
uart_receive #(
.CLK_FREQ (CLK_FREQ), //设置系统时钟频率
.UART_BPS (UART_BPS)) //设置串口接收波特率
u_uart_recv(
.clk (sys_clk),
.rst_n(sys_rst_n),
.uart_rxd(uart_rxd),
.uart_done(uart_recv_done),
.uart_data(uart_recv_data)
);
//串口发送模块
uart_send#(
.CLK_FREQ(CLK_FREQ), //设置系统时钟频率
.UART_BPS(UART_BPS)) //设置串口发送波特率
u_uart_send(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.uart_en(uart_send_en),
.uart_din(uart_send_data),
.uart_tx_busy(uart_tx_busy),
.uart_txd(uart_txd)
);
//串口环回模块
uart_loop u_uart_loop(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.recv_done(uart_recv_done), //接收一帧数据完成标志位
.recv_data(uart_recv_data), //接收数据
.AT_OK(AT_OK_STATE),
.AT_OK_DOWN_LOOP(AT_OK_DOWN),
.tx_busy(), //发送忙状态标志
.send_en(), //发送使能信号
.send_data() //待发送数据
);
pll pll_inst (
.inclk0 (sys_clk),
.c0 (clk_100m_0),
.c1 (clk_150m)
//.c4 ( clk_1m )
);
fifo_savemod
#(
.FIFO_WIDTH(TIS_OUT_FIFO_BIT_WIDTH),
.FIFO_DEPTH(TIS_OUT_FIFO_DEPTH),
.FIFO_CNT_WIDTH(TIS_OUT_FIFO_CNT)
) TIS_SEND_FIFO
(
.clk(sys_clk),
.rst(sys_rst_n),
.iEn(tis_tx_ien),
.iData(tis_tx_dat),
.oData(tis_tx_fifo),
.oTag(tis_tx_otag)
);
/*
fifo_v fifo_v (
clock(sys_clk),
data(tis_tx_dat),
rdreq(tis_tx_otag),
wrreq(tis_tx_ien),
q(tis_tx_fifo)
);
*/
uart_fifo_send uart_fifo_send(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.tis_tx_otag(tis_tx_otag),
.AT_OK_STATE_buffer(AT_OK_STATE),
.tis_tx_ien(tis_tx_ien),
.uart_send_en(uart_send_en),
.uart_send_data(uart_send_data),
.tis_tx_fifo(tis_tx_fifo),
.uart_tx_busy(uart_tx_busy),
.AT_OK_DOWN(AT_OK_DOWN),
.tis_tx_dat(tis_tx_dat)
);
endmodule
IP核设计:FIFO的设计可以通过IP核设计异步时钟FIFO。
1、IP核设计
位宽232,深度32,读写时钟,读写使能,读写端口,写满读空标志位。不同位宽设置可以在IP核设计选项中实现,输入输出位宽不一样。
对于FIFO的深度与位宽的需求计算根据同一时刻写入的数据与读出的数据做差得到的值就是FIFO的大小。
2、读数据
注意,读代码流程,以及读使能后需要几个时钟周期才有数据。
module fifo_rd(
input sys_clk,
input sys_rst_n,
input [231:0] data ,
input rdfull ,
input rdempty ,
output reg rdreq ,
input AT_OK ,
input uart_tx_busy ,
output reg uart_send_en ,
output reg AT_OK_DOWN ,
output reg [7:0] send_data_buffer
);
//reg define
reg [4:0] rd_num;
reg [7:0]data_buffer[29:0];
reg [7:0] i;
reg tx_ready;
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
rd_num <= 5'd0;
rdreq <= 1'b0;
send_data_buffer <= 8'd0;
i <= 8'd0;
end
else if((AT_OK == 1'b1) && (i <= 8'd29))begin
case(rd_num)
5'd0:
begin
//如果fifo满,下一个状态,否则当前状态
if(rdfull)begin
rdreq <= 1'b1;
rd_num <= rd_num + 1'b1;
end
rd_num <= rd_num + 1'b1;
end
5'd1:
begin
rdreq <= 1'b1;
rd_num <= rd_num + 1'b1;
i <= 8'd0;
end
5'd2:
begin
rdreq <= 1'b1;
rd_num <= rd_num + 1'b1;
i <= 8'd0;
end
5'd3:
begin
if(rdempty)begin
rdreq <= 1'b0;
rd_num <= 5'd0;
end
else begin
rdreq <= 1'b1;
for(i=8'd0;i<8'd29;i=i+1'b1) begin
data_buffer[i] <= data[(8'd29-i)*8-1 -:8];
end
rd_num <= rd_num + 1'b1;
i <= 8'd0;
end
end
5'd4:
begin
rdreq <= 1'b0;
rd_num <= rd_num + 1'b1;
end
5'd5:
begin
send_data_buffer <= data_buffer[i];
tx_ready <= 1'b1;
if(tx_ready && (~uart_tx_busy)) begin //检测串口发送模块空闲
tx_ready <= 1'b0; //准备过程结束
uart_send_en <= 1'b1; //拉高发送使能信号
//i <= i + 1'b1;
rd_num <= 5'd5;
end
else if(uart_send_en == 1'b1)begin
i <= i + 1'b1;
tx_ready <= 1'b0;
uart_send_en <= 1'b0;
rd_num <= 5'd5;
if(i > 8'd29)begin
i <= 8'd0;
rd_num <= 5'd0;
end
end
else if(i == 8'd29)begin
i <= 8'd0;
rd_num <= 5'd0;
AT_OK_DOWN <= 1'b1;
end
end
default:;
endcase
end
else if(tx_ready && (~uart_tx_busy)) begin //检测串口发送模块空闲
//tx_ready <= 1'b0; //准备过程结束
//uart_send_en <= 1'b1; //拉高发送使能信号
i <= i;
if(i == 8'd0)begin
i <= 8'd0;
AT_OK_DOWN <= 1'b0;
rd_num <= 5'd0;
end
end
else if(i == 8'd0)begin
i <= 8'd0;
AT_OK_DOWN <= 1'b0;
rd_num <= 5'd0;
end
end
endmodule
3、写数据
注意:判断写满和写空标志
module fifo_wr(
input sys_clk ,
input sys_rst_n,
input wrempty ,
input wrfull ,
input AT_OK ,
output reg [231:0] data ,
output reg wrreq
);
reg [232-1:0] ram_buf [15:0];
reg [4:0] fifo_num;
//写数据
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
ram_buf[0] <= {8'haa,16'hbbcc,{64{1'b1}},{{8'd232-8'd64-8'd40}{1'b1}},8'h0D,8'h0A};
fifo_num <= 4'd0;
data <= 232'd0;
wrreq <= 1'b0;
end
//接收到指令写入数据
else if(1'b1)begin
case(fifo_num)
5'd0:
begin
//如果写是空的,进入下一个状态,否则在当前状态
if(wrempty == 1'b1)begin
wrreq <= 1'b1;
fifo_num <= fifo_num + 1'b1;
end
else
fifo_num <= fifo_num;
end
5'd1:
begin
//如果写满了,返回上一个状态,如果没有写满,继续写
if(wrfull == 1'b1)begin
wrreq <= 1'b0;
data <= 232'd0;
fifo_num <= 5'd0;
end
else
wrreq <= 1'b1;
data <= ram_buf[0];
fifo_num <= 5'd2;
end
default:fifo_num <= 5'd0;
endcase
end
end
endmodule
4、顶层模块
module uart_loop_test(
input sys_clk,
input sys_rst_n,
input uart_rxd,
output uart_txd
);
//parameter
parameter CLK_FREQ = 50000000;
parameter UART_BPS = 921600;
//fifo
parameter TIS_OUT_FIFO_BIT_WIDTH = 9'd232; //8'd64;
parameter TIS_OUT_FIFO_CNT = 4'd8;//5;3;7;
parameter TIS_OUT_FIFO_DEPTH = 8'd128;//16;4;64;
//wire define
wire uart_recv_done;
wire [7:0] uart_recv_data;
wire uart_send_en;
wire AT_OK_STATE;
wire AT_OK_STATE_2;
wire [7:0] uart_send_data;
wire uart_tx_busy;
wire clk_100m_0;
wire clk_150m;
wire clk_50m;
wire clk_25m;
//
wire [1:0] tis_tx_otag;
wire [232-1:0] tis_tx_fifo;
//reg//
reg [232-1:0] sa_tx_dat;
wire [1:0]tis_tx_ien;
wire [232-1:0] tis_tx_dat;
wire AT_OK_DOWN;
//************************************
//*** main code
//************************************
//模块例化时对应
uart_receive #(
.CLK_FREQ (CLK_FREQ), //设置系统时钟频率
.UART_BPS (UART_BPS)) //设置串口接收波特率
u_uart_recv(
.clk (sys_clk),
.rst_n(sys_rst_n),
.uart_rxd(uart_rxd),
.uart_done(uart_recv_done),
.uart_data(uart_recv_data)
);
//串口发送模块
uart_send#(
.CLK_FREQ(CLK_FREQ), //设置系统时钟频率
.UART_BPS(UART_BPS)) //设置串口发送波特率
u_uart_send(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.uart_en(uart_send_en),
.uart_din(uart_send_data),
.uart_tx_busy(uart_tx_busy),
.uart_txd(uart_txd)
);
//串口环回模块
uart_loop u_uart_loop(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.recv_done(uart_recv_done), //接收一帧数据完成标志位
.recv_data(uart_recv_data), //接收数据
.AT_OK(AT_OK_STATE),
.AT_OK_2(AT_OK_STATE_2),
.AT_OK_DOWN_LOOP(AT_OK_DOWN)
//.tx_busy(), //发送忙状态标志
//.send_en(), //发送使能信号
//.send_data() //待发送数据
);
pll pll_inst (
.inclk0 (sys_clk),
.c0 (clk_100m_0),
.c1 (clk_150m),
.c2 (clk_50m),
.c3 (clk_25m)
);
fifo_savemod
#(
.FIFO_WIDTH(TIS_OUT_FIFO_BIT_WIDTH),
.FIFO_DEPTH(TIS_OUT_FIFO_DEPTH),
.FIFO_CNT_WIDTH(TIS_OUT_FIFO_CNT)
) TIS_SEND_FIFO
(
.clk(sys_clk),
.rst(sys_rst_n),
.iEn(tis_tx_ien),
.iData(tis_tx_dat),
.oData(tis_tx_fifo),
.oTag(tis_tx_otag)
);
/*
fifo_v fifo_v (
clock(sys_clk),
data(tis_tx_dat),
rdreq(tis_tx_otag),
wrreq(tis_tx_ien),
q(tis_tx_fifo)
);
*/
uart_fifo_send uart_fifo_send(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.tis_tx_otag(),
.AT_OK_STATE_buffer(),
.tis_tx_ien(),
.uart_send_en(),
//.uart_send_data(),
.tis_tx_fifo(),
.uart_tx_busy(),
.AT_OK_DOWN(),
.tis_tx_dat()
);
//把指定数据写入,在根据收到信号,把数据读出,
wire [12:0] ram_addr; //读写地址
//wire [231:0] ram_wr_data;//写数据
//wire ram_rd_en; //读使能
//wire ram_wr_en; //写使能
//wire [231:0] ram_rd_data;//读数据
ram_1port u_ram_1port(
.address (ram_addr),
.clock (sys_clk),
.data (),
.rden (),
.wren (),
.q ()
);
/*
//读写 ram 操作模块
uart_ram_send uart_ram_send(
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.ram_wr_en(), //写使能
.ram_rd_en(), //读使能
.ram_addr(ram_addr), //ram读写地址
.ram_wr_data(), //ram写数据
.ram_rd_data(), //ram读数据
.uart_send_data(),
.uart_send_en(), //串口接收数据正确,发送使能
.uart_tx_busy(),
.AT_OK_DOWN(),
.AT_OK_STATE_buffer(),
.AT_OK_STATE_buffer_2()
);
*/
//2ram define
ram_2port ram_2port_inst (
.data (ram_wr_data),
.wraddress (ram_wr_addr),
.wrclock (clk_100m_0 ),
.wren (ram_wr_en ),
.q (ram_rd_data ),
.rdaddress (ram_rd_addr ),
.rdclock (clk_50m ),
.rden (ram_rd_en )
);
//wire define
wire ram_wr_en;
wire [9:0] ram_wr_addr;
wire [231:0] ram_wr_data;
// 写入数据
uart_2ram_write uart_2ram_write(
.sys_clk (clk_100m_0) ,
.sys_rst_n(sys_rst_n) ,
.AT_OK(),
//ram写端口操作
.ram_wr_en(ram_wr_en) , //ram写使能
.ram_wr_addr(ram_wr_addr) , //写地址
.ram_wr_data(ram_wr_data) , //写数据
);
//wire
wire ram_rd_en;
wire [9:0] ram_rd_addr;
wire [231:0] ram_rd_data;
wire [231:0] ram_rd_data_buffer;
wire read_done;
//读出数据
uart_2ram_read uart_2ram_read(
.sys_clk (clk_50m),
.sys_rst_n(sys_rst_n),
//RAM读出数据
.ram_rd_en(ram_rd_en) ,
.ram_rd_addr(ram_rd_addr) ,
.ram_rd_data(ram_rd_data) ,
.AT_OK() ,
.uart_tx_busy(),
.uart_send_en(),
.AT_OK_DOWN(),
//.read_done(read_done)
.uart_send_data()
);
//FIFO
wire wrreq;
wire [231:0] data;
wire wrempty;
wire wrfull;
wire wrusedw;
wire rdreq;
wire [231:0] q;
wire rdempty;
wire rdfull;
wire rdusedw;
fifo fifo(
.wrclk ( clk_100m_0 ) , // 写时钟
.wrreq ( wrreq ) , // 写请求
.data ( data ) , // 写入 FIFO 的数据
.wrempty( wrempty ) , // 写空信号
.wrfull ( wrfull ) , // 写满信号
.wrusedw( wrusedw ) , // 写侧数据量
.rdclk ( clk_25m ) , // 读时钟
.rdreq ( rdreq ) , // 读请求
.q ( q ) , // 从 FIFO 输出的数据
.rdempty( rdempty ) , // 读空信号
.rdfull ( rdfull ) , // 读满信号
.rdusedw( rdusedw ) // 读侧数据量
);
fifo_wr fifo_wr(
.sys_clk (clk_100m_0) ,
.sys_rst_n (sys_rst_n) ,
.wrempty (wrempty) ,
.wrfull (wrfull) ,
.AT_OK (AT_OK_STATE),
.data (data) ,
.wrreq (wrreq)
);
fifo_rd fifo_rd(
.sys_clk (clk_25m) ,
.sys_rst_n (sys_rst_n) ,
.data (q) ,
.rdfull (rdfull) ,
.rdempty (rdempty) ,
.rdreq (rdreq) ,
.AT_OK (AT_OK_STATE) ,
.uart_tx_busy (uart_tx_busy) ,
.uart_send_en (uart_send_en) ,
.AT_OK_DOWN (AT_OK_DOWN) ,
.send_data_buffer (uart_send_data)
);
endmodule
二、RAM
三、ROM