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. module dma_zx(
  10.  
  11.         input clk,
  12.         input rst_n,
  13.  
  14.  
  15.         // ZXBUS-related signals
  16.  
  17.         input zxdmaread,  // async strobes made directly from zxbus signals
  18.         input zxdmawrite, //
  19.  
  20.         input      [7:0] dma_wr_data, // data written by ZXBUS here
  21.         output reg [7:0] dma_rd_data, // to be output to the ZXBUS from here
  22.  
  23.         output reg wait_ena, // for zxbus module, to stop temporarily ZX Z80
  24.  
  25.  
  26.  
  27.  
  28.         // different global & control signals
  29.  
  30.         output reg dma_on,
  31.  
  32.  
  33.         // signals from ports.v
  34.  
  35.         input      [7:0] din,  // input and output from ports.v
  36.         output reg [7:0] dout,
  37.  
  38.         input module_select, // =1 - module selected for read-write operations from ports.v
  39.         input write_strobe, // one-cycle positive write strobe - writes to the selected registers from din
  40.  
  41.         input [1:0] regsel, // 2'b00 - high address, 2'b01 - middle address, 2'b10 - low address, 2'b11 - control register
  42.  
  43.  
  44.         // signals for DMA controller
  45.  
  46.       output reg [20:0] dma_addr,
  47.       output reg  [7:0] dma_wd,
  48.       input       [7:0] dma_rd,
  49.       output reg        dma_rnw,
  50.  
  51.       output reg dma_req,
  52.       input      dma_ack,
  53.       input      dma_end
  54.  
  55. );
  56.  
  57.         reg [7:0] dma_rd_temp; // temporarily buffered read data from DMA module
  58.  
  59.         reg zxdmaread_sync;  // syncing appropriate zxbus signals - stage 1
  60.         reg zxdmawrite_sync; //
  61.  
  62.         reg [1:0] zxdmaread_strobe;  // syncing zxbus signals: stage 2 and change detection
  63.         reg [1:0] zxdmawrite_strobe; //
  64.  
  65.  
  66.         reg zxread_beg, zxwrite_beg; // 1-cycle positive pulses based on synced in zxdmaread and zxdmawrite
  67.         reg zxread_end, zxwrite_end; //
  68.  
  69.  
  70.         reg dma_prireq; // primary dma request
  71.         reg dma_prirnw; // primary rnw for dma request
  72.  
  73.         reg waitena_reg; // registered wait_ena
  74.         reg waitena_fwd; // forwarded early wait_ena: output wait_ena made from both this signals
  75.  
  76.  
  77.         reg [3:0] zdma_state, zdma_next; // main FSM for zx-dma
  78.  
  79.         reg [1:0] dmarq_state,dmarq_next; // DMA req gen
  80.  
  81.  
  82.  
  83.         localparam _HAD = 2'b00; // high address
  84.         localparam _MAD = 2'b01; // mid address
  85.         localparam _LAD = 2'b10; // low address
  86.         localparam _CST = 2'b11; // control and status
  87.  
  88.         // control dout bus
  89.         always @*
  90.         case( regsel[1:0] )
  91.                 _HAD: dout = { 3'b000, dma_addr[20:16] };
  92.                 _MAD: dout = dma_addr[15:8];
  93.                 _LAD: dout = dma_addr[7:0];
  94.                 _CST: dout = { dma_on, 7'bXXXXXXX };
  95.         endcase
  96.  
  97.         // ports.v write access & dma_addr control
  98.         always @(posedge clk, negedge rst_n)
  99.         if( !rst_n ) // async reset
  100.         begin
  101.                 dma_on <= 1'b0;
  102.         end
  103.         else // posedge clk
  104.         begin
  105.                 // dma_on control
  106.                 if( module_select && write_strobe && (regsel==_CST) )
  107.                         dma_on <= din[7];
  108.  
  109.                 // dma_addr control
  110.                 if( dma_ack && dma_on )
  111.                         dma_addr <= dma_addr + 21'd1; // increment on beginning of DMA transfer
  112.                 else if( module_select && write_strobe )
  113.                 begin
  114.                         if( regsel==_HAD )
  115.                                 dma_addr[20:16] <= din[4:0];
  116.                         else if( regsel==_MAD )
  117.                                 dma_addr[15:8]  <= din[7:0];
  118.                         else if( regsel==_LAD )
  119.                                 dma_addr[7:0]   <= din[7:0];
  120.                 end
  121.         end
  122.  
  123.  
  124.  
  125.         // syncing in zxdmaread and zxdmawrite, making _begin and _end pulses
  126.         always @(negedge clk) // forcing signals syncing in!
  127.         begin
  128.                 zxdmaread_sync  <= zxdmaread;
  129.                 zxdmawrite_sync <= zxdmawrite;
  130.         end
  131.  
  132.         always @(posedge clk)
  133.         begin
  134.                 zxdmaread_strobe[1:0]  <= { zxdmaread_strobe[0],  zxdmaread_sync  };
  135.                 zxdmawrite_strobe[1:0] <= { zxdmawrite_strobe[0], zxdmawrite_sync };
  136.         end
  137.  
  138.         always @*
  139.         begin
  140.                 zxread_beg  <= zxdmaread_strobe[0]  && (!zxdmaread_strobe[1]);
  141.                 zxwrite_beg <= zxdmawrite_strobe[0] && (!zxdmawrite_strobe[1]);
  142.  
  143.                 zxread_end  <= (!zxdmaread_strobe[0])  && zxdmaread_strobe[1];
  144.                 zxwrite_end <= (!zxdmawrite_strobe[0]) && zxdmawrite_strobe[1];
  145.         end
  146.  
  147.  
  148.  
  149.  
  150.  
  151.         // main FSM for zx-dma control
  152.  
  153.         localparam zdmaIDLE       = 0;
  154.         localparam zdmaREAD       = 1; // read cycle has begun
  155.         localparam zdmaENDREAD1   = 2; // end read cycle: wait for zxread_end
  156.         localparam zdmaENDREAD2   = 3; // end read cycle: data from dma_rd_temp to dma_rd_data
  157.         localparam zdmaSTARTWAIT  = 4; // assert wait_ena
  158.         localparam zdmaFWDNOWAIT1 = 5; // forward data from dma_rd to dma_rd_data, negate wait_ena, if any, go to zdmaREAD if zxread_beg
  159.         localparam zdmaFWDNOWAIT2 = 6; // forward data from dma_rd to dma_rd_data, negate wait_ena, if any, go to zdmaREAD always
  160.         localparam zdmaWAITED     = 7; // waited until dma_end
  161.         localparam zdmaWRITEWAIT  = 8; // write wait
  162.  
  163.         always @(posedge clk, negedge rst_n)
  164.         if( !rst_n )
  165.                 zdma_state <= zdmaIDLE;
  166.         else if( !dma_on )
  167.                 zdma_state <= zdmaIDLE;
  168.         else
  169.                 zdma_state <= zdma_next;
  170.  
  171.  
  172.         always @*
  173.         begin
  174.  
  175.                 case( zdma_state )
  176.  
  177.                 zdmaIDLE:
  178.                         if( zxread_beg )
  179.                                 zdma_next = zdmaREAD;
  180.                         else if( zxwrite_end )
  181.                                 zdma_next = zdmaWRITEWAIT;
  182.                         else
  183.                                 zdma_next = zdmaIDLE;
  184.  
  185.                 zdmaREAD:
  186.                         if( dma_end && zxread_end ) // both signal simultaneously
  187.                                 zdma_next = zdmaFWDNOWAIT1;
  188.                         else if( zxread_end )
  189.                                 zdma_next = zdmaSTARTWAIT;
  190.                         else if( dma_end )
  191.                                 zdma_next = zdmaENDREAD1;
  192.                         else
  193.                                 zdma_next = zdmaREAD;
  194.  
  195.                 zdmaENDREAD1:
  196.                         if( zxread_end )
  197.                                 zdma_next = zdmaENDREAD2;
  198.                         else
  199.                                 zdma_next = zdmaENDREAD1;
  200.  
  201.                 zdmaENDREAD2:
  202.                         if( zxread_beg )
  203.                                 zdma_next = zdmaREAD;
  204.                         else
  205.                                 zdma_next = zdmaIDLE;
  206.  
  207.                 zdmaSTARTWAIT:
  208.                         if( dma_end && zxread_beg )
  209.                                 zdma_next = zdmaFWDNOWAIT2;
  210.                         else if( dma_end )
  211.                                 zdma_next = zdmaFWDNOWAIT1;
  212.                         else if( zxread_beg )
  213.                                 zdma_next = zdmaWAITED;
  214.                         else if( zxwrite_beg ) // to prevent dead locks!
  215.                                 zdma_next = zdmaIDLE;
  216.                         else
  217.                                 zdma_next = zdmaSTARTWAIT;
  218.  
  219.                 zdmaFWDNOWAIT1:
  220.                         if( zxread_beg )
  221.                                 zdma_next = zdmaREAD;
  222.                         else
  223.                                 zdma_next = zdmaIDLE;
  224.  
  225.                 zdmaFWDNOWAIT2:
  226.                         zdma_next = zdmaREAD;
  227.  
  228.                 zdmaWAITED:
  229.                         if( dma_end )
  230.                                 zdma_next = zdmaFWDNOWAIT2;
  231.                         else
  232.                                 zdma_next = zdmaWAITED;
  233.  
  234.  
  235.                 zdmaWRITEWAIT:
  236.                         if( dma_ack )
  237.                                 zdma_next = zdmaIDLE;
  238.                         else if( zxread_beg )
  239.                                 zdma_next = zdmaIDLE;
  240.                         else
  241.                                 zdma_next = zdmaWRITEWAIT;
  242.  
  243.  
  244.                 endcase
  245.         end
  246.  
  247.         //control read data forwarding
  248.         always @(posedge clk)
  249.                 if( dma_end ) dma_rd_temp <= dma_rd;
  250.  
  251.         always @(posedge clk)
  252.                 case( zdma_next )
  253.                         zdmaENDREAD2:
  254.                                 dma_rd_data <= dma_rd_temp;
  255.                         zdmaFWDNOWAIT1:
  256.                                 dma_rd_data <= dma_rd;
  257.                         zdmaFWDNOWAIT2:
  258.                                 dma_rd_data <= dma_rd;
  259.                 endcase
  260.  
  261.  
  262.         // control wait_ena
  263.         always @(posedge clk, negedge rst_n)
  264.                 if( !rst_n )
  265.                         waitena_reg <= 1'b0;
  266.                 else if( !dma_on )
  267.                         waitena_reg <= 1'b0;
  268.                 else if( (zdma_next == zdmaSTARTWAIT) || (zdma_next == zdmaWRITEWAIT) )
  269.                         waitena_reg <= 1'b1;
  270.                 else if( (zdma_state == zdmaFWDNOWAIT1) || (zdma_state == zdmaFWDNOWAIT2) || (zdma_state == zdmaIDLE) )
  271.                         waitena_reg <= 1'b0;
  272.  
  273.         always @*
  274.                 waitena_fwd = ( (zdma_state==zdmaREAD) && zxread_end && (!dma_end) ) || ( (zdma_state==zdmaIDLE) && zxwrite_end );
  275.  
  276.         always @*
  277.                 wait_ena = waitena_reg | waitena_fwd;
  278.  
  279.  
  280.  
  281.  
  282.  
  283.         // FSM for dma requests
  284.  
  285.         localparam dmarqIDLE   = 0;
  286.         localparam dmarqRDREQ1 = 1;
  287.         localparam dmarqRDREQ2 = 2;
  288.         localparam dmarqWRREQ  = 3;
  289.  
  290.         always @(posedge clk, negedge rst_n)
  291.         if( !rst_n )
  292.                 dmarq_state <= dmarqIDLE;
  293.         else if( !dma_on )
  294.                 dmarq_state <= dmarqIDLE;
  295.         else
  296.                 dmarq_state <= dmarq_next;
  297.  
  298.         always @*
  299.         case( dmarq_state )
  300.  
  301.                 dmarqIDLE:
  302.                         if( zxread_beg )
  303.                                 dmarq_next <= dmarqRDREQ1;
  304.                         else if( zxwrite_end )
  305.                                 dmarq_next <= dmarqWRREQ;
  306.                         else
  307.                                 dmarq_next <= dmarqIDLE;
  308.  
  309.                 dmarqRDREQ1:
  310.                         if( zxwrite_beg )
  311.                                 dmarq_next <= dmarqIDLE; // to prevent dead ends!
  312.                         else if( dma_ack && (!zxread_beg) )
  313.                                 dmarq_next <= dmarqIDLE;
  314.                         else if( (!dma_ack) && zxread_beg )
  315.                                 dmarq_next <= dmarqRDREQ2;
  316.                         else // nothing or both zxread_beg and dma_ack
  317.                                 dmarq_next <= dmarqRDREQ1;
  318.  
  319.                 dmarqRDREQ2:
  320.                         if( dma_ack )
  321.                                 dmarq_next <= dmarqRDREQ1;
  322.                         else
  323.                                 dmarq_next <= dmarqRDREQ2;
  324.  
  325.                 dmarqWRREQ:
  326.                         if( dma_ack || zxread_beg ) //zxread_beg - to prevent dead end!
  327.                                 dmarq_next <= dmarqIDLE;
  328.                         else
  329.                                 dmarq_next <= dmarqWRREQ;
  330.         endcase
  331.  
  332.         always @(posedge clk, negedge rst_n)
  333.         if( !rst_n )
  334.                 dma_prireq <= 1'b0;
  335.         else
  336.         case( dmarq_next )
  337.  
  338.                 dmarqIDLE:
  339.                 begin
  340.                         dma_prireq <= 1'b0;
  341.                 end
  342.  
  343.                 dmarqRDREQ1:
  344.                 begin
  345.                         dma_prireq <= 1'b1;
  346.                         dma_prirnw <= 1'b1;
  347.                 end
  348.  
  349.                 dmarqRDREQ2:
  350.                 begin
  351.                         // nothing
  352.                 end
  353.  
  354.                 dmarqWRREQ:
  355.                 begin
  356.                         dma_prireq <= 1'b1;
  357.                         dma_prirnw <= 1'b0;
  358.                 end
  359.  
  360.         endcase
  361.  
  362.         always @* dma_req <= (dma_prireq | zxread_beg | zxwrite_end ) & dma_on;
  363.  
  364.         always @*
  365.                 if( zxread_beg )
  366.                         dma_rnw <= 1'b1;
  367.                 else if( zxwrite_end )
  368.                         dma_rnw <= 1'b0;
  369.                 else
  370.                         dma_rnw <= dma_prirnw;
  371.  
  372.         always @* dma_wd <= dma_wr_data;
  373.  
  374.  
  375. endmodule
  376.  
  377.