1.FIFO原理介绍
2.FIFO IP 在vivado中使用。
3.建立顶层文件
module fifo_test(
input clk_sys,
input rst_n
);
reg [15:0] w_data;
wire wr_en;
wire rd_en;
wire [15:0] r_data;
wire full;
wire empty;
wire [8:0] rd_data_count;
wire [8:0] wr_data_count;
wire clk_50M;
wire clk_25M;
wire locked;
wire fifo_rst_n;
wire wr_clk;
wire rd_clk;
reg [7:0] wcnt;
reg [7:0] rcnt;
//例化pll,产生写入时钟50MHz和输出时钟25Mhz,输出给FIFO
clk_wiz_0 pll_clk
(
// Clock out ports
.clk_out1(clk_50M), // output clk_out1
.clk_out2(clk_25M), // output clk_out2
// Status and control signals
.reset(rst_n), // input reset
.locked(locked), // output locked
// Clock in ports
.clk_in1(clk_sys)
); // input clk_in1
//PLL产生时钟赋值给FIFO
assign fifo_rst_n=locked;
assign wr_clk=clk_50M;
assign rd_clk=clk_25M;
//写FIFO状态机
localparam W_IDLE=1;
localparam W_FIFO=2;
reg [2:0] write_state;
reg [2:0] next_write_state;
always@(posedge wr_clk or negedge fifo_rst_n)
begin
if(!fifo_rst_n)
write_state<=W_IDLE;
else
write_state<=next_write_state;
end
always@(*)
begin
case(write_state)
W_IDLE:
begin
if(wcnt==8'd120)
next_write_state<=W_FIFO;
else
next_write_state<=W_IDLE;
end
W_FIFO:
next_write_state<=W_FIFO;
default:
next_write_state<=W_IDLE;
endcase
end
always@(posedge wr_clk or negedge fifo_rst_n)
begin
if(!fifo_rst_n)
wcnt<=8'd0;
else if (write_state==W_IDLE)
wcnt<=wcnt+1'b1;
else
wcnt<=8'd0;
end
//在写FIFO状态下,如果不满就继续向FIFO中写数据,写满就停止写入
assign wr_en=(write_state==W_FIFO)? ~full:1'b0;
//在写使能的情况下,写入数据值如何变化
always@(posedge wr_clk or negedge fifo_rst_n)
begin
if(!fifo_rst_n)
w_data<=16'd0;
else if(wr_en)
w_data<=w_data+1'b1;
end
//读数据时,FIFO状态机
localparam R_IDLE=1;
localparam R_FIFO=2;
reg [2:0] read_state;
reg [2:0] next_read_state;
always@(posedge rd_clk or negedge fifo_rst_n)
begin
if(!fifo_rst_n)
read_state<=R_IDLE;
else
read_state<=next_read_state;
end
always@(*)
begin
case(read_state)
R_IDLE:
begin
if(rcnt==8'd60)
next_read_state<=R_FIFO;
else
next_read_state<=R_IDLE;
end
R_FIFO:
next_read_state<=R_FIFO;
default:
next_read_state<=R_IDLE;
endcase
end
always@(posedge rd_clk or negedge fifo_rst_n)
begin
if(!fifo_rst_n)
rcnt<=8'd0;
else if (read_state==R_IDLE)
rcnt<=rcnt+1'b1;
else
rcnt<=8'd0;
end
//在读FIFO状态下,如果不空就从FIFO中读数据
assign rd_en=(read_state==R_FIFO)? ~empty:1'b0;
//例化FIFO IP核
fifo_ip FIFO_init (
.wr_clk(wr_clk), // input wire wr_clk
.rd_clk(rd_clk), // input wire rd_clk
.din(w_data), // input wire [15 : 0] din
.wr_en(wr_en), // input wire wr_en
.rd_en(rd_en), // input wire rd_en
.dout(r_data), // output wire [15 : 0] dout
.full(full), // output wire full
.empty(empty), // output wire empty
.rd_data_count(rd_data_count), // output wire [8 : 0] rd_data_count
.wr_data_count(wr_data_count) // output wire [8 : 0] wr_data_count
);
ila_0 ila_wr (
.clk(clk_sys), // input wire clk
.probe0(w_data), // input wire [15:0] probe0
.probe1(wr_en), // input wire [0:0] probe1
.probe2(full), // input wire [0:0] probe2
.probe3(wr_data_count) // input wire [8:0] probe3
);
ila_0 ila_rd (
.clk(clk_sys), // input wire clk
.probe0(r_data), // input wire [15:0] probe0
.probe1(rd_en), // input wire [0:0] probe1
.probe2(empty), // input wire [0:0] probe2
.probe3(rd_data_count) // input wire [8:0] probe3
);
endmodule
4.读写测试