Subversion Repositories ngs

Rev

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

  1. // part of NeoGS project
  2. //
  3. // (c) NedoPC 2007-2008
  4. //
  5. // modelling is in tb_dma1.*
  6. // look also at dma_access.png
  7.  
  8. module dma_access(
  9.  
  10.         input            clk,
  11.  
  12.         input            rst_n,
  13.  
  14.  
  15.         input            dma_req,  // DMA request
  16.         input     [21:0] dma_addr, // DMA address (2mb)
  17.         input            dma_rnw,  // DMA READ/nWRITE
  18.         input      [7:0] dma_wd,   // DMA data to write
  19.         output reg [7:0] dma_rd,   // DMA data just read
  20.  
  21.         output reg       dma_busynready, // DMA BUSY/nREADY
  22.         output reg       dma_ack, // positive pulse as dma_busynready goes high
  23.         output reg       dma_end, // positive pulse as dma_busynready goes low
  24.  
  25.         output wire        mem_dma_bus,  // DMA taking over the bus
  26.         output wire [21:0] mem_dma_addr, // DMA address going to the bus
  27.         output wire  [7:0] mem_dma_wd,   // DMA data going to the bus
  28.         input        [7:0] mem_dma_rd,   // DMA data going from the bus
  29.         output wire        mem_dma_rnw,  // DMA bus direction (1=read, 0=write)
  30.         output reg         mem_dma_oe,   // DMA read strobe going to the bus
  31.         output reg         mem_dma_we,   // DMA write pulse going to the bus
  32.  
  33.  
  34.         output reg       busrq_n, // CPU       signals
  35.         input            busak_n  //    control
  36. );
  37.  
  38.         reg dma_bus;
  39.  
  40.         reg [21:0] int_dma_addr;
  41.         reg        int_dma_rnw;
  42.         reg  [7:0] int_dma_wd;
  43.         wire [7:0] int_dma_rd;
  44.  
  45.         assign mem_dma_bus  = dma_bus;
  46.         assign mem_dma_addr = int_dma_addr;
  47.         assign mem_dma_wd   = int_dma_wd;
  48.         assign mem_dma_rnw  = int_dma_rnw;
  49.         assign int_dma_rd   = mem_dma_rd;
  50.  
  51.  
  52.  
  53.         localparam IDLE     = 0;
  54.         localparam START    = 1;
  55.         localparam WACK     = 2;
  56.         localparam READ1    = 3;
  57.         localparam READ2    = 4;
  58.         localparam WRITE1   = 5;
  59.         localparam WRITE2   = 6;
  60.  
  61.  
  62.         reg [3:0] state;
  63.         reg [3:0] next_state;
  64.  
  65.  
  66.  
  67.  
  68.         // for simulation purposes
  69.         initial
  70.         begin
  71.                 state       <= IDLE;
  72.                 busrq_n     <= 1'b1;
  73.                 mem_dma_oe  <= 1'b1;
  74.                 mem_dma_we  <= 1'b1;
  75.         end
  76.  
  77.  
  78. // FSM
  79.         always @(posedge clk, negedge rst_n)
  80.         begin
  81.                 if( !rst_n )
  82.                         state <= IDLE;
  83.                 else
  84.                         state <= next_state;
  85.         end
  86.  
  87.  
  88.         always @*
  89.         begin
  90.                 case( state )
  91. //////////////////////////////////////////////////////////////////////////////////////////
  92.                 IDLE:
  93.                 begin
  94.                         if( dma_req==1'b1 )
  95.                                 next_state <= START;
  96.                         else
  97.                                 next_state <= IDLE;
  98.                 end
  99. //////////////////////////////////////////////////////////////////////////////////////////
  100.                 START:
  101.                 begin
  102.                         next_state <= WACK;
  103.                 end
  104. //////////////////////////////////////////////////////////////////////////////////////////
  105.                 WACK:
  106.                 begin
  107.                         if( busak_n == 1'b1 ) ///// ACHTUNG WARNING!!! probably use here registered busak?
  108.                                 next_state <= WACK;
  109.                         else // busak_n == 1'b0
  110.                         begin
  111.                                 if( int_dma_rnw == 1'b1 ) // read
  112.                                         next_state <= READ1;
  113.                                 else // int_dma_rnw == 1'b0 - write
  114.                                         next_state <= WRITE1;
  115.                         end
  116.                 end
  117. //////////////////////////////////////////////////////////////////////////////////////////
  118.                 READ1:
  119.                 begin
  120.                         next_state <= READ2;
  121.                 end
  122. //////////////////////////////////////////////////////////////////////////////////////////
  123.                 READ2:
  124.                 begin
  125.                         if( dma_req == 1'b0 )
  126.                                 next_state <= IDLE;
  127.                         else // dma_req == 1'b1
  128.                         begin
  129.                                 if( dma_rnw == 1'b1 ) // next is read
  130.                                         next_state <= READ1;
  131.                                 else // dma_rnw == 1'b0 - next is write
  132.                                         next_state <= WRITE1;
  133.                         end
  134.                 end
  135. //////////////////////////////////////////////////////////////////////////////////////////
  136.                 WRITE1:
  137.                 begin
  138.                         next_state <= WRITE2;
  139.                 end
  140. //////////////////////////////////////////////////////////////////////////////////////////
  141.                 WRITE2:
  142.                 begin
  143.                         if( dma_req == 1'b0 )
  144.                                 next_state <= IDLE;
  145.                         else // dma_req == 1'b1
  146.                         begin
  147.                                 if( dma_rnw == 1'b1 ) // next is read
  148.                                         next_state <= READ1;
  149.                                 else // dma_rnw == 1'b0 - next is write
  150.                                         next_state <= WRITE1;
  151.                         end
  152.                 end
  153. //////////////////////////////////////////////////////////////////////////////////////////
  154.                 endcase
  155.         end
  156.  
  157.  
  158.         always @(posedge clk, negedge rst_n)
  159.         begin
  160.                 if( !rst_n )
  161.                 begin
  162.                         busrq_n        <= 1'b1;
  163.                         dma_busynready <= 1'b0;
  164.                         dma_ack        <= 1'b0;
  165.                         dma_end        <= 1'b0;
  166.                         dma_bus        <= 1'b0;
  167.                         mem_dma_oe     <= 1'b1;
  168.                 end
  169.                 else case( next_state )
  170. //////////////////////////////////////////////////////////////////////////////////////////
  171.                 IDLE:
  172.                 begin
  173.                         dma_end        <= 1'b0;
  174.  
  175.                         busrq_n        <= 1'b1;
  176.                         dma_bus        <= 1'b0;
  177.                         mem_dma_oe     <= 1'b1;
  178.                 end
  179. //////////////////////////////////////////////////////////////////////////////////////////
  180.                 START:
  181.                 begin
  182. //                      dma_bus        <= 1'b0; // if rst=0>1 and dma_ack=1 --> ??? is this really needed?
  183.  
  184.  
  185.                         busrq_n        <= 1'b0;
  186.  
  187.                         dma_busynready <= 1'b1;
  188.                         dma_ack        <= 1'b1;
  189.  
  190.                         int_dma_rnw    <= dma_rnw;
  191.                         int_dma_addr   <= dma_addr;
  192.                         int_dma_wd     <= dma_wd;
  193.                 end
  194. //////////////////////////////////////////////////////////////////////////////////////////
  195.                 WACK:
  196.                 begin
  197.                         dma_ack <= 1'b0;
  198.                 end
  199. //////////////////////////////////////////////////////////////////////////////////////////
  200.                 READ1:
  201.                 begin
  202.                         dma_bus    <= 1'b1; // take over the bus
  203.                         mem_dma_oe <= 1'b0;
  204.                         if( dma_busynready == 1'b0 ) // if we are here from READ2 or WRITE2
  205.                         begin
  206.                                 dma_busynready <= 1'b1;
  207.                                 dma_ack        <= 1'b1;
  208.                                 dma_end        <= 1'b0;
  209.                                 int_dma_rnw    <= 1'b1;
  210.                                 int_dma_addr   <= dma_addr;
  211.                         end
  212.                 end
  213. //////////////////////////////////////////////////////////////////////////////////////////
  214.                 READ2:
  215.                 begin
  216.                         dma_busynready <= 1'b0;
  217.                         dma_ack        <= 1'b0;
  218.                         dma_end        <= 1'b1;
  219.                         dma_rd <= int_dma_rd;
  220.                 end
  221. //////////////////////////////////////////////////////////////////////////////////////////
  222.                 WRITE1:
  223.                 begin
  224.                         dma_bus    <= 1'b1; // take over the bus
  225.                         mem_dma_oe <= 1'b1;
  226.  
  227.                         if( dma_busynready == 1'b0 ) // from READ2 or WRITE2
  228.                         begin
  229.                                 dma_busynready <= 1'b1;
  230.                                 dma_ack        <= 1'b1;
  231.                                 dma_end        <= 1'b0;
  232.                                 int_dma_rnw    <= 1'b0;
  233.                                 int_dma_addr   <= dma_addr;
  234.                                 int_dma_wd     <= dma_wd;
  235.                         end
  236.                 end
  237. //////////////////////////////////////////////////////////////////////////////////////////
  238.                 WRITE2:
  239.                 begin
  240.                         dma_busynready <= 1'b0;
  241.                         dma_ack        <= 1'b0;
  242.                         dma_end        <= 1'b1;
  243.                 end
  244. //////////////////////////////////////////////////////////////////////////////////////////
  245.                 endcase
  246.         end
  247.  
  248.  
  249.  
  250.  
  251. // mem_dma_we generator
  252.  
  253.         always @(negedge clk,negedge rst_n)
  254.         begin
  255.                 if( !rst_n )
  256.                         mem_dma_we <= 1'b1;
  257.                 else
  258.                 begin
  259.                         if( dma_bus )
  260.                         begin
  261.                                 if( !int_dma_rnw )
  262.                                         mem_dma_we <= ~mem_dma_we;
  263.                         end
  264.                         else
  265.                                 mem_dma_we <= 1'b1;
  266.                 end
  267.         end
  268.  
  269.  
  270. endmodule
  271.  
  272.