// module example_fifo (
// input wire sys_clk ,
// input wire [7:0] pi_data ,
// input wire rd_req ,
// input wire wr_req ,
// output wire mepty ,
// output wire full ,
// output wire [7:0] po_data ,
// output wire [7:0] usedw
// );
// scfifo_8x256 scfifo_8x256_insert(
// .clock ( sys_clk ) ,
// .data ( pi_data ) ,
// .rdreq ( rd_req ) ,
// .wrreq ( wr_req ) ,
// .empty ( mepty ) ,
// .full ( full ) ,
// .q ( po_data ) ,
// .usedw ( usedw )
// );
// endmodule
module example_fifo(
input wire wr_clk ,
input wire wr_req ,
input wire [7:0] wr_data ,
input wire rd_clk ,
input wire rd_req ,
output wire [15:00] rd_data ,
output wire wr_empty ,
output wire wr_full ,
output wire [8:0] wr_usedw ,
output wire rd_empty ,
output wire rd_full ,
output wire [7:0] rd_usedw
);
dcfifo_8x256_to_16x128 dcfifo_8x256_to_16x128_inst (
.data ( wr_data ),
.rdclk ( rd_clk ),
.rdreq ( rd_req ),
.wrclk ( wr_clk ),
.wrreq ( wr_req ),
.q ( rd_data ),
.rdempty ( rd_empty ),
.rdfull ( rd_full ),
.rdusedw ( rd_usedw ),
.wrempty ( wr_empty ),
.wrfull ( wr_full ),
.wrusedw ( wr_usedw )
);
endmodule
`timescale 1ns/1ns
module test_dcfifo ();
reg wr_clk ; // dcfifo 输入信号定义
reg wr_req ;
reg [7:0] wr_data ;
reg rd_clk ;
reg rd_req ;
reg sys_rst_n; // 复位
reg [1:0] cnt_base ; // 用来产生读请求的计数器
reg wr_full_reg0 ;
reg wr_full_reg1 ;
wire [15:00] rd_data ;
wire wr_empty ;
wire wr_full ;
wire [8:0] wr_usedw ;
wire rd_empty ;
wire rd_full ;
wire [7:0] rd_usedw ;
parameter CYCLE = 20 ;
initial begin
wr_clk = 1'b1 ; // 读写时钟赋初值
rd_clk = 1'b1 ; // 复位信号描述
sys_rst_n <= 1'b0 ;
#(CYCLE) ;
sys_rst_n <= 1'b1 ;
end
always #(CYCLE / 2) wr_clk = ~wr_clk ; // 写时钟频率是读时钟的二倍。
always #(CYCLE ) rd_clk = ~rd_clk ;
// cnt_base 0 ~ 3 循环计数 为了产生写请求,故在写时钟域下。
always @(posedge wr_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
cnt_base <= 1'b0 ;
end else begin
if(cnt_base == 2'd3) begin
cnt_base <= 1'b0 ;
end else begin
cnt_base <= cnt_base + 1'b1 ;
end
end
end
// wr_req 读请求,在写时钟域下 cnt_base == 0 且没有读请求时拉高时,拉高一个wr_clk周期
always @(posedge wr_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
wr_req <= 1'b0 ;
end else begin
if(cnt_base == 2'd0 && rd_req == 1'b0) begin
wr_req <= 1'b1 ;
end else begin
wr_req <= 1'b0 ;
end
end
end
// wr_data 写数据 在写时钟域下,在写在写请求拉高时,wr_data == 255(因为深度是256) 归零。
// 没计满 则在写请求拉高时,加一
always @(posedge wr_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
wr_data <= 8'b0 ;
end else begin
if(wr_data == 8'd255 && wr_req == 1'b1) begin
wr_data <= 8'd0 ;
end else begin
if(wr_req == 1'b1) begin
wr_data <= wr_data + 1'b1 ;
end else begin
wr_data <= wr_data ;
end
end
end
end
// wr_full 跨时钟域同步处理 wr_full_reg1
always @(posedge rd_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
wr_full_reg0 <= 1'b0 ;
wr_full_reg1 <= 1'b0 ;
end else begin
wr_full_reg0 <= wr_full ;
wr_full_reg1 <= wr_full_reg0 ;
end
end
// rd_req 写满开读,读空拉低。(读请求)拉低后写请求拉高
always @(posedge rd_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
rd_req <= 1'b0 ;
end else begin
if(wr_full_reg1 == 1'b1) begin
rd_req <= 1'b1 ;
end else begin
if(rd_empty) begin
rd_req <= 1'b0 ;
end else begin
rd_req <= rd_req ;
end
end
end
end
example_fifo example_fifo_insert(
.wr_clk ( wr_clk ) ,
.wr_req ( wr_req ) ,
.wr_data ( wr_data ) ,
.rd_clk ( rd_clk ) ,
.rd_req ( rd_req ) ,
.rd_data ( rd_data ) ,
.wr_empty ( wr_empty ) ,
.wr_full ( wr_full ) , // 写满标志信号,在写时钟域下。
.wr_usedw ( wr_usedw ) , // 需要同步到读时钟域下 用来拉高读请求。
.rd_empty ( rd_empty ) , // 读空 用来拉低读请求
.rd_full ( rd_full ) ,
.rd_usedw ( rd_usedw )
);
endmodule
`timescale 1ns/1ns
module test_fifo();
reg sys_clk ; // 系统时钟
reg [7:0] pi_data ; // 写数据 输入
reg rd_req ; // 读请求
reg wr_req ; // 写请求
wire empty ; // 空标志 可以用来控制读请求
wire full ; // 满标志 可以用来控制读请求
wire [7:0] po_data ; // 读数据输出
wire [7:0] usedw ; // 数据余量
reg sys_rst_n ; // 系统复位(仿真文件用到)
reg [1:0] cnt_base ; // 0 ~ 3 计数器
// Instantiation
example_fifo example_fifo_insert (
.sys_clk ( sys_clk ) ,
.pi_data ( pi_data ) ,
.rd_req ( rd_req ) ,
.wr_req ( wr_req ) ,
.mepty ( empty ) ,
.full ( full ) ,
.po_data ( po_data ) ,
.usedw ( usedw )
);
parameter CYCLE = 20 ;
// cnt_base 4个时钟周期 用来产生读写使能
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
cnt_base <= 2'd0 ;
end else begin
if(cnt_base == 2'd3) begin
cnt_base <= 2'd0 ;
end else begin
cnt_base <= cnt_base + 1'b1 ;
end
end
end
// wr_req 写请求,再没有读请求时,cnt_base == 0 拉高一个sys_clk 时钟周期写请求
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
wr_req <= 1'b0 ;
end else begin
if(cnt_base == 2'd0 && rd_req == 1'b0 ) begin // 读请求拉低后,即开始写数据
wr_req <= 1'b1 ;
end else begin
wr_req <= 1'b0 ;
end
end
end
// pi_data 写入的数据 在读请求拉高的情况下,每过一个时钟周期数据加一.
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
pi_data <= 8'd0 ;
end else begin
if(pi_data == 8'd255 && wr_req == 1'b1) begin
pi_data <= 8'd0 ;
end else begin
if(wr_req == 1'b1) begin
pi_data <= pi_data + 1'b1 ;
end else begin
pi_data <= pi_data ;
end
end
end
end
// rd_req 写满开读,读空停止
always @(posedge sys_clk or negedge sys_rst_n) begin
if(~sys_rst_n) begin
rd_req <= 1'b0 ;
end else begin
if(full == 1'b1) begin
rd_req <= 1'b1 ;
end else begin
if(empty == 1'b1) begin
rd_req <= 1'b0 ;
end else begin
rd_req <= rd_req ;
end
end
end
end
initial begin // 初始化
sys_clk = 1'b1 ;
sys_rst_n <= 1'b0 ;
#( CYCLE * 100) ;
sys_rst_n <= 1'b1 ;
end
always #( CYCLE / 2 ) sys_clk = ~sys_clk ;
endmodule