module asynch_fifo#( parameter FIFO_AFULL_SIZE = 1, parameter FIFO_AEMPTY_SIZE = 1, parameter FIFO_PTR = 4, parameter FIFO_WIDTH = 8 // parameter FIFO_DEPTH = 16 )( fifo_wrclk , fifo_wr_rst_n , fifo_wren , fifo_wrdata , reset_wrptr , fifo_rdclk , fifo_rd_rst_n , fifo_rden , fifo_rddata , reset_rdptr , fifo_full , fifo_empty , fifo_afull , fifo_aempty , fifo_room_avail, fifo_data_avail ); input wire fifo_wrclk ; input wire fifo_wr_rst_n ; input wire fifo_wren ; input wire [FIFO_WIDTH-1:0] fifo_wrdata ; input wire reset_wrptr ; input wire fifo_rdclk ; input wire fifo_rd_rst_n ; input wire fifo_rden ; output wire [FIFO_WIDTH-1:0] fifo_rddata ; input wire reset_rdptr ; output reg fifo_full ; output reg fifo_empty ; output wire fifo_afull ; output wire fifo_aempty ; output reg [FIFO_PTR:0] fifo_room_avail; output reg [FIFO_PTR:0] fifo_data_avail;
localparam FIFO_DEPTH = (1<<FIFO_PTR); localparam FIFO_TWICEDEPTH_MINUS1 = 2*FIFO_DEPTH - 1;
//****************REG************************** reg [FIFO_PTR:0] wr_ptr_wab,wr_ptr_wab_nxt;//extra wraparound bit wire [FIFO_PTR:0] fifo_room_avail_nxt ; wire fifo_full_nxt ; wire [FIFO_PTR:0] wr_ptr ;//write ptr without wraparound bit reg [FIFO_PTR:0] rd_ptr_wab,rd_ptr_wab_nxt;//extra wraparound bit wire [FIFO_PTR:0] fifo_data_avail_nxt ; wire fifo_empty_nxt ; wire [FIFO_PTR:0] rd_ptr ;//read ptr without wraparound bit
reg [FIFO_PTR:0] wr_ptr_wab_gray ; wire [FIFO_PTR:0] wr_ptr_wab_gray_nxt ; reg [FIFO_PTR:0] wr_ptr_wab_gray_sync1 ; reg [FIFO_PTR:0] wr_ptr_wab_gray_sync2 ; reg [FIFO_PTR:0] wr_ptr_wab_rdclk ; wire [FIFO_PTR:0] wr_ptr_wab_rdclk_nxt ;
reg [FIFO_PTR:0] rd_ptr_wab_gray ; wire [FIFO_PTR:0] rd_ptr_wab_gray_nxt ; reg [FIFO_PTR:0] rd_ptr_wab_gray_sync1 ; reg [FIFO_PTR:0] rd_ptr_wab_gray_sync2 ; reg [FIFO_PTR:0] rd_ptr_wab_wrclk ; wire [FIFO_PTR:0] rd_ptr_wab_wrclk_nxt ; //write pointer control logic //********************************************* always@(*) begin wr_ptr_wab_nxt = wr_ptr_wab; if(reset_wrptr) begin wr_ptr_wab_nxt = 'd0; end else if(fifo_wren&&(wr_ptr_wab == FIFO_TWICEDEPTH_MINUS1)) begin wr_ptr_wab_nxt = 'd0; end else if(fifo_wren) begin wr_ptr_wab_nxt = wr_ptr_wab + 1'b1; end end
always@(posedge fifo_wrclk or negedge fifo_wr_rst_n) begin if(!fifo_wr_rst_n) begin wr_ptr_wab <= 'd0; end else begin wr_ptr_wab <= wr_ptr_wab_nxt; end end
//convert the binary wr_ptr to gray,flop it,and then pass it to read domain //********************************************* binary_to_gray#(.PTR(FIFO_PTR)) u_binary_to_gray_wr ( .binary_value (wr_ptr_wab_nxt ), .gray_value (wr_ptr_wab_gray_nxt ) );
always@(posedge fifo_wrclk or negedge fifo_wr_rst_n) begin if(!fifo_wr_rst_n) begin wr_ptr_wab_gray <= 'd0; end else begin wr_ptr_wab_gray <= wr_ptr_wab_gray_nxt; end end
//synchronize wr_ptr_wab_gray into read clock domain //********************************************* always@(posedge fifo_rdclk or negedge fifo_rd_rst_n) begin if(!fifo_rd_rst_n) begin wr_ptr_wab_gray_sync1 <= 'd0; wr_ptr_wab_gray_sync2 <= 'd0; end else begin wr_ptr_wab_gray_sync1 <= wr_ptr_wab_gray; wr_ptr_wab_gray_sync2 <= wr_ptr_wab_gray_sync1; end end
//convert wr_ptr_wab_gray_sync2 back to binary form //********************************************* gray_to_binary#(.PTR(FIFO_PTR)) u_gray_to_binary_wr ( .gray_value (wr_ptr_wab_gray_sync2 ), .binary_value (wr_ptr_wab_rdclk_nxt ) );
always@(posedge fifo_rdclk or negedge fifo_rd_rst_n) begin if(!fifo_rd_rst_n) begin wr_ptr_wab_rdclk <= 'd0; end else begin wr_ptr_wab_rdclk <= wr_ptr_wab_rdclk_nxt; end end
//read pointer control logic //********************************************* always@(*) begin rd_ptr_wab_nxt = rd_ptr_wab; if(reset_rdptr) begin rd_ptr_wab_nxt = 'd0; end else if(fifo_rden && (rd_ptr_wab == FIFO_TWICEDEPTH_MINUS1)) begin rd_ptr_wab_nxt = 'd0; end else if(fifo_rden) begin rd_ptr_wab_nxt = rd_ptr_wab + 1'b1; end end
always@(posedge fifo_rdclk or negedge fifo_rd_rst_n) begin if(!fifo_rd_rst_n) begin rd_ptr_wab <= 'd0; end else begin rd_ptr_wab <= rd_ptr_wab_nxt; end end
//convert the binary rd_ptr to gray and then pass it to write clock domain //********************************************* binary_to_gray#(.PTR(FIFO_PTR)) u_binary_to_gray_rd ( .binary_value (rd_ptr_wab_nxt ), .gray_value (rd_ptr_wab_gray_nxt ) );
always@(posedge fifo_rdclk or negedge fifo_rd_rst_n) begin if(!fifo_rd_rst_n) begin rd_ptr_wab_gray <= 'd0; end else begin rd_ptr_wab_gray <= rd_ptr_wab_gray_nxt; end end
//synchronize rd_ptr_wab_gray into write clock domain //********************************************* always@(posedge fifo_wrclk or negedge fifo_wr_rst_n) begin if(!fifo_wr_rst_n) begin rd_ptr_wab_gray_sync1 <= 'd0; rd_ptr_wab_gray_sync2 <= 'd0; end else begin rd_ptr_wab_gray_sync1 <= rd_ptr_wab_gray; rd_ptr_wab_gray_sync2 <= rd_ptr_wab_gray_sync1; end end
//convert rd_ptr_wab_gray_sync2 back to binary form //********************************************* gray_to_binary#(.PTR(FIFO_PTR)) u_gray_to_binary_rd ( .gray_value (rd_ptr_wab_gray_sync2 ), .binary_value (rd_ptr_wab_wrclk_nxt ) );
always@(posedge fifo_rdclk or negedge fifo_rd_rst_n) begin if(!fifo_rd_rst_n) begin rd_ptr_wab_wrclk <= 'd0; end else begin rd_ptr_wab_wrclk <= rd_ptr_wab_wrclk_nxt; end end
assign wr_ptr = wr_ptr_wab[FIFO_PTR-1:0]; assign rd_ptr = rd_ptr_wab[FIFO_PTR-1:0];
//the ram instantiation sdp //*********************************************
sdp_ram #( .DATA_W (FIFO_WIDTH ), .ADDR_WIDTH (FIFO_PTR ), .REG_OUT (0 ) )u_ram( .data_in (fifo_wrdata ), .wraddress (wr_ptr ), .wren (fifo_wren ), .clk_w (fifo_wrclk ), .data_out (fifo_rddata ), .rdaddress (rd_ptr ), .rden (fifo_rden ), .clk_r (fifo_rdclk ), .rst_n_w (fifo_wr_rst_n ), .rst_n_r (fifo_rd_rst_n ) );
//generate fifo_full:pointers equal,but the warp around bits are different //********************************************* assign fifo_full_nxt = (wr_ptr_wab_nxt[FIFO_PTR] != rd_ptr_wab_wrclk_nxt[FIFO_PTR]) && (wr_ptr_wab_nxt[FIFO_PTR-1:0] == rd_ptr_wab_wrclk_nxt[FIFO_PTR-1:0]);
assign fifo_room_avail_nxt = (wr_ptr_wab[FIFO_PTR] == rd_ptr_wab_wrclk[FIFO_PTR])? (FIFO_DEPTH - (wr_ptr_wab[FIFO_PTR-1:0] - rd_ptr_wab_wrclk[FIFO_PTR-1:0])): (rd_ptr_wab_wrclk[FIFO_PTR-1:0] - wr_ptr_wab[FIFO_PTR-1:0]);
//generate fifo_empty:pointers are equal including the warp around bits //********************************************* assign fifo_empty_nxt = (rd_ptr_wab_nxt[FIFO_PTR:0] == wr_ptr_wab_rdclk_nxt[FIFO_PTR:0]);
assign fifo_data_avail_nxt = (rd_ptr_wab[FIFO_PTR] == wr_ptr_wab_rdclk[FIFO_PTR])? (wr_ptr_wab_rdclk[FIFO_PTR-1:0] - rd_ptr_wab[FIFO_PTR-1:0]): (FIFO_DEPTH - (rd_ptr_wab[FIFO_PTR-1:0] - wr_ptr_wab_rdclk[FIFO_PTR-1:0]));
assign fifo_afull = (fifo_room_avail_nxt <= FIFO_AFULL_SIZE)? 1:0; assign fifo_aempty = (fifo_data_avail_nxt <= FIFO_AEMPTY_SIZE ) ? 1:0;
always@(posedge fifo_wrclk or negedge fifo_wr_rst_n) begin if(!fifo_wr_rst_n) begin fifo_full <= 1'b0; fifo_room_avail <= 'd0; end else begin fifo_full <= fifo_full_nxt; fifo_room_avail <= fifo_room_avail_nxt; end end
always@(posedge fifo_rdclk or negedge fifo_rd_rst_n) begin if(!fifo_rd_rst_n) begin fifo_empty <= 1'b1; fifo_data_avail <= 'd0; end else begin fifo_empty <= fifo_empty_nxt; fifo_data_avail <= fifo_data_avail_nxt; end end
endmodule
module binary_to_gray#( parameter PTR = 4 //"1","0" )( binary_value , gray_value );
input wire [PTR:0] binary_value ; output wire [PTR:0] gray_value ;
generate genvar i; for( i = 0 ; i < PTR ; i = i + 1 ) begin assign gray_value = binary_value ^ binary_value[ i + 1 ]; end
endgenerate
assign gray_value[PTR] = binary_value[PTR];
endmodule
module gray_to_binary#( parameter PTR = 4 //"1","0" )( binary_value , gray_value );
input wire [PTR:0] gray_value ; output wire [PTR:0] binary_value ;
generate genvar i; for( i = 0 ; i < PTR ; i = i + 1 ) begin assign binary_value = binary_value[i + 1] ^ gray_value; end
endgenerate
assign binary_value[PTR] = gray_value[PTR];
endmodule
module sdp_ram#( parameter DATA_W = 1, parameter ADDR_WIDTH= 9, parameter REG_OUT = 1, parameter U_DLY = 1 )( input [1 -1:0] clk_w , input [1 -1:0] rst_n_w , input [1 -1:0] wren , input [ADDR_WIDTH -1:0] wraddress , input [DATA_W -1:0] data_in , input [1 -1:0] clk_r , input [1 -1:0] rst_n_r , input [1 -1:0] rden , input [ADDR_WIDTH -1:0] rdaddress , output [DATA_W -1:0] data_out );
localparam ADDR_NUM = 2**ADDR_WIDTH;
reg [DATA_W -1:0] mem [ADDR_NUM -1:0]; reg [DATA_W -1:0] q_tmp ; reg [DATA_W -1:0] q_tmp_1d ;
always@(posedge clk_w or negedge rst_n_w) begin if(!rst_n_w) mem[wraddress] <= #U_DLY 'd0; else if(wren==1'b1) begin mem[wraddress] <= #U_DLY data_in; end end
always@(posedge clk_r or negedge rst_n_r) begin if(!rst_n_r) q_tmp <= #U_DLY 'd0; else if(rden==1'b1) begin q_tmp <= #U_DLY mem[rdaddress]; end end
always@(posedge clk_r ) begin q_tmp_1d <= #U_DLY q_tmp; end
assign data_out =(REG_OUT == 1) ? q_tmp_1d : q_tmp ;
endmodule |