调用xpm_fifo_sync原语和使用FIFO IP盒基本一致。使用xpm_fifo_sync优势:可以在代码中更改数据位宽和深度,不用再重新生成FIFO IP核。
原语打开方法:
将引脚设置成和调用FIFO IP一致,例化后:
module SYNC_FIFO#(
parameter READ_MODE = "fwft", //"std"- standard read mode;"fwft"- First-Word-Fall-Through read mode
parameter integer DATA_WIDTH = 32, //1 to 4096
parameter integer DATA_DEPTH = 2048, //16 to 4194304
parameter integer READ_LATENCY= 0 //0 to 100 "fwft":0; "std":1
)(
input wire clk,
input wire rst,
input wire [DATA_WIDTH-1 : 0] din,
input wire wr_en,
input wire rd_en,
output wire [DATA_WIDTH-1 : 0] dout,
output wire full,
output wire empty,
output wire [$clog2(DATA_DEPTH) : 0] data_count
);
wire [$clog2(DATA_DEPTH) : 0] rd_data_count;
wire [$clog2(DATA_DEPTH) : 0] wr_data_count;
assign data_count= wr_data_count;
wire sync_rst;
xpm_cdc_sync_rst #(
.DEST_SYNC_FF (3 ),
.INIT (1 ),
.INIT_SYNC_FF (0 ),
.SIM_ASSERT_CHK (0 )
)
u_sync_rst(
.dest_rst (sync_rst ),
.dest_clk (clk ),
.src_rst (rst )
);
xpm_fifo_sync #(
.DOUT_RESET_VALUE("0"), // String
.ECC_MODE("no_ecc"), // String
.FIFO_MEMORY_TYPE("block"), // String"auto", "block", "distributed", or "ultra";
.FIFO_READ_LATENCY(READ_LATENCY),// DECIMAL 0 to 100
.FIFO_WRITE_DEPTH(DATA_DEPTH), // DECIMAL 16 to 4194304
.FULL_RESET_VALUE(0), // DECIMAL
.PROG_EMPTY_THRESH(10), // DECIMAL
.PROG_FULL_THRESH(10), // DECIMAL
.RD_DATA_COUNT_WIDTH($clog2(DATA_DEPTH)+1), // DECIMAL 1 to 23
.READ_DATA_WIDTH(DATA_WIDTH), // DECIMAL
.READ_MODE(READ_MODE), // String//"std"- standard read mode;"fwft"- First-Word-Fall-Through read mode
.SIM_ASSERT_CHK(0), // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
.USE_ADV_FEATURES("0707"), // String
.WAKEUP_TIME(0), // DECIMAL
.WRITE_DATA_WIDTH(DATA_WIDTH), // DECIMAL
.WR_DATA_COUNT_WIDTH($clog2(DATA_DEPTH)+1) // DECIMAL 1 to 23
)
u_xpm_fifo_sync(
////OUTPUT
.almost_empty (),
.almost_full (),
.data_valid (),
.dbiterr (),
.dout (dout ),
.empty (empty ),
.full (full ),
.overflow (),
.prog_empty (),
.prog_full (),
.rd_data_count (rd_data_count),
.rd_rst_busy (),
.sbiterr (),
.underflow (),
.wr_ack (),
.wr_data_count (wr_data_count),
.wr_rst_busy (),
//INPUT
.din (din ),
.injectdbiterr (0 ),
.injectsbiterr (0 ),
.rd_en (rd_en ),
.rst (sync_rst ),
.sleep (0 ),
.wr_clk (clk ),
.wr_en (wr_en )
);
endmodule
同时使用IP生成一个FIFO进行仿真对比。
一、"fwft"模式(First-Word-Fall-Through read mode)
生成的FIFO IP同样设置为fwft模式,仿真代码如下:
`timescale 1ns / 1ps
module tb_syncfifo();
parameter READ_MODE = "fwft";//"std"- standard read mode;"fwft"- First-Word-Fall-Through read mode
parameter integer DATA_WIDTH = 32;
parameter integer DATA_DEPTH = 2048;
reg clk;
reg rst;
reg [DATA_WIDTH-1 : 0] din;
reg wr_en;
reg rd_en;
wire [DATA_WIDTH-1 : 0] dout;
wire full;
wire empty;
wire [$clog2(DATA_DEPTH) : 0] data_count;
wire [31 : 0] dout_IP;
wire full_IP;
wire empty_IP;
wire [11 : 0] data_count_IP;
SYNC_FIFO#(
.READ_MODE (READ_MODE),
.DATA_WIDTH (DATA_WIDTH),
.DATA_DEPTH (DATA_DEPTH),
.READ_LATENCY (0 )
)u_scfifo(
.clk (clk ),
.rst (rst ),
.din (din ),
.wr_en (wr_en ),
.rd_en (rd_en ),
.dout (dout ),
.full (full ),
.empty (empty ),
.data_count (data_count)
);
wire sync_rst;
xpm_cdc_sync_rst #(
.DEST_SYNC_FF (3 ),
.INIT (1 ),
.INIT_SYNC_FF (0 ),
.SIM_ASSERT_CHK (0 )
)
u_sync_rst(
.dest_rst (sync_rst ),
.dest_clk (clk ),
.src_rst (rst )
);
SCFIFO_32W_2048D u_IP_fifo(
.clk (clk ),
.srst (sync_rst ),
.din (din ),
.wr_en (wr_en ),
.rd_en (rd_en ),
.dout (dout_IP ),
.full (full_IP ),
.empty (empty_IP ),
.data_count (data_count_IP)
);
initial begin
clk<=0;
rst<=1;
#2000
rst<=0;
end
always #5 clk<=!clk;
reg [31:0] cnt;
always @(posedge clk or posedge rst)
begin
if (rst) begin
cnt <= 0;
end else begin
if(cnt>=6000)
cnt<=0;
else
cnt<=cnt+1;
end
end
always @(*)
begin
if (rst) begin
wr_en <= 0;
end else begin
if(cnt>200&&cnt<3000 && full==0)begin
wr_en <= 1;
end else
wr_en <= 0;
end
end
always @(posedge clk or posedge rst)
begin
if (rst) begin
din<=0;
end else begin
if(cnt>200&&cnt<3000 && full==0)begin
din <=din+1;
end
end
end
always @(*)
begin
if (rst) begin
rd_en <= 0;
end else begin
if(cnt>3000 && empty==0)begin
rd_en <= 1;
end else
rd_en <= 0;
end
end
endmodule
仿真波形如下:
1、写FIFO
FIFO空信号(empty):调用XPM原语和使用IP核一致,都在写入数据后延迟3个周期拉低;
FIFO计数信号(count):调用XPM原语计数延迟2个周期(与手册一致),调用IP核计数延迟1个周期。
FIFO满信号(full):调用XPM原语和使用IP核一致,都在写入2048+2个数据后拉高;
2、读FIFO
FIFO满信号(full):调用XPM原语和使用IP核一致,都在读取数据后1个时钟周期后拉低;
FIFO计数信号(count):调用XPM原语计数延迟2个周期,调用IP核计数延迟1个周期。
FIFO输出信号(dout): 调用XPM原语和使用IP核一致,rd_en使能时输出数据,无时钟延迟。
FIFO空信号(empty):调用XPM原语和使用IP核一致,都在读完数据后1个周期拉高;
二、"std"模式(standard read mode)
生成的FIFO IP同样设置为STD模式,仿真代码如下:
`timescale 1ns / 1ps
module tb_syncfifo_std();
parameter READ_MODE = "std";//"std"- standard read mode;"fwft"- First-Word-Fall-Through read mode
parameter integer DATA_WIDTH = 32;
parameter integer DATA_DEPTH = 2048;
reg clk;
reg rst;
reg [DATA_WIDTH-1 : 0] din;
reg wr_en;
reg rd_en;
wire [DATA_WIDTH-1 : 0] dout;
wire full;
wire empty;
wire [$clog2(DATA_DEPTH) : 0] data_count;
wire [31 : 0] dout_IP;
wire full_IP;
wire empty_IP;
wire [10 : 0] data_count_IP;
SYNC_FIFO#(
.READ_MODE (READ_MODE),
.DATA_WIDTH (DATA_WIDTH),
.DATA_DEPTH (DATA_DEPTH),
.READ_LATENCY (1 )
)u_scfifo(
.clk (clk ),
.rst (rst ),
.din (din ),
.wr_en (wr_en ),
.rd_en (rd_en ),
.dout (dout ),
.full (full ),
.empty (empty ),
.data_count (data_count)
);
wire sync_rst;
xpm_cdc_sync_rst #(
.DEST_SYNC_FF (3 ),
.INIT (1 ),
.INIT_SYNC_FF (0 ),
.SIM_ASSERT_CHK (0 )
)
u_sync_rst(
.dest_rst (sync_rst ),
.dest_clk (clk ),
.src_rst (rst )
);
SCFIFO_32W_2048D_STD u_IP_fifo(
.clk (clk ),
.srst (sync_rst ),
.din (din ),
.wr_en (wr_en ),
.rd_en (rd_en ),
.dout (dout_IP ),
.full (full_IP ),
.empty (empty_IP ),
.data_count (data_count_IP)
);
initial begin
clk<=0;
rst<=1;
#2000
rst<=0;
end
always #5 clk<=!clk;
reg [31:0] cnt;
always @(posedge clk or posedge rst)
begin
if (rst) begin
cnt <= 0;
end else begin
if(cnt>=6000)
cnt<=0;
else
cnt<=cnt+1;
end
end
always @(*)
begin
if (rst) begin
wr_en <= 0;
end else begin
if(cnt>200&&cnt<3000 && full==0)begin
wr_en <= 1;
end else
wr_en <= 0;
end
end
always @(posedge clk or posedge rst)
begin
if (rst) begin
din<=0;
end else begin
if(cnt>200&&cnt<3000 && full==0)begin
din <=din+1;
end
end
end
always @(*)
begin
if (rst) begin
rd_en <= 0;
end else begin
if(cnt>3000 && empty==0)begin
rd_en <= 1;
end else
rd_en <= 0;
end
end
endmodule
1、写FIFO
FIFO空信号(empty):调用XPM原语和使用IP核一致,都在写入数据后1个周期拉低;
FIFO计数信号(count):调用XPM原语计数延迟2个周期(与手册一致),调用IP核计数延迟1个周期。
FIFO满信号(full):调用XPM原语和使用IP核一致,都在写入2048个数据后拉高;
2、读FIFO
FIFO满信号(full):调用XPM原语和使用IP核一致,都在读取数据后1个时钟周期后拉低;
FIFO计数信号(count):调用XPM原语计数延迟2个周期,调用IP核计数延迟1个周期。
FIFO输出信号(dout): 调用XPM原语和使用IP核一致,rd_en使能后下一个时钟周期输出数据,1个时钟周期延迟。
FIFO空信号(empty):调用XPM原语和使用IP核一致,都在读完2048个数据后1个周期拉高;