RAM+空满信号判断,两种方法
一、空满标志用指针位置得到
二、空满标志用fifo的中数据的计数得到
一、当写指针超过读指针一圈,写满;写指针等于读指针,读空
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 11:42:44 12/29/2021
// Design Name:
// Module Name: fifo
// Project Name:
// Target Devices:
// Tool versions:
// Description: //1、空满标志用指针位置得到
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module fifo#(
parameter date_width=8,
parameter date_addr =4,
parameter date_depth=1<<date_addr
)
(
input clk,
input rst_n,
input [date_width-1:0] date_in,
input wr_en,
input rd_en,
output reg [date_width-1:0] date_out,
output empty,
output full
// output [date_addr-1:0]wr_adr,
// output [date_addr-1:0]rd_adr
);
//=============读写指针,多一位来控制空满========
reg [date_addr:0] wr_adr_ptr;
reg [date_addr:0] rd_adr_ptr;
//=============Fifo中的读写地址=============
wire [date_addr-1:0]wr_adr;
wire [date_addr-1:0]rd_adr;
assign wr_adr=wr_adr_ptr[date_addr-1:0];
assign rd_adr=rd_adr_ptr[date_addr-1:0];//!!!rd_adr
//============读写指针控制=========
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
wr_adr_ptr <= 'd0;
else if(wr_en && (~full))
wr_adr_ptr <= wr_adr_ptr + 1'b1;
else
wr_adr_ptr <= wr_adr_ptr;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
rd_adr_ptr <= 'd0;
else if(rd_en && (~empty))
rd_adr_ptr <= rd_adr_ptr + 1'b1;
else
rd_adr_ptr <= rd_adr_ptr;
end
//============双端口ram===========
//Write
integer i;
reg [date_width-1:0] ram [date_depth-1:0];
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
for(i=0;i<=date_depth-1;i=i+1)
ram[i]<=0;
else if(wr_en&&(!full))
ram[wr_adr]<=date_in;
else
ram[wr_adr]<=ram[wr_adr];
end
//Read
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
date_out<=0;
else if(rd_en&&(!empty))
date_out<=ram[rd_adr];
else
date_out<=date_out;
end
//=============空满信号判断,读写指针同则空,MSB不同,其他同则满===========
assign empty=(wr_adr_ptr==rd_adr_ptr)?1'b1:1'b0;
assign full =({(!wr_adr_ptr[date_addr]),wr_adr_ptr[date_addr-1:0]}==rd_adr_ptr)?1'b1:1'b0;
endmodule
testbench:写的同时读入
`timescale 1ns / 1ps
// Company:
// Engineer:
//
// Create Date: 16:25:00 12/29/2021
// Design Name: fifo
// Module Name: C:/Users/74172/Desktop/IC/FPGA/zsz_project/sync_fifo_prt/test.v
// Project Name: sync_fifo_prt
// Target Device:
// Tool versions:
// Description:
//
// Verilog Test Fixture created by ISE for module: fifo
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
module test;
// Inputs
reg clk;
reg rst_n;
reg [7:0] date_in;
reg wr_en;
reg rd_en;
// Outputs
wire [7:0] date_out;
wire empty;
wire full;
// Instantiate the Unit Under Test (UUT)
fifo uut (
.clk(clk),
.rst_n(rst_n),
.date_in(date_in),
.wr_en(wr_en),
.rd_en(rd_en),
.date_out(date_out),
.empty(empty),
.full(full)
);
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
date_in<=0;
else if(wr_en)
date_in <= date_in + 1'b1;
end
initial clk=0;
always #5 clk=~clk;
initial begin
// Initialize Inputs
rst_n = 0;
wr_en = 0;
rd_en = 0;
#100;
rst_n = 1;
wr_en = 1;
#100
rd_en = 1;
#50
wr_en=0;
rd_en=1;
#400;
rd_en=0;
$stop;
end
endmodule
二、根据读写状态,对fifo中的数据进行计数,等于date_depth时候,为full
修改
1、 修改计数器的宽度,需要cnt==16时候,判断空满。
2、 修改full的判断值,当cnt==16时候,立刻ful==1,所以正好0-15。
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 16:22:26 12/28/2021
// Design Name:
// Module Name: fifo_cnt
// Project Name:
// Target Devices:
// Tool versions:
// Description: //2、空满标志用fifo的中数据的计数得到
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module fifo_cnt#(
parameter date_width=8,
parameter date_addr =4, //深度16
parameter date_depth=1<<date_addr
)
(
input clk,
input rst_n,
input [date_width-1:0] date_in,
input wr_en,
input rd_en,
output reg [date_width-1:0] date_out,
output empty,
output full,
output reg [date_addr:0] fifo_counter,
output reg [date_addr-1:0] wr_addr,
output reg [date_addr-1:0] rd_addr
//output wr_err,
//output rd_err
);
//=============RAM中的读写地址=============
//reg [date_addr-1:0] wr_addr;
//reg [date_addr-1:0] rd_addr;
always@(posedge clk or negedge rst_n)begin//写成negedge clk能对吗!
if(!rst_n)
wr_addr<=0;
else if(wr_en&&(!full))
wr_addr<=wr_addr+1'b1;
else
wr_addr<=wr_addr;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
rd_addr<=0;
else if(rd_en&&(!empty))
rd_addr<=rd_addr+1'b1;
else
rd_addr<=rd_addr;
end
//=====================双端口RAM=====================
integer i;
reg [date_width-1:0] register [date_depth-1:0];
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
for(i=0;i<=date_depth-1;i=i+1)
register[i]<=0;
else if(wr_en&&!full)
register[wr_addr]<=date_in;
end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
date_out<=0;
else if(rd_en&&!empty)
date_out<=register[rd_addr];
end
//=====================FIFO中数据Counter==============
//reg [date_addr-1:0] fifo_counter;
// always@(posedge clk or negedge rst_n)begin
// if(!rst_n)
// fifo_counter<=0;
// else if((wr_en&&!full)&&!rd_en)
// fifo_counter<=fifo_counter+1'b1;
// else if((rd_en&&!empty)&&!wr_en)
// fifo_counter<=fifo_counter-1'b1;
// else
// fifo_counter<=fifo_counter;
// end
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
fifo_counter<=0;
else begin
case({wr_en,rd_en})
2'b00: fifo_counter<=fifo_counter;
2'b01: if(!empty)
fifo_counter<=fifo_counter-1'b1;
else
fifo_counter<=fifo_counter;
2'b10: if(!full)
fifo_counter<=fifo_counter+1'b1;
else
fifo_counter<=fifo_counter;
2'b11: fifo_counter<=fifo_counter;
endcase
end
end
//====================判断空满信号===============
assign full =(fifo_counter==date_depth)?1'b1:1'b0;
assign empty=(fifo_counter==0)?1'b1:1'b0;
endmodule
testbench
`timescale 1ns / 1ps
// Company:
// Engineer:
//
// Create Date: 16:31:19 12/28/2021
// Design Name: fifo_cnt
// Module Name: C:/Users/74172/Desktop/IC/FPGA/zsz_project/sync_fifo_cnt/zzz.v
// Project Name: sync_fifo_cnt
// Target Device:
// Tool versions:
// Description:
//
// Verilog Test Fixture created by ISE for module: fifo_cnt
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
module zzz;
// Inputs
reg clk;
reg rst_n;
reg [7:0] date_in;
reg wr_en;
reg rd_en;
// Outputs
wire [7:0] date_out;
wire empty;
wire full;
wire [3:0] fifo_counter;
wire [3:0] wr_addr;
wire [3:0] rd_addr;
// Instantiate the Unit Under Test (UUT)
fifo_cnt uut (
.clk(clk),
.rst_n(rst_n),
.date_in(date_in),
.wr_en(wr_en),
.rd_en(rd_en),
.date_out(date_out),
.empty(empty),
.full(full),
.fifo_counter(fifo_counter),
.wr_addr(wr_addr),
.rd_addr(rd_addr)
);
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
date_in<=0;
else if(wr_en)
date_in <= date_in + 1'b1;
end
initial clk=0;
always #5 clk=~clk;
initial begin
// Initialize Inputs
rst_n = 0;
wr_en = 0;
rd_en = 0;
#100;
rst_n = 1;
wr_en = 1;
#300
wr_en=0;
rd_en = 1;
#300
rd_en=0;
$stop;
end
endmodule