204 lines
3.9 KiB
Verilog
204 lines
3.9 KiB
Verilog
|
|
////////////////////////////////////////////////
|
|
//Engineer: Xiaodong Zhong
|
|
//Date: 2019.5.21
|
|
//Description: ?????ram
|
|
////////////////////////////////////////////////
|
|
module syn_fwft_fifo #(
|
|
parameter width =16,
|
|
parameter depth =1024,
|
|
parameter prog_full_thre =512,
|
|
parameter prog_empty_thre =16
|
|
)(
|
|
input clk,
|
|
input rst,
|
|
input clr,
|
|
|
|
input wr_en,
|
|
input [width-1:0] din,
|
|
output full,
|
|
output almost_full,
|
|
output prog_full,
|
|
|
|
|
|
input rd_en,
|
|
output [width-1:0] dout,
|
|
output empty,
|
|
output almost_empty,
|
|
output prog_empty,
|
|
|
|
output [clog2(depth-1)-1:0] cnt
|
|
);
|
|
////////////////////////////////////////////////
|
|
//log2 function
|
|
////////////////////////////////////////////////
|
|
function integer clog2(input integer depth);
|
|
begin
|
|
for(clog2=0;depth>0;clog2=clog2+1)
|
|
depth =depth>>1;
|
|
end
|
|
endfunction
|
|
|
|
localparam aw = clog2(depth-1);
|
|
|
|
////////////////////////////////////////////////
|
|
//reg & wire
|
|
////////////////////////////////////////////////
|
|
reg [aw-1:0] wr_p;
|
|
reg [aw-1:0] rd_p;
|
|
wire [aw-1:0] rd_p_next;
|
|
|
|
reg [aw:0] i;
|
|
reg wr_en_dly;
|
|
|
|
wire [width-1:0] ram_dout;
|
|
wire ram_rden;
|
|
////////////////////////////////////////////////
|
|
//combinational logic
|
|
////////////////////////////////////////////////
|
|
//assign cnt = (wr_p >= rd_p) ? wr_p - rd_p : depth-rd_p+wr_p;
|
|
|
|
|
|
assign full = (i>=(depth-1)) ? 1'b1 : 1'b0;
|
|
assign almost_full = (i >=(depth-4)) ? 1'b1 : 1'b0;
|
|
assign prog_full = (i >= (prog_full_thre-1)) ? 1'b1 :1'b0;
|
|
|
|
assign empty = (i==1'b0) ? 1'b1 : 1'b0;
|
|
assign almost_empty = (i<=1'b1) ? 1'b1 : 1'b0;
|
|
assign prog_empty = (i<=prog_empty_thre) ? 1'b1 :1'b0;
|
|
|
|
assign cnt = i[clog2(depth-1)-1:0];
|
|
|
|
assign rd_p_next = rd_p + {{(aw-2){1'b0}}, (rd_en & !empty)};
|
|
////////////////////////////////////////////////
|
|
//timing
|
|
////////////////////////////////////////////////
|
|
reg wr_clr_r;
|
|
reg wr_clr;
|
|
//----------------------------------------------
|
|
always @(posedge clk or posedge clr)
|
|
if(clr)
|
|
wr_clr <= 1'b1;
|
|
else if(!wr_clr_r)
|
|
wr_clr <= 1'b0;// Release Clear
|
|
|
|
always @(posedge clk or posedge clr)
|
|
if(clr)
|
|
wr_clr_r <= 1'b1;
|
|
else
|
|
wr_clr_r <= 1'b0;
|
|
//----------------------------------------------
|
|
always@(posedge clk or posedge rst)begin
|
|
if(rst )begin
|
|
wr_en_dly <=1'b0;
|
|
end
|
|
else begin
|
|
wr_en_dly <=wr_en;
|
|
end
|
|
end
|
|
|
|
always@(posedge clk or posedge rst)begin
|
|
if(rst )begin
|
|
wr_p <=0;
|
|
end
|
|
else if(wr_clr)begin
|
|
wr_p <=0;
|
|
end
|
|
else if(wr_en)begin
|
|
if(wr_p == depth-1)begin
|
|
wr_p <=0;
|
|
end
|
|
else begin
|
|
wr_p <=wr_p+1;
|
|
end
|
|
end
|
|
else begin
|
|
wr_p <=wr_p;
|
|
end
|
|
end
|
|
|
|
//----------------------------------------------
|
|
always@(posedge clk or posedge rst)begin
|
|
if(rst )begin
|
|
rd_p <=0;
|
|
end
|
|
else if(wr_clr)begin
|
|
rd_p <=0;
|
|
end
|
|
else if(rd_en)begin
|
|
if(rd_p == depth-1)begin
|
|
rd_p <=0;
|
|
end
|
|
else begin
|
|
rd_p <=rd_p+1;
|
|
end
|
|
end
|
|
else begin
|
|
rd_p <=rd_p;
|
|
end
|
|
end
|
|
|
|
//----------------------------------------------
|
|
always@(posedge clk or posedge rst)begin
|
|
if(rst)begin
|
|
i <=0;
|
|
end
|
|
else if(wr_clr)begin
|
|
i <=0;
|
|
end
|
|
else begin
|
|
case({wr_en_dly,rd_en})
|
|
2'b00:begin
|
|
i <=i;
|
|
end
|
|
2'b01:begin
|
|
if(i!=0)begin
|
|
i <=i-1'b1;
|
|
end
|
|
else begin
|
|
i <=i;
|
|
end
|
|
end
|
|
2'b10:begin
|
|
if(i!=depth)begin
|
|
i <=i+1'b1;
|
|
end
|
|
else begin
|
|
i <=i;
|
|
end
|
|
end
|
|
2'b11:begin
|
|
i <=i;
|
|
end
|
|
default:begin
|
|
i <=i;
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
////////////////////////////////////////////////
|
|
//SRAM
|
|
////////////////////////////////////////////////
|
|
spram #(
|
|
.width (width ),
|
|
.depth (depth )
|
|
)spram(
|
|
.clka (clk ),
|
|
.ena (wr_en ),
|
|
.dina (din ),
|
|
.addra (wr_p ),
|
|
|
|
.clkb (clk ),
|
|
//.enb (1'b1 ),
|
|
.enb (ram_rden ),
|
|
.doutb (ram_dout ),
|
|
.addrb (rd_p_next )
|
|
);
|
|
|
|
assign ram_rden = wr_p != rd_p_next;
|
|
assign dout = empty ? 0 : ram_dout;
|
|
|
|
endmodule
|
|
|
|
|