`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    19:19:08 12/01/2010 
// Design Name: 
// Module Name:    sd_dma 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module sd_dma(
  input [3:0] SD_DAT,
  inout SD_CLK,
  input CLK,
  input SD_DMA_EN,
  input SD_DMA_TGT,
  output SD_DMA_STATUS,
  output SD_DMA_SRAM_WE,
  output SD_DMA_NEXTADDR,
  output [7:0] SD_DMA_SRAM_DATA,
  input SD_DMA_PARTIAL,
  input [10:0] SD_DMA_PARTIAL_START,
  input [10:0] SD_DMA_PARTIAL_END
);

reg [10:0] SD_DMA_STARTr;
reg [10:0] SD_DMA_ENDr;
reg SD_DMA_PARTIALr;
always @(posedge CLK) SD_DMA_PARTIALr <= SD_DMA_PARTIAL;

reg SD_DMA_DONEr;
reg[2:0] SD_DMA_DONEr2;
initial begin
  SD_DMA_DONEr2 = 3'b000;
  SD_DMA_DONEr = 1'b0;
end
always @(posedge CLK) SD_DMA_DONEr2 <= {SD_DMA_DONEr2[1:0], SD_DMA_DONEr};
wire SD_DMA_DONE_rising = (SD_DMA_DONEr2[1:0] == 2'b01);

reg [2:0] SD_DMA_ENr;
initial SD_DMA_ENr = 3'b000;
always @(posedge CLK) SD_DMA_ENr <= {SD_DMA_ENr[1:0], SD_DMA_EN};
wire SD_DMA_EN_rising = (SD_DMA_ENr [1:0] == 2'b01);

reg SD_DMA_STATUSr;
assign SD_DMA_STATUS = SD_DMA_STATUSr;

// we need 1042 cycles (startbit + 1024 nibbles + 16 crc + stopbit)
reg [10:0] cyclecnt;
initial cyclecnt = 11'd0;

reg SD_DMA_SRAM_WEr;
assign SD_DMA_SRAM_WE = (cyclecnt < 1025 && SD_DMA_STATUSr) ? SD_DMA_SRAM_WEr : 1'b1;

reg SD_DMA_NEXTADDRr;
assign SD_DMA_NEXTADDR = (cyclecnt < 1025 && SD_DMA_STATUSr) ? SD_DMA_NEXTADDRr : 1'b0;

reg[7:0] SD_DMA_SRAM_DATAr;
assign SD_DMA_SRAM_DATA = SD_DMA_SRAM_DATAr;

// we have 4 internal cycles per SD clock
reg [12:0] clkcnt;
initial clkcnt = 13'd0;
reg SD_CLKr;
always @(posedge CLK) SD_CLKr <= clkcnt[1];
assign SD_CLK = SD_DMA_STATUSr ? SD_CLKr : 1'bZ;

always @(posedge CLK) begin
  if(SD_DMA_EN_rising) begin
    SD_DMA_STATUSr <= 1'b1;
    SD_DMA_STARTr <= (SD_DMA_PARTIALr ? SD_DMA_PARTIAL_START : 11'h0);
    SD_DMA_ENDr <= (SD_DMA_PARTIALr ? SD_DMA_PARTIAL_END : 11'd1024);
  end
  else if (SD_DMA_DONE_rising) SD_DMA_STATUSr <= 1'b0;
end

always @(posedge CLK) begin
  if(cyclecnt == 1042) SD_DMA_DONEr <= 1;
  else SD_DMA_DONEr <= 0;
end

always @(posedge CLK) begin
  if(SD_DMA_EN_rising || !SD_DMA_STATUSr) begin
    clkcnt <= 0;
  end else begin
    if(SD_DMA_STATUSr) begin
      clkcnt <= clkcnt + 1;
    end
  end
end

always @(posedge CLK) begin
  if(SD_DMA_EN_rising || !SD_DMA_STATUSr) cyclecnt <= 0;
  else if(clkcnt[1:0] == 2'b11) cyclecnt <= cyclecnt + 1;
end

// we have 8 clk cycles to complete one RAM write
// (4 clk cycles per SD_CLK; 2 SD_CLK cycles per byte)
always @(posedge CLK) begin
  if(SD_DMA_STATUSr) begin
    case(clkcnt[2:0])
      3'h0: begin
        SD_DMA_SRAM_WEr <= 1'b1;
        SD_DMA_SRAM_DATAr[7:4] <= SD_DAT;
        if(cyclecnt>SD_DMA_STARTr && cyclecnt <= SD_DMA_ENDr) SD_DMA_NEXTADDRr <= 1'b1;
      end
      3'h1:
        SD_DMA_NEXTADDRr <= 1'b0;
//  3'h2:
      3'h3:
        if(cyclecnt>=SD_DMA_STARTr && cyclecnt < SD_DMA_ENDr) SD_DMA_SRAM_WEr <= 1'b0;
      3'h4:
        SD_DMA_SRAM_DATAr[3:0] <= SD_DAT;
//  3'h5:
//  3'h6:
//  3'h7:
    endcase
  end
end

endmodule

