//+FHDR------------------------------------------------------------------------
|
//+FHDR------------------------------------------------------------------------
|
//Copyright (c) 2013 Latin Group American Integhrated Circuit, Inc. All rights reserved
|
//Copyright (c) 2013 Latin Group American Integhrated Circuit, Inc. All rights reserved
|
//GLADIC Open Source RTL
|
//GLADIC Open Source RTL
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//FILE NAME :
|
//FILE NAME :
|
//DEPARTMENT : IC Design / Verification
|
//DEPARTMENT : IC Design / Verification
|
//AUTHOR : Felipe Fernandes da Costa
|
//AUTHOR : Felipe Fernandes da Costa
|
//AUTHOR’S EMAIL :
|
//AUTHOR’S EMAIL :
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//RELEASE HISTORY
|
//RELEASE HISTORY
|
//VERSION DATE AUTHOR DESCRIPTION
|
//VERSION DATE AUTHOR DESCRIPTION
|
//1.0 YYYY-MM-DD name
|
//1.0 YYYY-MM-DD name
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//KEYWORDS : General file searching keywords, leave blank if none.
|
//KEYWORDS : General file searching keywords, leave blank if none.
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//PURPOSE : ECSS_E_ST_50_12C_31_july_2008
|
//PURPOSE : ECSS_E_ST_50_12C_31_july_2008
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//PARAMETERS
|
//PARAMETERS
|
//PARAM NAME RANGE : DESCRIPTION : DEFAULT : UNITS
|
//PARAM NAME RANGE : DESCRIPTION : DEFAULT : UNITS
|
//e.g.DATA_WIDTH [32,16] : width of the data : 32:
|
//e.g.DATA_WIDTH [32,16] : width of the data : 32:
|
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
//REUSE ISSUES
|
//REUSE ISSUES
|
//Reset Strategy :
|
//Reset Strategy :
|
//Clock Domains :
|
//Clock Domains :
|
//Critical Timing :
|
//Critical Timing :
|
//Test Features :
|
//Test Features :
|
//Asynchronous I/F :
|
//Asynchronous I/F :
|
//Scan Methodology :
|
//Scan Methodology :
|
//Instantiations :
|
//Instantiations :
|
//Synthesizable (y/n) :
|
//Synthesizable (y/n) :
|
//Other :
|
//Other :
|
//-FHDR------------------------------------------------------------------------
|
//-FHDR------------------------------------------------------------------------
|
module fifo_rx
|
module fifo_rx
|
#(
|
#(
|
parameter integer DWIDTH = 9,
|
parameter integer DWIDTH = 9,
|
parameter integer AWIDTH = 6
|
parameter integer AWIDTH = 6
|
)
|
)
|
|
|
(
|
(
|
input clock, reset, wr_en, rd_en,
|
input clock, reset, wr_en, rd_en,
|
input [DWIDTH-1:0] data_in,
|
input [DWIDTH-1:0] data_in,
|
output reg f_full,f_empty,
|
output reg f_full,f_empty,
|
output reg open_slot_fct,
|
output reg open_slot_fct,
|
output reg overflow_credit_error,
|
output reg overflow_credit_error,
|
output reg [DWIDTH-1:0] data_out,
|
output reg [DWIDTH-1:0] data_out,
|
output reg [AWIDTH-1:0] counter
|
output reg [AWIDTH-1:0] counter
|
);
|
);
|
|
|
reg [DWIDTH-1:0] mem [0:2**AWIDTH-1];
|
reg [DWIDTH-1:0] mem [0:2**AWIDTH-1];
|
|
|
reg [AWIDTH-1:0] wr_ptr;
|
reg [AWIDTH-1:0] wr_ptr;
|
reg [AWIDTH-1:0] rd_ptr;
|
reg [AWIDTH-1:0] rd_ptr;
|
|
|
reg block_read;
|
|
reg block_write;
|
|
|
|
reg [AWIDTH-1:0] credit_counter;
|
reg [AWIDTH-1:0] credit_counter;
|
|
|
|
reg [1:0] state_data_write;
|
|
reg [1:0] next_state_data_write;
|
|
|
|
reg [1:0] state_data_read;
|
|
reg [1:0] next_state_data_read;
|
|
|
|
|
|
/****************************************/
|
|
|
|
always@(*)
|
|
begin
|
|
next_state_data_write = state_data_write;
|
|
|
|
case(state_data_write)
|
|
2'd0:
|
|
begin
|
|
if(wr_en && !f_full)
|
|
begin
|
|
next_state_data_write = 2'd1;
|
|
end
|
|
else
|
|
begin
|
|
next_state_data_write = 2'd0;
|
|
end
|
|
end
|
|
2'd1:
|
|
begin
|
|
if(wr_en)
|
|
begin
|
|
next_state_data_write = 2'd1;
|
|
end
|
|
else
|
|
begin
|
|
next_state_data_write = 2'd2;
|
|
end
|
|
end
|
|
2'd2:
|
|
begin
|
|
next_state_data_write = 2'd0;
|
|
end
|
|
default:
|
|
begin
|
|
next_state_data_write = 2'd0;
|
|
end
|
|
endcase
|
|
end
|
|
|
|
/****************************************/
|
|
|
|
always@(*)
|
|
begin
|
|
next_state_data_read = state_data_read;
|
|
|
|
case(state_data_read)
|
|
2'd0:
|
|
begin
|
|
if(rd_en && !f_empty)
|
|
begin
|
|
next_state_data_read = 2'd1;
|
|
end
|
|
else
|
|
begin
|
|
next_state_data_read = 2'd0;
|
|
end
|
|
end
|
|
2'd1:
|
|
begin
|
|
if(rd_en)
|
|
begin
|
|
next_state_data_read = 2'd1;
|
|
end
|
|
else
|
|
begin
|
|
next_state_data_read = 2'd2;
|
|
end
|
|
end
|
|
2'd2:
|
|
begin
|
|
next_state_data_read = 2'd0;
|
|
end
|
|
default:
|
|
begin
|
|
next_state_data_read = 2'd0;
|
|
end
|
|
endcase
|
|
end
|
|
|
|
|
//Write pointer
|
//Write pointer
|
always@(posedge clock or negedge reset)
|
always@(posedge clock or negedge reset)
|
begin
|
begin
|
if (!reset)
|
if (!reset)
|
begin
|
begin
|
wr_ptr <= {(AWIDTH){1'b0}};
|
wr_ptr <= {(AWIDTH){1'b0}};
|
mem[0] <= {(DWIDTH){1'b0}};
|
mem[0] <= {(DWIDTH){1'b0}};
|
mem[1] <= {(DWIDTH){1'b0}};
|
mem[1] <= {(DWIDTH){1'b0}};
|
mem[2] <= {(DWIDTH){1'b0}};
|
mem[2] <= {(DWIDTH){1'b0}};
|
mem[3] <= {(DWIDTH){1'b0}};
|
mem[3] <= {(DWIDTH){1'b0}};
|
mem[4] <= {(DWIDTH){1'b0}};
|
mem[4] <= {(DWIDTH){1'b0}};
|
mem[5] <= {(DWIDTH){1'b0}};
|
mem[5] <= {(DWIDTH){1'b0}};
|
mem[6] <= {(DWIDTH){1'b0}};
|
mem[6] <= {(DWIDTH){1'b0}};
|
mem[7] <= {(DWIDTH){1'b0}};
|
mem[7] <= {(DWIDTH){1'b0}};
|
mem[8] <= {(DWIDTH){1'b0}};
|
mem[8] <= {(DWIDTH){1'b0}};
|
mem[9] <= {(DWIDTH){1'b0}};
|
mem[9] <= {(DWIDTH){1'b0}};
|
mem[10] <= {(DWIDTH){1'b0}};
|
mem[10] <= {(DWIDTH){1'b0}};
|
|
|
mem[11] <= {(DWIDTH){1'b0}};
|
mem[11] <= {(DWIDTH){1'b0}};
|
mem[12] <= {(DWIDTH){1'b0}};
|
mem[12] <= {(DWIDTH){1'b0}};
|
mem[13] <= {(DWIDTH){1'b0}};
|
mem[13] <= {(DWIDTH){1'b0}};
|
mem[14] <= {(DWIDTH){1'b0}};
|
mem[14] <= {(DWIDTH){1'b0}};
|
mem[15] <= {(DWIDTH){1'b0}};
|
mem[15] <= {(DWIDTH){1'b0}};
|
mem[16] <= {(DWIDTH){1'b0}};
|
mem[16] <= {(DWIDTH){1'b0}};
|
mem[17] <= {(DWIDTH){1'b0}};
|
mem[17] <= {(DWIDTH){1'b0}};
|
mem[18] <= {(DWIDTH){1'b0}};
|
mem[18] <= {(DWIDTH){1'b0}};
|
mem[19] <= {(DWIDTH){1'b0}};
|
mem[19] <= {(DWIDTH){1'b0}};
|
mem[20] <= {(DWIDTH){1'b0}};
|
mem[20] <= {(DWIDTH){1'b0}};
|
mem[21] <= {(DWIDTH){1'b0}};
|
mem[21] <= {(DWIDTH){1'b0}};
|
|
|
mem[22] <= {(DWIDTH){1'b0}};
|
mem[22] <= {(DWIDTH){1'b0}};
|
mem[23] <= {(DWIDTH){1'b0}};
|
mem[23] <= {(DWIDTH){1'b0}};
|
mem[24] <= {(DWIDTH){1'b0}};
|
mem[24] <= {(DWIDTH){1'b0}};
|
mem[25] <= {(DWIDTH){1'b0}};
|
mem[25] <= {(DWIDTH){1'b0}};
|
mem[26] <= {(DWIDTH){1'b0}};
|
mem[26] <= {(DWIDTH){1'b0}};
|
mem[27] <= {(DWIDTH){1'b0}};
|
mem[27] <= {(DWIDTH){1'b0}};
|
mem[28] <= {(DWIDTH){1'b0}};
|
mem[28] <= {(DWIDTH){1'b0}};
|
mem[29] <= {(DWIDTH){1'b0}};
|
mem[29] <= {(DWIDTH){1'b0}};
|
mem[30] <= {(DWIDTH){1'b0}};
|
mem[30] <= {(DWIDTH){1'b0}};
|
mem[31] <= {(DWIDTH){1'b0}};
|
mem[31] <= {(DWIDTH){1'b0}};
|
mem[32] <= {(DWIDTH){1'b0}};
|
mem[32] <= {(DWIDTH){1'b0}};
|
|
|
|
|
mem[33] <= {(DWIDTH){1'b0}};
|
mem[33] <= {(DWIDTH){1'b0}};
|
mem[34] <= {(DWIDTH){1'b0}};
|
mem[34] <= {(DWIDTH){1'b0}};
|
mem[35] <= {(DWIDTH){1'b0}};
|
mem[35] <= {(DWIDTH){1'b0}};
|
mem[36] <= {(DWIDTH){1'b0}};
|
mem[36] <= {(DWIDTH){1'b0}};
|
mem[37] <= {(DWIDTH){1'b0}};
|
mem[37] <= {(DWIDTH){1'b0}};
|
mem[38] <= {(DWIDTH){1'b0}};
|
mem[38] <= {(DWIDTH){1'b0}};
|
mem[39] <= {(DWIDTH){1'b0}};
|
mem[39] <= {(DWIDTH){1'b0}};
|
mem[40] <= {(DWIDTH){1'b0}};
|
mem[40] <= {(DWIDTH){1'b0}};
|
mem[41] <= {(DWIDTH){1'b0}};
|
mem[41] <= {(DWIDTH){1'b0}};
|
mem[42] <= {(DWIDTH){1'b0}};
|
mem[42] <= {(DWIDTH){1'b0}};
|
mem[43] <= {(DWIDTH){1'b0}};
|
mem[43] <= {(DWIDTH){1'b0}};
|
|
|
mem[44] <= {(DWIDTH){1'b0}};
|
mem[44] <= {(DWIDTH){1'b0}};
|
mem[45] <= {(DWIDTH){1'b0}};
|
mem[45] <= {(DWIDTH){1'b0}};
|
mem[46] <= {(DWIDTH){1'b0}};
|
mem[46] <= {(DWIDTH){1'b0}};
|
mem[47] <= {(DWIDTH){1'b0}};
|
mem[47] <= {(DWIDTH){1'b0}};
|
mem[48] <= {(DWIDTH){1'b0}};
|
mem[48] <= {(DWIDTH){1'b0}};
|
mem[49] <= {(DWIDTH){1'b0}};
|
mem[49] <= {(DWIDTH){1'b0}};
|
mem[50] <= {(DWIDTH){1'b0}};
|
mem[50] <= {(DWIDTH){1'b0}};
|
mem[51] <= {(DWIDTH){1'b0}};
|
mem[51] <= {(DWIDTH){1'b0}};
|
mem[52] <= {(DWIDTH){1'b0}};
|
mem[52] <= {(DWIDTH){1'b0}};
|
mem[53] <= {(DWIDTH){1'b0}};
|
mem[53] <= {(DWIDTH){1'b0}};
|
mem[54] <= {(DWIDTH){1'b0}};
|
mem[54] <= {(DWIDTH){1'b0}};
|
|
|
mem[55] <= {(DWIDTH){1'b0}};
|
mem[55] <= {(DWIDTH){1'b0}};
|
mem[56] <= {(DWIDTH){1'b0}};
|
mem[56] <= {(DWIDTH){1'b0}};
|
mem[57] <= {(DWIDTH){1'b0}};
|
mem[57] <= {(DWIDTH){1'b0}};
|
mem[58] <= {(DWIDTH){1'b0}};
|
mem[58] <= {(DWIDTH){1'b0}};
|
mem[59] <= {(DWIDTH){1'b0}};
|
mem[59] <= {(DWIDTH){1'b0}};
|
mem[60] <= {(DWIDTH){1'b0}};
|
mem[60] <= {(DWIDTH){1'b0}};
|
mem[61] <= {(DWIDTH){1'b0}};
|
mem[61] <= {(DWIDTH){1'b0}};
|
mem[62] <= {(DWIDTH){1'b0}};
|
mem[62] <= {(DWIDTH){1'b0}};
|
mem[63] <= {(DWIDTH){1'b0}};
|
mem[63] <= {(DWIDTH){1'b0}};
|
block_write <= 1'b0;
|
|
overflow_credit_error<=1'b0;
|
overflow_credit_error<=1'b0;
|
|
state_data_write <= 2'd0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
if(block_write)
|
|
|
state_data_write <= next_state_data_write;
|
|
|
|
case(state_data_write)
|
|
2'd0:
|
|
begin
|
|
mem[wr_ptr]<=data_in;
|
|
end
|
|
2'd1:
|
begin
|
begin
|
if(!wr_en)
|
mem[wr_ptr]<=mem[wr_ptr];
|
|
end
|
|
2'd2:
|
begin
|
begin
|
block_write <= 1'b0;
|
|
wr_ptr <= wr_ptr + 6'd1;
|
wr_ptr <= wr_ptr + 6'd1;
|
end
|
end
|
end
|
default:
|
else if (wr_en && !f_full)
|
|
begin
|
begin
|
block_write <= 1'b1;
|
mem[wr_ptr]<=mem[wr_ptr];
|
mem[wr_ptr]<=data_in;
|
wr_ptr <= wr_ptr;
|
end
|
end
|
|
endcase
|
|
|
if(wr_en && credit_counter > 6'd55)
|
if(wr_en && credit_counter > 6'd55)
|
begin
|
begin
|
|
|
overflow_credit_error<=1'b1;
|
overflow_credit_error<=1'b1;
|
end
|
end
|
|
else
|
|
overflow_credit_error <= overflow_credit_error;
|
end
|
end
|
end
|
end
|
|
|
//FULL - EMPTY COUNTER
|
//FULL - EMPTY COUNTER
|
|
|
always@(posedge clock or negedge reset)
|
always@(posedge clock or negedge reset)
|
begin
|
begin
|
if (!reset)
|
if (!reset)
|
begin
|
begin
|
f_full <= 1'b0;
|
f_full <= 1'b0;
|
f_empty <= 1'b1;
|
f_empty <= 1'b1;
|
counter <= {(AWIDTH){1'b0}};
|
counter <= {(AWIDTH){1'b0}};
|
credit_counter <= 6'd55;
|
credit_counter <= 6'd55;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
|
|
if((wr_en && !f_full && !block_write) && (rd_en && !f_empty && !block_read))
|
if (state_data_write == 2'd2)
|
begin
|
|
if(rd_ptr == 6'd7 || rd_ptr == 6'd15 || rd_ptr == 6'd23 || rd_ptr == 6'd31 || rd_ptr == 6'd39 || rd_ptr == 6'd47 || rd_ptr == 6'd55 || rd_ptr == 6'd63)
|
|
credit_counter <= credit_counter - 6'd1 + 6'd8;
|
|
else
|
|
credit_counter <= credit_counter - 6'd1;
|
|
end
|
|
else if (wr_en && !f_full && !block_write)
|
|
begin
|
begin
|
credit_counter <= credit_counter - 6'd1;
|
credit_counter <= credit_counter - 6'd1;
|
end
|
end
|
else if(rd_en && !f_empty && !block_read)
|
else if(state_data_read == 2'd2)
|
begin
|
begin
|
if(rd_ptr == 6'd7 || rd_ptr == 6'd15 || rd_ptr == 6'd23 || rd_ptr == 6'd31 || rd_ptr == 6'd39 || rd_ptr == 6'd47 || rd_ptr == 6'd55 || rd_ptr == 6'd63)
|
if(rd_ptr == 6'd7 || rd_ptr == 6'd15 || rd_ptr == 6'd23 || rd_ptr == 6'd31 || rd_ptr == 6'd39 || rd_ptr == 6'd47 || rd_ptr == 6'd55 || rd_ptr == 6'd63)
|
begin
|
begin
|
|
if(credit_counter < 6'd48)
|
credit_counter <= credit_counter + 6'd8;
|
credit_counter <= credit_counter + 6'd8;
|
|
else
|
|
credit_counter <= credit_counter + 6'd7;
|
end
|
end
|
end
|
end
|
else
|
else
|
credit_counter <= credit_counter;
|
credit_counter <= credit_counter;
|
|
|
if((wr_en && !f_full && !block_write) && (rd_en && !f_empty && !block_read))
|
if (state_data_write == 2'd2)
|
begin
|
begin
|
|
if(counter == 6'd63)
|
counter <= counter;
|
counter <= counter;
|
end
|
else
|
else if (wr_en && !f_full && !block_write)
|
|
begin
|
|
counter <= counter + 6'd1;
|
counter <= counter + 6'd1;
|
end
|
end
|
else if(rd_en && !f_empty && !block_read)
|
else if(state_data_read == 2'd2)
|
begin
|
begin
|
|
if(counter == 6'd0)
|
|
counter <= counter;
|
|
else
|
counter <= counter - 6'd1;
|
counter <= counter - 6'd1;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
counter <= counter;
|
counter <= counter;
|
end
|
end
|
|
|
if(counter == 6'd63)
|
if(counter == 6'd63)
|
begin
|
begin
|
f_full <= 1'b1;
|
f_full <= 1'b1;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
f_full <= 1'b0;
|
f_full <= 1'b0;
|
end
|
end
|
|
|
if(counter == 6'd0)
|
if(counter == 6'd0)
|
begin
|
begin
|
f_empty <= 1'b1;
|
f_empty <= 1'b1;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
f_empty <= 1'b0;
|
f_empty <= 1'b0;
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
//Read pointer
|
//Read pointer
|
always@(posedge clock or negedge reset)
|
always@(posedge clock or negedge reset)
|
begin
|
begin
|
if (!reset)
|
if (!reset)
|
begin
|
begin
|
rd_ptr <= {(AWIDTH){1'b0}};
|
rd_ptr <= {(AWIDTH){1'b0}};
|
data_out <= 9'd0;
|
data_out <= 9'd0;
|
open_slot_fct<= 1'b0;
|
open_slot_fct<= 1'b0;
|
block_read <= 1'b0;
|
state_data_read <= 2'd0;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
|
|
|
state_data_read <= next_state_data_read;
|
|
|
|
case(state_data_read)
|
|
2'd0:
|
|
begin
|
|
if(rd_en)
|
|
begin
|
|
data_out <= data_out;
|
|
open_slot_fct<= open_slot_fct;
|
|
rd_ptr <= rd_ptr+ 6'd1;
|
|
end
|
|
else
|
|
begin
|
|
open_slot_fct<= open_slot_fct;
|
|
data_out <= mem[rd_ptr];
|
|
end
|
|
end
|
|
2'd1:
|
|
begin
|
if(rd_ptr == 6'd7 || rd_ptr == 6'd15 || rd_ptr == 6'd23 || rd_ptr == 6'd31 || rd_ptr == 6'd39 || rd_ptr == 6'd47 || rd_ptr == 6'd55 || rd_ptr == 6'd63)
|
if(rd_ptr == 6'd7 || rd_ptr == 6'd15 || rd_ptr == 6'd23 || rd_ptr == 6'd31 || rd_ptr == 6'd39 || rd_ptr == 6'd47 || rd_ptr == 6'd55 || rd_ptr == 6'd63)
|
begin
|
begin
|
open_slot_fct<= 1'b1;
|
open_slot_fct<= 1'b1;
|
end
|
end
|
else
|
else
|
begin
|
begin
|
open_slot_fct<= 1'b0;
|
open_slot_fct<= 1'b0;
|
end
|
end
|
|
|
if(block_read)
|
data_out <= mem[rd_ptr];
|
begin
|
|
if(!rd_en)
|
|
begin
|
|
block_read<= 1'b0;
|
|
end
|
end
|
|
2'd2:
|
|
begin
|
|
open_slot_fct<= open_slot_fct;
|
|
data_out <= data_out;
|
end
|
end
|
else
|
default:
|
if(rd_en && !f_empty)
|
|
begin
|
begin
|
block_read<= 1'b1;
|
rd_ptr <= rd_ptr;
|
rd_ptr <= rd_ptr+ 6'd1;
|
data_out <= data_out;
|
end
|
end
|
|
endcase
|
|
|
data_out <= mem[rd_ptr];
|
|
|
|
end
|
end
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|