//////////////////////////////////////////////////////////////////////////////////
`timescale 1ns / 1ps
`define CLOG2(x) \
(x <= 2) ? 1 : \
(x <= 4) ? 2 : \
(x <= 8) ? 3 : \
(x <= 16) ? 4 : \
(x <= 32) ? 5 : \
(x <= 64) ? 6 : \
(x <= 128) ? 7 : \
(x <= 256) ? 8 : \
(x <= 512) ? 9 : \
(x <= 1024) ? 10 : \
-1
module SYNC_FIFO #(
parameter WIDTH = 64,
parameter DEPTH = 1024,
parameter AWIDTH = `CLOG2(DEPTH)
)(
input rst,
input clk,
input wr_en,
input rd_en,
input [WIDTH-1:0] fifo_din,
input [AWIDTH-1:0] strt_addr,
input [AWIDTH-1:0] end_addr,
output [WIDTH-1:0] fifo_dout,
output fifo_empty,
output fifo_full
);
reg [AWIDTH:0] rd_ptr, wr_ptr;
wire [WIDTH-1:0] ram_dout;
wire [AWIDTH-1:0] ram_addr;
initial begin
wr_ptr <= 0;
rd_ptr <= 0;
end
//*************** FIFO STATUS *****************************************
assign fifo_empty = (wr_ptr == rd_ptr);
assign fifo_full = ( (wr_ptr[AWIDTH] != rd_ptr[AWIDTH]) &&
(wr_ptr[AWIDTH-1:0] == rd_ptr[AWIDTH-1:0]) );
//*************** FIFO POINTERS ***************************************
always@(posedge clk or posedge rst) begin
if(rst) begin
wr_ptr <= {1'b0,strt_addr};
rd_ptr <= {1'b0,strt_addr};
end
else begin
if(!fifo_full && wr_en) begin
wr_ptr <= wr_ptr + 1;
if(wr_ptr[AWIDTH-1:0] == end_addr)
wr_ptr <= {1'b1,strt_addr};
end
if(!fifo_empty && rd_en) begin
rd_ptr <= rd_ptr + 1;
if(rd_ptr[AWIDTH-1:0] == end_addr)
rd_ptr <= {1'b1,strt_addr};
end
end
end
//*************** RAM INTERFACE***************************************
assign fifo_dout = rst ? 0 : ((!fifo_empty && rd_en) ? ram_dout : fifo_dout);
assign ram_addr = wr_en ? wr_ptr : (rd_en ? rd_ptr : 0);
simple_ram1 BRAM_64Kb (
.clka (clk),
.wea (wr_en),
.addra (ram_addr),
.dina (fifo_din),
.douta (ram_dout)
);
endmodule
//*********************************************************************
module simple_ram1#(
parameter WIDTH = 64,
parameter DEPTH = 1024,
parameter AWIDTH = `CLOG2(DEPTH)
)(
input clka ,
input wea ,
input [AWIDTH-1:0] addra,
input [WIDTH-1:0] dina,
output reg [WIDTH-1:0] douta
);
reg [WIDTH-1:0] mem [DEPTH-1:0];
initial
douta <= 0;
always@(posedge clka) begin
if(wea)
mem[addra] <= dina;
else
douta <= mem[addra];
end
endmodule
//*************** TEST BENCH ***************************************
module tb_ram_to_fifo;
// Inputs
reg rst;
reg clk;
reg wr_en;
reg rd_en;
reg [63:0] fifo_din;
reg [9:0] strt_addr;
reg [9:0] end_addr;
// Outputs
wire [63:0] fifo_dout;
wire fifo_empty;
wire fifo_full;
parameter DEPTH = 1024;
// Instantiate the Unit Under Test (UUT)
RAM_TO_FIFO uut (
.rst(rst),
.clk(clk),
.wr_en(wr_en),
.rd_en(rd_en),
.fifo_din(fifo_din),
.strt_addr(strt_addr),
.end_addr(end_addr),
.fifo_dout(fifo_dout),
.fifo_empty(fifo_empty),
.fifo_full(fifo_full)
);
initial begin
// Initialize Inputs
rst = 0;
clk = 0;
wr_en = 0;
rd_en = 0;
fifo_din = 0;
strt_addr = 0;
end_addr = 0; #27
// rst = 1;#20
rst = 0;#22
strt_addr = 0;
end_addr = 1023; #28
rwd_fifo();
#150;
end
task rwd_fifo;
reg [64:0]j,temp,x=5;
begin
for(j=0; j <2500; j=j+1) begin
#1
temp = j%32;
x = x +2;
if(temp < 15) begin
wr_en = 1;
fifo_din = x;
rd_en = 0;
end
else if((temp > 15)&&(temp < 20)) begin
wr_en = 0;
rd_en = 0;
fifo_din = 0;
end
else if((temp >= 20) &&(temp <= 32))begin
rd_en = 1;
wr_en = 0;
fifo_din =0;
end
else begin
wr_en = 0;
rd_en = 0;
fifo_din = 0;
end
@ (posedge clk);
end
wr_en = 0;rd_en = 0;
end
endtask
always
#`clkperiodby2 clk <= ~clk;
endmodule
// Module No.: 001
// Module Name: SYNC_FIFO
// Engineer: Jayant Sharma
// Create Date: 06:13:06 07/19/2014
// Description: This module converts a single port ram into a synchronous FIFO.
// Tool Version: XilinxISE 14.7
//////////////////////////////////////////////////////////////////////////////////`timescale 1ns / 1ps
`define CLOG2(x) \
(x <= 2) ? 1 : \
(x <= 4) ? 2 : \
(x <= 8) ? 3 : \
(x <= 16) ? 4 : \
(x <= 32) ? 5 : \
(x <= 64) ? 6 : \
(x <= 128) ? 7 : \
(x <= 256) ? 8 : \
(x <= 512) ? 9 : \
(x <= 1024) ? 10 : \
-1
module SYNC_FIFO #(
parameter WIDTH = 64,
parameter DEPTH = 1024,
parameter AWIDTH = `CLOG2(DEPTH)
)(
input rst,
input clk,
input wr_en,
input rd_en,
input [WIDTH-1:0] fifo_din,
input [AWIDTH-1:0] strt_addr,
input [AWIDTH-1:0] end_addr,
output [WIDTH-1:0] fifo_dout,
output fifo_empty,
output fifo_full
);
reg [AWIDTH:0] rd_ptr, wr_ptr;
wire [WIDTH-1:0] ram_dout;
wire [AWIDTH-1:0] ram_addr;
initial begin
wr_ptr <= 0;
rd_ptr <= 0;
end
//*************** FIFO STATUS *****************************************
assign fifo_empty = (wr_ptr == rd_ptr);
assign fifo_full = ( (wr_ptr[AWIDTH] != rd_ptr[AWIDTH]) &&
(wr_ptr[AWIDTH-1:0] == rd_ptr[AWIDTH-1:0]) );
//*************** FIFO POINTERS ***************************************
always@(posedge clk or posedge rst) begin
if(rst) begin
wr_ptr <= {1'b0,strt_addr};
rd_ptr <= {1'b0,strt_addr};
end
else begin
if(!fifo_full && wr_en) begin
wr_ptr <= wr_ptr + 1;
if(wr_ptr[AWIDTH-1:0] == end_addr)
wr_ptr <= {1'b1,strt_addr};
end
if(!fifo_empty && rd_en) begin
rd_ptr <= rd_ptr + 1;
if(rd_ptr[AWIDTH-1:0] == end_addr)
rd_ptr <= {1'b1,strt_addr};
end
end
end
//*************** RAM INTERFACE***************************************
assign fifo_dout = rst ? 0 : ((!fifo_empty && rd_en) ? ram_dout : fifo_dout);
assign ram_addr = wr_en ? wr_ptr : (rd_en ? rd_ptr : 0);
simple_ram1 BRAM_64Kb (
.clka (clk),
.wea (wr_en),
.addra (ram_addr),
.dina (fifo_din),
.douta (ram_dout)
);
endmodule
//*********************************************************************
module simple_ram1#(
parameter WIDTH = 64,
parameter DEPTH = 1024,
parameter AWIDTH = `CLOG2(DEPTH)
)(
input clka ,
input wea ,
input [AWIDTH-1:0] addra,
input [WIDTH-1:0] dina,
output reg [WIDTH-1:0] douta
);
reg [WIDTH-1:0] mem [DEPTH-1:0];
initial
douta <= 0;
always@(posedge clka) begin
if(wea)
mem[addra] <= dina;
else
douta <= mem[addra];
end
endmodule
//*************** TEST BENCH ***************************************
module tb_ram_to_fifo;
// Inputs
reg rst;
reg clk;
reg wr_en;
reg rd_en;
reg [63:0] fifo_din;
reg [9:0] strt_addr;
reg [9:0] end_addr;
// Outputs
wire [63:0] fifo_dout;
wire fifo_empty;
wire fifo_full;
parameter DEPTH = 1024;
// Instantiate the Unit Under Test (UUT)
RAM_TO_FIFO uut (
.rst(rst),
.clk(clk),
.wr_en(wr_en),
.rd_en(rd_en),
.fifo_din(fifo_din),
.strt_addr(strt_addr),
.end_addr(end_addr),
.fifo_dout(fifo_dout),
.fifo_empty(fifo_empty),
.fifo_full(fifo_full)
);
initial begin
// Initialize Inputs
rst = 0;
clk = 0;
wr_en = 0;
rd_en = 0;
fifo_din = 0;
strt_addr = 0;
end_addr = 0; #27
// rst = 1;#20
rst = 0;#22
strt_addr = 0;
end_addr = 1023; #28
rwd_fifo();
#150;
end
task rwd_fifo;
reg [64:0]j,temp,x=5;
begin
for(j=0; j <2500; j=j+1) begin
#1
temp = j%32;
x = x +2;
if(temp < 15) begin
wr_en = 1;
fifo_din = x;
rd_en = 0;
end
else if((temp > 15)&&(temp < 20)) begin
wr_en = 0;
rd_en = 0;
fifo_din = 0;
end
else if((temp >= 20) &&(temp <= 32))begin
rd_en = 1;
wr_en = 0;
fifo_din =0;
end
else begin
wr_en = 0;
rd_en = 0;
fifo_din = 0;
end
@ (posedge clk);
end
wr_en = 0;rd_en = 0;
end
endtask
always
#`clkperiodby2 clk <= ~clk;
endmodule
can you describe this code with comments ?. That will help in understanding quickly. Thanks.
ReplyDelete