- // part of NeoGS project 
- // 
- // (c) NedoPC 2007-2009 
- // 
- // ZX dma controller 
- // 
- // includes dma address regs, dma control reg 
- // 
- // CURRENTLY ONLY READ ON ZXBUS SIDE FROM NGS MEM, error in WAIT generation! zx_dma2.v - further development 
-   
- module dma_zx( 
-   
-         input clk, 
-         input rst_n, 
-   
-   
-         // ZXBUS-related signals 
-   
-         input zxdmaread,  // async strobes made directly from zxbus signals 
-         input zxdmawrite, // 
-   
-         input      [7:0] dma_wr_data, // data written by ZXBUS here 
-         output reg [7:0] dma_rd_data, // to be output to the ZXBUS from here 
-   
-         output reg wait_ena, // for zxbus module, to stop temporarily ZX Z80 
-   
-   
-   
-   
-         // different global & control signals 
-   
-         output reg dma_on, 
-   
-   
-         // signals from ports.v 
-   
-         input      [7:0] din,  // input and output from ports.v 
-         output reg [7:0] dout, 
-   
-         input module_select, // =1 - module selected for read-write operations from ports.v 
-         input write_strobe, // one-cycle positive write strobe - writes to the selected registers from din 
-   
-         input [1:0] regsel, // 2'b00 - high address, 2'b01 - middle address, 2'b10 - low address, 2'b11 - control register 
-   
-   
-         // signals for DMA controller 
-   
-       output reg [20:0] dma_addr, 
-       output reg  [7:0] dma_wd, 
-       input       [7:0] dma_rd, 
-       output reg        dma_rnw, 
-   
-       output reg dma_req, 
-       input      dma_ack, 
-       input      dma_end 
-   
- ); 
-   
-         reg [7:0] dma_rd_temp; // temporarily buffered read data from DMA module 
-   
-         reg [2:0] zxdmaread_sync;  // syncing appropriate zxbus signals 
-         reg [2:0] zxdmawrite_sync; 
-   
-         reg zxread_begin, zxwrite_begin; // 1-cycle positive pulses based on synced in zxdmaread and zxdmawrite 
-         reg zxread_end,   zxwrite_end;   // 
-   
-   
-         reg dma_prereq; // to help assert dma_req one cycle earlier 
-   
-   
-   
-         reg [1:0] waena_state,waena_next; // and wait_ena generation 
-   
-         reg [1:0] dmarq_state,dmarq_next; // DMA req gen 
-   
-   
-   
-         localparam _HAD = 2'b00; // high address 
-         localparam _MAD = 2'b01; // mid address 
-         localparam _LAD = 2'b10; // low address 
-         localparam _CST = 2'b11; // control and status 
-   
-         // control dout bus 
-         always @* 
-         case( regsel[1:0] ) 
-                 _HAD: dout = { 3'b000, dma_addr[20:16] }; 
-                 _MAD: dout = dma_addr[15:8]; 
-                 _LAD: dout = dma_addr[7:0]; 
-                 _CST: dout = { dma_on, 7'bXXXXXXX }; 
-         endcase 
-   
-         // ports.v write access & dma_addr control 
-         always @(posedge clk, negedge rst_n) 
-         if( !rst_n ) // async reset 
-         begin 
-                 dma_on <= 1'b0; 
-         end 
-         else // posedge clk 
-         begin 
-                 // dma_on control 
-                 if( module_select && write_strobe && (regsel==_CST) ) 
-                         dma_on <= din[7]; 
-   
-                 // dma_addr control 
-                 if( dma_ack && dma_on ) 
-                         dma_addr <= dma_addr + 21'd1; // increment on beginning of DMA transfer 
-                 else if( module_select && write_strobe ) 
-                 begin 
-                         if( regsel==_HAD ) 
-                                 dma_addr[20:16] <= din[4:0]; 
-                         else if( regsel==_MAD ) 
-                                 dma_addr[15:8]  <= din[7:0]; 
-                         else if( regsel==_LAD ) 
-                                 dma_addr[7:0]   <= din[7:0]; 
-                 end 
-         end 
-   
-   
-   
-         // syncing in zxdmaread and zxdmawrite, making _begin and _end pulses 
-         always @(posedge clk) 
-         begin 
-                 zxdmaread_sync[2:0]  <= { zxdmaread_sync[1:0],  zxdmaread  }; 
-                 zxdmawrite_sync[2:0] <= { zxdmawrite_sync[1:0], zxdmawrite }; 
-         end 
-   
-         always @* 
-         begin 
-                 zxread_begin  <= zxdmaread_sync[1]  && (!zxdmaread_sync[2]); 
-                 zxwrite_begin <= zxdmawrite_sync[1] && (!zxdmawrite_sync[2]); 
-   
-                 zxread_end  <= (!zxdmaread_sync[1])  && zxdmaread_sync[2]; 
-                 zxwrite_end <= (!zxdmawrite_sync[1]) && zxdmawrite_sync[2]; 
-         end 
-   
-   
-   
-         // temporary: dma_rnw always at read state 
-         always @* dma_rnw = 1'b1; 
-   
-   
-   
-         // FSM for wait_enable 
-   
-         localparam waenaIDLE = 0; 
-         localparam waenaWAIT = 1; 
-   
-         always @(posedge clk, negedge rst_n) 
-         if( !rst_n ) 
-                 waena_state <= waenaIDLE; 
-         else if( !dma_on ) 
-                 waena_state <= waenaIDLE; 
-         else 
-                 waena_state <= waena_next; 
-   
-         always @* 
-         case( waena_state ) 
-                 waenaIDLE: 
-                         if( zxread_end && (!dma_end) ) 
-                                 waena_next <= waenaWAIT; 
-                         else 
-                                 waena_next <= waenaIDLE; 
-                 waenaWAIT: 
-                         if( dma_end ) 
-                                 waena_next <= waenaIDLE; 
-                         else 
-                                 waena_next <= waenaWAIT; 
-         endcase 
-   
-         always @(posedge clk, negedge rst_n) 
-         if( !rst_n ) 
-                 wait_ena <= 1'b0; 
-         else if( !dma_on ) 
-                 wait_ena <= 1'b0; 
-         else 
-         case( waena_next ) 
-                 waenaIDLE: 
-                         wait_ena <= 1'b0; 
-                 waenaWAIT: 
-                         wait_ena <= 1'b1; 
-         endcase 
-   
-   
-   
-         // FSM for dma request 
-   
-         localparam dmarqIDLE = 0; 
-         localparam dmarqREQ1 = 1; 
-         localparam dmarqREQ2 = 2; 
-   
-         always @(posedge clk, negedge rst_n) 
-         if( !rst_n ) 
-                 dmarq_state <= dmarqIDLE; 
-         else if( !dma_on ) 
-                 dmarq_state <= dmarqIDLE; 
-         else 
-                 dmarq_state <= dmarq_next; 
-   
-         always @* 
-         case( dmarq_state ) 
-                 dmarqIDLE: 
-                         if( zxread_begin ) 
-                                 dmarq_next <= dmarqREQ1; 
-                         else 
-                                 dmarq_next <= dmarqIDLE; 
-                 dmarqREQ1: 
-                         if( dma_ack && (!zxread_begin) ) 
-                                 dmarq_next <= dmarqIDLE; 
-                         else if( (!dma_ack) && zxread_begin ) 
-                                 dmarq_next <= dmarqREQ2; 
-                         else // nothing or both zxread_begin and dma_ack 
-                                 dmarq_next <= dmarqREQ1; 
-                 dmarqREQ2: 
-                         if( dma_ack ) 
-                                 dmarq_next <= dmarqREQ1; 
-                         else 
-                                 dmarq_next <= dmarqREQ2; 
-         endcase 
-   
-         always @(posedge clk, negedge rst_n) 
-         if( !rst_n ) 
-                 dma_prereq <= 1'b0; 
-         else 
-         case( dmarq_next ) 
-                 dmarqIDLE: 
-                         dma_prereq <= 1'b0; 
-                 dmarqREQ1: 
-                         dma_prereq <= 1'b1; 
-                 dmarqREQ2: 
-                         dma_prereq <= 1'b1; 
-         endcase 
-   
-         always @* dma_req <= (dma_prereq | zxread_begin) & dma_on; 
-   
-   
-         // pick up data from DMA 
-   
-         always @(posedge clk) if( dma_end ) dma_rd_temp <= dma_rd; 
-   
-         always @(posedge clk) 
-         begin 
-                 if( zxread_end && dma_end ) // simultaneously coming zxread_end and dma_end: get data directly from dma 
-                         dma_rd_data <= dma_rd; 
-                 else if( dma_end && wait_ena ) // dma_end was after zxread_end: get data directly from dma 
-                         dma_rd_data <= dma_rd; 
-                 else if( zxread_end ) 
-                         dma_rd_data <= dma_rd_temp; // we can always corrupt dma_rd_data at zxread_end strobe, even if we 
-                                                     // will overwrite it with newer arrived data later 
-         end 
-   
-   
- endmodule 
-   
-