module sd_fifo_filler(
           input wb_clk,
           input rst,
           //WB Signals
           output [31:0] wbm_adr_o,
           output wbm_we_o,
           output [31:0] wbm_dat_o,
           input [31:0] wbm_dat_i,
           output wbm_cyc_o,
           output wbm_stb_o,
           input wbm_ack_i,
           //Data Master Control signals
           input en_rx_i,
           input en_tx_i,
           input [31:0] adr_i,
           //Data Serial signals
           input sd_clk,
           input [31:0] dat_i,
           output [31:0] dat_o,
           input wr_i,
           input rd_i,
           output sd_full_o,
           output sd_empty_o,
           output wb_full_o,
           output wb_empty_o
       );

`define FIFO_MEM_ADR_SIZE 4
`define MEM_OFFSET 4

wire reset_fifo;
wire fifo_rd;
reg [31:0] offset;
reg fifo_rd_ack;
reg fifo_rd_reg;

assign fifo_rd = wbm_cyc_o & wbm_ack_i;
assign reset_fifo = !en_rx_i & !en_tx_i;

assign wbm_we_o = en_rx_i & !wb_empty_o;
assign wbm_cyc_o = en_rx_i ? en_rx_i & !wb_empty_o : en_tx_i & !wb_full_o;
assign wbm_stb_o = en_rx_i ? wbm_cyc_o & fifo_rd_ack : wbm_cyc_o;

generic_fifo_dc_gray #(
    .dw(32), 
    .aw(`FIFO_MEM_ADR_SIZE)
    ) generic_fifo_dc_gray0 (
    .rd_clk(wb_clk),
    .wr_clk(sd_clk), 
    .rst(!(rst | reset_fifo)), 
    .clr(1'b0), 
    .din(dat_i), 
    .we(wr_i),
    .dout(wbm_dat_o), 
    .re(en_rx_i & wbm_cyc_o & wbm_ack_i), 
    .full(sd_full_o), 
    .empty(wb_empty_o), 
    .wr_level(), 
    .rd_level() 
    );
    
generic_fifo_dc_gray #(
    .dw(32), 
    .aw(`FIFO_MEM_ADR_SIZE)
    ) generic_fifo_dc_gray1 (
    .rd_clk(sd_clk),
    .wr_clk(wb_clk), 
    .rst(!(rst | reset_fifo)), 
    .clr(1'b0), 
    .din(wbm_dat_i), 
    .we(en_tx_i & wbm_cyc_o & wbm_stb_o & wbm_ack_i),
    .dout(dat_o), 
    .re(rd_i), 
    .full(wb_full_o), 
    .empty(sd_empty_o), 
    .wr_level(), 
    .rd_level() 
    );

assign wbm_adr_o = adr_i+offset;

always @(posedge wb_clk or posedge rst)
    if (rst) begin
        offset <= 0;
        fifo_rd_reg <= 0;
        fifo_rd_ack <= 1;
    end
    else begin
        fifo_rd_reg <= fifo_rd;
        fifo_rd_ack <= fifo_rd_reg | !fifo_rd;
        if (wbm_cyc_o & wbm_stb_o & wbm_ack_i)
            offset <= offset + `MEM_OFFSET;
        else if (reset_fifo)
            offset <= 0;
    end

endmodule