Subversion Repositories ngs

Rev

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

  1. // part of NeoGS project
  2. //
  3. // (c) NedoPC 2013
  4. //
  5. // mp3 data dma controller
  6.  
  7. module dma_mp3
  8. (
  9.         input  wire clk,
  10.         input  wire rst_n,
  11.  
  12.         output wire [ 7:0] md_din,   // mp3 data interface
  13.         output wire        md_start, //
  14.         input  wire        md_rdy,   //
  15.         input  wire        md_dreq,  //
  16.  
  17.  
  18.         // signals for ports.v
  19.         //
  20.         input  wire [7:0] din,  // input and output from ports.v
  21.         output reg  [7:0] dout,
  22.         //
  23.         input  wire       module_select, // =1 - module selected for read-write operations from ports.v
  24.         input  wire       write_strobe,  // one-cycle positive write strobe - writes to the selected registers from din
  25.         //
  26.         input  wire [1:0] regsel, // 2'b00 - high address, 2'b01 - middle address, 2'b10 - low address, 2'b11 - control register
  27.  
  28.  
  29.         // signals for DMA controller/DMA sequencer
  30.         //
  31.         output reg  [21:0] dma_addr,
  32.         input  wire  [7:0] dma_rd,   // data read from DMA
  33.         output wire        dma_rnw,
  34.         //
  35.         output reg         dma_req,
  36.         input  wire        dma_ack,
  37.         input  wire        dma_end,
  38.  
  39.         output wire        int_req
  40. );
  41.         reg dma_on;
  42.  
  43.         wire dma_finish;
  44.  
  45.         wire w511;
  46.         wire rdone;
  47.  
  48.         reg [3:0] state,next_state;
  49.  
  50.  
  51.         assign int_req = dma_finish;
  52.  
  53.         assign dma_rnw = 1'b1;
  54.  
  55.  
  56.  
  57.  
  58.  
  59.         localparam _HAD = 2'b00; // high address
  60.         localparam _MAD = 2'b01; // mid address
  61.         localparam _LAD = 2'b10; // low address
  62.         localparam _CST = 2'b11; // control and status
  63.  
  64.         // control dout bus
  65.         always @*
  66.         case( regsel[1:0] )
  67.                 _HAD: dout = { 2'b00,  dma_addr[21:16] };
  68.                 _MAD: dout =           dma_addr[15:8];
  69.                 _LAD: dout =           dma_addr[7:0];
  70.                 _CST: dout = { dma_on, 7'bXXX_XXXX };
  71.         endcase
  72.  
  73.         // dma_on control
  74.         always @(posedge clk, negedge rst_n)
  75.         if( !rst_n )
  76.                 dma_on <= 1'b0;
  77.         else if( dma_finish )
  78.                 dma_on <= 1'b0;
  79.         else if( module_select && write_strobe && (regsel==_CST) )
  80.                 dma_on <= din[7];
  81.  
  82.         // dma_addr control
  83.         always @(posedge clk)
  84.         if( dma_req && dma_ack && dma_on )
  85.                 dma_addr <= dma_addr + 22'd1; // increment on successfull DMA transfer
  86.         else if( module_select && write_strobe )
  87.         begin
  88.                 if( regsel==_HAD )
  89.                         dma_addr[21:16] <= din[5:0];
  90.                 else if( regsel==_MAD )
  91.                         dma_addr[15:8]  <= din[7:0];
  92.                 else if( regsel==_LAD )
  93.                         dma_addr[7:0]   <= din[7:0];
  94.         end
  95.  
  96.  
  97.  
  98.  
  99.         localparam _IDLE  = 4'd0;
  100.         localparam _START = 4'd1;
  101.         localparam _DMARD = 4'd2;
  102.         localparam _MP3W1 = 4'd3;
  103.         localparam _MP3W2 = 4'd4;
  104.         localparam _MP3W3 = 4'd5;
  105.         localparam _STOP  = 4'd6;
  106.  
  107.  
  108.         always @(posedge clk, negedge dma_on)
  109.         if( !dma_on )
  110.                 state <= _IDLE;
  111.         else
  112.                 state <= next_state;
  113.  
  114.         always @*
  115.         case( state )
  116.         _IDLE: next_state = _START;
  117.  
  118.         _START: next_state = _DMARD;
  119.  
  120.         _DMARD:begin
  121.                 if( dma_req )
  122.                         next_state = _DMARD;
  123.                 else
  124.                         next_state = _MP3W1;
  125.         end
  126.  
  127.         _MP3W1: next_state = _MP3W2;
  128.  
  129.         _MP3W2:begin
  130.                 if( md_rdy && md_dreq )
  131.                         next_state = _MP3W3;
  132.                 else
  133.                         next_state = _MP3W2;
  134.         end
  135.  
  136.         _MP3W3:begin
  137.                 if( rdone )
  138.                         next_state = _STOP;
  139.                 else
  140.                         next_state = _MP3W2;
  141.         end
  142.  
  143.         _STOP: next_state = _STOP;
  144.  
  145.         endcase
  146.  
  147.  
  148.         assign md_start = ( state==_MP3W3 );
  149.  
  150.         assign dma_finish = ( state==_STOP );
  151.  
  152.  
  153.  
  154.         always @(posedge clk, negedge dma_on)
  155.         if( !dma_on )
  156.                 dma_req <= 1'b0;
  157.         else if( state==_START )
  158.                 dma_req <= 1'b1;
  159.         else if( dma_ack && w511 )
  160.                 dma_req <= 1'b0;
  161.  
  162.  
  163.  
  164.  
  165.         dma_fifo_oneshot dma_fifo_oneshot
  166.         (
  167.                 .clk  (clk   ),
  168.                 .rst_n(dma_on),
  169.        
  170.                 .wr_stb( dma_end  ),
  171.                 .rd_stb( md_start || state==_MP3W1 ),
  172.        
  173.                 .wdone(     ),
  174.                 .rdone(rdone),
  175.                 .empty(     ),
  176.                 .w511 (w511 ),
  177.        
  178.                 .wd(dma_rd),
  179.                 .rd(md_din)
  180.         );
  181.  
  182.  
  183. endmodule
  184.  
  185.