Subversion Repositories ngs

Rev

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

  1. // part of NeoGS project
  2. //
  3. // (c) NedoPC 2007-2009
  4. //
  5. // ZX dma controller
  6. //
  7. // includes dma address regs, dma control reg
  8. //
  9. // CURRENTLY ONLY READ ON ZXBUS SIDE FROM NGS MEM, error in WAIT generation! zx_dma2.v - further development
  10.  
  11. module dma_zx(
  12.  
  13.         input clk,
  14.         input rst_n,
  15.  
  16.  
  17.         // ZXBUS-related signals
  18.  
  19.         input zxdmaread,  // async strobes made directly from zxbus signals
  20.         input zxdmawrite, //
  21.  
  22.         input      [7:0] dma_wr_data, // data written by ZXBUS here
  23.         output reg [7:0] dma_rd_data, // to be output to the ZXBUS from here
  24.  
  25.         output reg wait_ena, // for zxbus module, to stop temporarily ZX Z80
  26.  
  27.  
  28.  
  29.  
  30.         // different global & control signals
  31.  
  32.         output reg dma_on,
  33.  
  34.  
  35.         // signals from ports.v
  36.  
  37.         input      [7:0] din,  // input and output from ports.v
  38.         output reg [7:0] dout,
  39.  
  40.         input module_select, // =1 - module selected for read-write operations from ports.v
  41.         input write_strobe, // one-cycle positive write strobe - writes to the selected registers from din
  42.  
  43.         input [1:0] regsel, // 2'b00 - high address, 2'b01 - middle address, 2'b10 - low address, 2'b11 - control register
  44.  
  45.  
  46.         // signals for DMA controller
  47.  
  48.       output reg [20:0] dma_addr,
  49.       output reg  [7:0] dma_wd,
  50.       input       [7:0] dma_rd,
  51.       output reg        dma_rnw,
  52.  
  53.       output reg dma_req,
  54.       input      dma_ack,
  55.       input      dma_end
  56.  
  57. );
  58.  
  59.         reg [7:0] dma_rd_temp; // temporarily buffered read data from DMA module
  60.  
  61.         reg [2:0] zxdmaread_sync;  // syncing appropriate zxbus signals
  62.         reg [2:0] zxdmawrite_sync;
  63.  
  64.         reg zxread_begin, zxwrite_begin; // 1-cycle positive pulses based on synced in zxdmaread and zxdmawrite
  65.         reg zxread_end,   zxwrite_end;   //
  66.  
  67.  
  68.         reg dma_prereq; // to help assert dma_req one cycle earlier
  69.  
  70.  
  71.  
  72.         reg [1:0] waena_state,waena_next; // and wait_ena generation
  73.  
  74.         reg [1:0] dmarq_state,dmarq_next; // DMA req gen
  75.  
  76.  
  77.  
  78.         localparam _HAD = 2'b00; // high address
  79.         localparam _MAD = 2'b01; // mid address
  80.         localparam _LAD = 2'b10; // low address
  81.         localparam _CST = 2'b11; // control and status
  82.  
  83.         // control dout bus
  84.         always @*
  85.         case( regsel[1:0] )
  86.                 _HAD: dout = { 3'b000, dma_addr[20:16] };
  87.                 _MAD: dout = dma_addr[15:8];
  88.                 _LAD: dout = dma_addr[7:0];
  89.                 _CST: dout = { dma_on, 7'bXXXXXXX };
  90.         endcase
  91.  
  92.         // ports.v write access & dma_addr control
  93.         always @(posedge clk, negedge rst_n)
  94.         if( !rst_n ) // async reset
  95.         begin
  96.                 dma_on <= 1'b0;
  97.         end
  98.         else // posedge clk
  99.         begin
  100.                 // dma_on control
  101.                 if( module_select && write_strobe && (regsel==_CST) )
  102.                         dma_on <= din[7];
  103.  
  104.                 // dma_addr control
  105.                 if( dma_ack && dma_on )
  106.                         dma_addr <= dma_addr + 21'd1; // increment on beginning of DMA transfer
  107.                 else if( module_select && write_strobe )
  108.                 begin
  109.                         if( regsel==_HAD )
  110.                                 dma_addr[20:16] <= din[4:0];
  111.                         else if( regsel==_MAD )
  112.                                 dma_addr[15:8]  <= din[7:0];
  113.                         else if( regsel==_LAD )
  114.                                 dma_addr[7:0]   <= din[7:0];
  115.                 end
  116.         end
  117.  
  118.  
  119.  
  120.         // syncing in zxdmaread and zxdmawrite, making _begin and _end pulses
  121.         always @(posedge clk)
  122.         begin
  123.                 zxdmaread_sync[2:0]  <= { zxdmaread_sync[1:0],  zxdmaread  };
  124.                 zxdmawrite_sync[2:0] <= { zxdmawrite_sync[1:0], zxdmawrite };
  125.         end
  126.  
  127.         always @*
  128.         begin
  129.                 zxread_begin  <= zxdmaread_sync[1]  && (!zxdmaread_sync[2]);
  130.                 zxwrite_begin <= zxdmawrite_sync[1] && (!zxdmawrite_sync[2]);
  131.  
  132.                 zxread_end  <= (!zxdmaread_sync[1])  && zxdmaread_sync[2];
  133.                 zxwrite_end <= (!zxdmawrite_sync[1]) && zxdmawrite_sync[2];
  134.         end
  135.  
  136.  
  137.  
  138.         // temporary: dma_rnw always at read state
  139.         always @* dma_rnw = 1'b1;
  140.  
  141.  
  142.  
  143.         // FSM for wait_enable
  144.  
  145.         localparam waenaIDLE = 0;
  146.         localparam waenaWAIT = 1;
  147.  
  148.         always @(posedge clk, negedge rst_n)
  149.         if( !rst_n )
  150.                 waena_state <= waenaIDLE;
  151.         else if( !dma_on )
  152.                 waena_state <= waenaIDLE;
  153.         else
  154.                 waena_state <= waena_next;
  155.  
  156.         always @*
  157.         case( waena_state )
  158.                 waenaIDLE:
  159.                         if( zxread_end && (!dma_end) )
  160.                                 waena_next <= waenaWAIT;
  161.                         else
  162.                                 waena_next <= waenaIDLE;
  163.                 waenaWAIT:
  164.                         if( dma_end )
  165.                                 waena_next <= waenaIDLE;
  166.                         else
  167.                                 waena_next <= waenaWAIT;
  168.         endcase
  169.  
  170.         always @(posedge clk, negedge rst_n)
  171.         if( !rst_n )
  172.                 wait_ena <= 1'b0;
  173.         else if( !dma_on )
  174.                 wait_ena <= 1'b0;
  175.         else
  176.         case( waena_next )
  177.                 waenaIDLE:
  178.                         wait_ena <= 1'b0;
  179.                 waenaWAIT:
  180.                         wait_ena <= 1'b1;
  181.         endcase
  182.  
  183.  
  184.  
  185.         // FSM for dma request
  186.  
  187.         localparam dmarqIDLE = 0;
  188.         localparam dmarqREQ1 = 1;
  189.         localparam dmarqREQ2 = 2;
  190.  
  191.         always @(posedge clk, negedge rst_n)
  192.         if( !rst_n )
  193.                 dmarq_state <= dmarqIDLE;
  194.         else if( !dma_on )
  195.                 dmarq_state <= dmarqIDLE;
  196.         else
  197.                 dmarq_state <= dmarq_next;
  198.  
  199.         always @*
  200.         case( dmarq_state )
  201.                 dmarqIDLE:
  202.                         if( zxread_begin )
  203.                                 dmarq_next <= dmarqREQ1;
  204.                         else
  205.                                 dmarq_next <= dmarqIDLE;
  206.                 dmarqREQ1:
  207.                         if( dma_ack && (!zxread_begin) )
  208.                                 dmarq_next <= dmarqIDLE;
  209.                         else if( (!dma_ack) && zxread_begin )
  210.                                 dmarq_next <= dmarqREQ2;
  211.                         else // nothing or both zxread_begin and dma_ack
  212.                                 dmarq_next <= dmarqREQ1;
  213.                 dmarqREQ2:
  214.                         if( dma_ack )
  215.                                 dmarq_next <= dmarqREQ1;
  216.                         else
  217.                                 dmarq_next <= dmarqREQ2;
  218.         endcase
  219.  
  220.         always @(posedge clk, negedge rst_n)
  221.         if( !rst_n )
  222.                 dma_prereq <= 1'b0;
  223.         else
  224.         case( dmarq_next )
  225.                 dmarqIDLE:
  226.                         dma_prereq <= 1'b0;
  227.                 dmarqREQ1:
  228.                         dma_prereq <= 1'b1;
  229.                 dmarqREQ2:
  230.                         dma_prereq <= 1'b1;
  231.         endcase
  232.  
  233.         always @* dma_req <= (dma_prereq | zxread_begin) & dma_on;
  234.  
  235.  
  236.         // pick up data from DMA
  237.  
  238.         always @(posedge clk) if( dma_end ) dma_rd_temp <= dma_rd;
  239.  
  240.         always @(posedge clk)
  241.         begin
  242.                 if( zxread_end && dma_end ) // simultaneously coming zxread_end and dma_end: get data directly from dma
  243.                         dma_rd_data <= dma_rd;
  244.                 else if( dma_end && wait_ena ) // dma_end was after zxread_end: get data directly from dma
  245.                         dma_rd_data <= dma_rd;
  246.                 else if( zxread_end )
  247.                         dma_rd_data <= dma_rd_temp; // we can always corrupt dma_rd_data at zxread_end strobe, even if we
  248.                                                     // will overwrite it with newer arrived data later
  249.         end
  250.  
  251.  
  252. endmodule
  253.  
  254.