Subversion Repositories ngs

Rev

Rev 98 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

  1. // part of NeoGS project
  2. //
  3. // (c) NedoPC 2007-2013
  4. //
  5. // SD-card dma controller
  6.  
  7. /*
  8.  
  9.  supports yet:
  10.   1. only read of SD card (512 bytes at once)
  11.   2. only full bursing writeback of read data to memory
  12.  
  13.  SD read algo:
  14.  send FFs always. Check replies.
  15.  After first non-FF reply receive 512 bytes into FPGA mem then into RAM
  16.  
  17. */
  18.  
  19.  
  20. module dma_sd
  21. (
  22.         input  wire clk,
  23.         input  wire rst_n,
  24.  
  25.         // control to spi module of SD-card
  26.         //
  27.         output wire       sd_start,
  28.         input  wire       sd_rdy,
  29.         input  wire [7:0] sd_recvdata,
  30.  
  31.        
  32.         // signals for ports.v
  33.         //
  34.         input  wire [7:0] din,  // input and output from ports.v
  35.         output reg  [7:0] dout,
  36.         //
  37.         input  wire       module_select, // =1 - module selected for read-write operations from ports.v
  38.         input  wire       write_strobe,  // one-cycle positive write strobe - writes to the selected registers from din
  39.         //
  40.         input  wire [1:0] regsel, // 2'b00 - high address, 2'b01 - middle address, 2'b10 - low address, 2'b11 - control register
  41.  
  42.         // signals for DMA controller/DMA sequencer
  43.         //
  44.         output reg  [21:0] dma_addr,
  45.         output wire  [7:0] dma_wd,   // data written to DMA
  46.         output wire        dma_rnw,
  47.         //
  48.         output wire        dma_req,
  49.         input  wire        dma_ack,
  50.         input  wire        dma_end,
  51.  
  52.         output wire        int_req
  53. );
  54.  
  55.         reg dma_on;
  56.  
  57.         wire dma_finish;
  58.  
  59.         reg [3:0] state, next_state;
  60.  
  61.         wire wdone,rdone;
  62.        
  63.         reg int_dma_req;
  64.  
  65.  
  66.  
  67.         assign int_req = dma_finish;
  68.  
  69.  
  70.  
  71.         localparam _HAD = 2'b00; // high address
  72.         localparam _MAD = 2'b01; // mid address
  73.         localparam _LAD = 2'b10; // low address
  74.         localparam _CST = 2'b11; // control and status
  75.  
  76.  
  77.  
  78.         // control dout bus
  79.         always @*
  80.         case( regsel[1:0] )
  81.                 _HAD: dout = { 2'b00,  dma_addr[21:16] };
  82.                 _MAD: dout =           dma_addr[15:8];
  83.                 _LAD: dout =           dma_addr[7:0];
  84.                 _CST: dout = { dma_on, 7'bXXX_XXXX };
  85.         endcase
  86.  
  87.  
  88.         // dma_on control
  89.         always @(posedge clk, negedge rst_n)
  90.         if( !rst_n )
  91.                 dma_on <= 1'b0;
  92.         else if( dma_finish )
  93.                 dma_on <= 1'b0;
  94.         else if( module_select && write_strobe && (regsel==_CST) )
  95.                 dma_on <= din[7];
  96.  
  97.  
  98.         // dma_addr control
  99.         always @(posedge clk)
  100.         if( dma_req && dma_ack && dma_on )
  101.                 dma_addr <= dma_addr + 22'd1; // increment on successfull DMA transfer
  102.         else if( module_select && write_strobe )
  103.         begin
  104.                 if( regsel==_HAD )
  105.                         dma_addr[21:16] <= din[5:0];
  106.                 else if( regsel==_MAD )
  107.                         dma_addr[15:8]  <= din[7:0];
  108.                 else if( regsel==_LAD )
  109.                         dma_addr[7:0]   <= din[7:0];
  110.         end
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.         // controlling FSM
  118.  
  119.         localparam _IDLE   = 4'd0;
  120.         localparam _WRDY1  = 4'd1;
  121.         localparam _WRDY2  = 4'd2;
  122.         localparam _RECV1  = 4'd3;
  123.         localparam _RECV2  = 4'd4;
  124.         localparam _CRC1   = 4'd5;
  125.         localparam _CRC2   = 4'd6;
  126.         localparam _DMAWR  = 4'd7;
  127.         localparam _STOP   = 4'd8;
  128.  
  129.  
  130.         always @(posedge clk, negedge dma_on)
  131.         if( !dma_on )
  132.                 state = _IDLE;
  133.         else // posedge clk
  134.                 state <= next_state;
  135.  
  136.         always @*
  137.         case( state )
  138.  
  139.         _IDLE: next_state = _WRDY1;
  140.        
  141.         _WRDY1:begin
  142.                 next_state = _WRDY2;
  143.         end
  144.        
  145.         _WRDY2:begin   
  146.                 if(     !sd_rdy )
  147.                                 next_state = _WRDY2;
  148.                 else     if( sd_recvdata==8'hFF )
  149.                             next_state = _WRDY1;
  150.                 else         if( sd_recvdata==8'hFE )
  151.                             next_state = _RECV1;
  152.                 else   
  153.                             next_state = _STOP;
  154.         end        
  155.                        
  156.         _RECV1:begin   
  157.                 if( !wdone )
  158.                         next_state = _RECV2;
  159.                 else
  160.                         next_state = _CRC1;
  161.         end
  162.  
  163.         _RECV2:begin
  164.                 if( !sd_rdy )
  165.                         next_state = _RECV2;
  166.                 else
  167.                         next_state = _RECV1;
  168.         end
  169.  
  170.         _CRC1:begin // 1st CRC byte is already started in last _RECV1 state
  171.                 if( !sd_rdy )
  172.                         next_state = _CRC1;
  173.                 else
  174.                         next_state = _CRC2;
  175.         end
  176.  
  177.         _CRC2:begin // here just start 2nd CRC byte receive
  178.                 next_state = _DMAWR;
  179.         end
  180.  
  181.         _DMAWR:begin
  182.                 if( int_dma_req )
  183.                         next_state = _DMAWR;
  184.                 else
  185.                         next_state = _STOP;
  186.         end
  187.  
  188.         _STOP:begin
  189.                 next_state = _STOP; // rely on dma_on going to 0 and resetting everything
  190.         end
  191.        
  192.         endcase
  193.  
  194.  
  195.         // sd_start
  196.         assign sd_start = ( state==_WRDY1 || state==_RECV1 || state==_CRC2 );
  197.  
  198.        
  199.         // dma_finish
  200.         assign dma_finish = ( state==_STOP );
  201.  
  202.        
  203.        
  204.  
  205.        
  206.  
  207.         // only dma writes
  208.         assign dma_rnw = 1'b0;
  209.  
  210.         assign dma_req = int_dma_req;
  211.  
  212.         always @(posedge clk, negedge dma_on)
  213.         if( !dma_on )
  214.                 int_dma_req <= 1'b0;
  215.         else if( state==_CRC2 )
  216.                 int_dma_req <= 1'b1;
  217.         else if( rdone && dma_ack )
  218.                 int_dma_req <= 1'b0;
  219.  
  220.  
  221.  
  222.         // fifo
  223.         dma_fifo_oneshot dma_fifo_oneshot
  224.         (
  225.                 .clk  (clk   ),
  226.                 .rst_n(dma_on),
  227.        
  228.                 .wr_stb( state==_RECV2 && sd_rdy ),
  229.                 .rd_stb( (dma_req && dma_ack) || state==_CRC2 ),
  230.        
  231.                 .wdone(wdone),
  232.                 .rdone(rdone),
  233.                 .empty(     ),
  234.                 .w511 (     ),
  235.        
  236.                 .wd(sd_recvdata),
  237.                 .rd(dma_wd     )
  238.         );
  239.        
  240.        
  241.  
  242. endmodule
  243.  
  244.  
  245.  
  246.  
  247.