Subversion Repositories ngs

Rev

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

  1. // part of NeoGS project (c) 2007-2008 NedoPC
  2. //
  3. // ZXBUS interface module
  4. // Features:
  5. // I. provides IORQGE generation via zxblkiorq_n output on addresses $xxB3, $xxBB and $xx33
  6. // II.  Asynchronously outs data_reg_in or data_bit and command bit to zxbus
  7. // III. Asynchronouly latches in data_reg_out and command_reg_out from zxbus
  8. // IV.  Synchronously updates data_bit and command_bit according to zxbus activity,
  9. //       or sets it to *_bit_in value when *_bit_wr is 1
  10. // V.   Generates nmi_n negative 8-clock pulse when $010xxxxx is written to $xx33 port.
  11. //      Initiates internal reset when $100xxxxx is written to $xx33 port
  12. //      Toggles LED when $001xxxxx is written
  13. //
  14. //
  15. // TODO: add DMA functionality
  16.  
  17. module zxbus(
  18.  
  19.         zxid, // zxbus DATA BUS in/out [7:0]
  20.         zxa, // zxbus ADDRESS 7-0 in [7:0]
  21.         zxa14,zxa15, // zxbus ADDRESS 14,15
  22.         zxiorq_n,zxmreq_n, // zxbus /IORQ,/MREQ
  23.         zxrd_n,zxwr_n, // zxbus /RD, /WR
  24.         zxcsrom_n, // zxbus /CSROM
  25.         zxblkiorq_n, // active low - signals to generate IORQGE
  26.         zxblkrom_n, // active low - signals to block onboard zx ROM
  27.         zxgenwait_n, // active low - signals to generate /WAIT to ZXBUS
  28.         zxbusin, // controls 74hct245 buffer direction (1 - input from bus, 0 - output to zx)
  29.         zxbusena_n, // 74hct245 buffer enable signal
  30.  
  31.         command_reg_out, // output data of command register (asynchronous)
  32.  
  33.         data_reg_out, // output data of data register (asynchronous)
  34.         data_reg_in, // input data of data register (asynchronous)
  35.  
  36.         data_bit, // data bit out (synchronous to cpu_clock)
  37.         command_bit, // command bit out (synchronous to cpu_clock)
  38.  
  39.         data_bit_in, // input data to be written to data bit
  40.         command_bit_in, // input data to be written to command bit
  41.  
  42.         data_bit_wr, // write strobe (positive), which writes data from data_bit_in to data_bit (sync to cpu_clock)
  43.         command_bit_wr, // write strobe (positive), which writes data from command_bit_in to command_bit (sync to cpu_clock)
  44.  
  45.         rst_from_zx_n, // reset out to NGS z80 indicating board must be reset
  46.         nmi_n, // nmi out to NGS z80 (2^NMI_CNT_SIZE cpu_clock periods low pulse) - synchronous!
  47.  
  48.         led_toggle,
  49.  
  50.         rst_n, // chip-wide reset input (some critical init)
  51.  
  52.         cpu_clock // NGS Z80 CPU clock in (clk_fpga on schematics)
  53.  
  54. );
  55.  
  56.         parameter NMI_CNT_SIZE = 2;
  57.  
  58.         localparam GSCOM  = 8'hBB;
  59.         localparam GSSTAT = GSCOM;
  60.         localparam GSDAT  = 8'hB3;
  61.         localparam GSCTR  = 8'h33;
  62.  
  63. // INPUTS/OUTPUTS of module
  64.  
  65.         inout reg [7:0] zxid;
  66.  
  67.         input [7:0] zxa;
  68.         input zxa14,zxa15;
  69.         input zxiorq_n,zxmreq_n;
  70.         input zxrd_n,zxwr_n;
  71.  
  72.         input zxcsrom_n;
  73.  
  74.         output reg zxblkiorq_n,zxblkrom_n,zxbusin,zxbusena_n,zxgenwait_n;
  75.  
  76.         output reg [7:0] command_reg_out;
  77.  
  78.         output reg [7:0] data_reg_out;
  79.  
  80.         input [7:0] data_reg_in;
  81.  
  82.         output reg data_bit;
  83.  
  84.         output reg command_bit;
  85.  
  86.         input data_bit_in;
  87.         input command_bit_in;
  88.  
  89.         input data_bit_wr;
  90.         input command_bit_wr;
  91.  
  92.         output reg rst_from_zx_n;
  93.  
  94.         output reg nmi_n;
  95.  
  96.         output reg led_toggle;
  97.  
  98.         input cpu_clock;
  99.  
  100.         input rst_n;
  101.  
  102. // internal regs and wires
  103.  
  104.         wire [7:0] dbin; // input data from zx data bus
  105.         reg [7:0] dbout; // output to the zx data bus
  106.  
  107.         wire [7:0] zxlowaddr; // low address on ZX address bus
  108.         wire zxdataport; // =1 when data port address selected ($B3)
  109.         wire zxcommport; // =1 when command port address selected ($BB)
  110.         wire zxrstport;  // =1 when reset/nmi port address selected ($33)
  111.  
  112.         wire zxiord_n; // = iorq_n | rd_n
  113.         wire zxiowr_n; // = iorq_n | wr_n
  114.  
  115.         reg [2:0] rddataport; // for                    data_bit
  116.         reg [2:0] wrdataport; //    synchronous       of        and
  117.         reg [2:0] wrcommport; //               control             command_bit
  118.  
  119.         reg async_rst_toggle; // asynchronous toggles on writes to port $33
  120.         reg async_nmi_toggle;
  121.         reg async_led_toggle;
  122.  
  123.         reg [2:0] sync_rst_toggle; // syncing toggles in and detect edges
  124.         reg [2:0] sync_nmi_toggle; // generate z80res or nmi on every edge
  125.         reg [2:0] sync_led_toggle; // LED toggle on every edge
  126.  
  127.         reg prezxrst1,prezxrst2; // reset out (rst_from_zx_n) must have some negation delay when rst_n asserts
  128.  
  129.         reg [NMI_CNT_SIZE:0] nmi_counter; // counter to make 2^NMI_CNT_SIZE cpu_clock's pulses, plus stopbit
  130.  
  131. // actual code
  132. //---------------------------------------------------------------------------
  133.  
  134. // zx data bus switcher
  135.  
  136.         assign dbin[7:0] = zxid;
  137.  
  138.         always @*
  139.         begin
  140.                 if( zxbusin == 1'b1 )
  141.                 begin
  142.                         zxid <= 8'bZZZZZZZZ;
  143.                 end
  144.                 else // zxbusin==0
  145.                 begin
  146.                         zxid <= dbout[7:0];
  147.                 end
  148.         end
  149.         // +
  150.  
  151.  
  152. // zx address decoder, IORQGE generator
  153.  
  154.         assign zxdataport = (zxa == GSDAT); // =1 when $B3
  155.         assign zxcommport = (zxa == GSCOM); // =1 when $BB
  156.         assign zxrstport  = (zxa == GSCTR); // =1 when $33
  157.  
  158.         always @*
  159.         begin
  160.                 if( zxdataport || zxcommport || zxrstport ) // address if any of ports is on bus
  161.                         zxblkiorq_n <= 1'b0;                  // generate IORQGE!
  162.                 else
  163.                         zxblkiorq_n <= 1'b1;
  164.         end
  165. // +
  166.  
  167.  
  168. // stubs for possible dma mode
  169.  
  170.         always @*
  171.         begin
  172.                 zxblkrom_n <= 1'b1;
  173.                 zxgenwait_n <= 1'b1;
  174.         end
  175.  
  176.  
  177. // I/O RD and WR strobes
  178.  
  179.         assign zxiord_n = zxiorq_n | zxrd_n;
  180.         assign zxiowr_n = zxiorq_n | zxwr_n;
  181. // +
  182.  
  183.  
  184. // write from zxbus to the data register
  185.  
  186.         always @(posedge zxiowr_n)
  187.         begin
  188.                 if( zxdataport )
  189.                 begin
  190.                         data_reg_out <= dbin;
  191.                 end
  192.         end
  193.         // +
  194.  
  195. // write from zxbus to the command register
  196.  
  197.         always @(posedge zxiowr_n)
  198.         begin
  199.                 if( zxcommport )
  200.                 begin
  201.                         command_reg_out <= dbin;
  202.                 end
  203.         end
  204.         // +
  205.  
  206.  
  207. // read to zxbus some registers
  208.  
  209.         always @*
  210.         begin
  211.                 if( (!zxiord_n) && ( zxdataport || zxcommport ) )
  212.                         zxbusin <= 1'b0;
  213.                 else
  214.                         zxbusin <= 1'b1;
  215.  
  216.                 if( ( (!zxiowr_n) || (!zxiord_n) ) && ( zxdataport || zxcommport || zxrstport ) )
  217.                         zxbusena_n <= 1'b0;
  218.                 else
  219.                         zxbusena_n <= 1'b1;
  220.         end
  221.  
  222.         always @*
  223.         begin
  224.                 case( {zxdataport,zxcommport} )
  225.                         2'b10:   dbout <= data_reg_in;
  226.                         2'b01:   dbout <= { data_bit, 6'bXXXXXX, command_bit };
  227.                         default: dbout <= 8'bXXXXXXXX;
  228.                 endcase
  229.         end
  230.         // +
  231.  
  232.  
  233.  
  234.  
  235. // SYNCHRONOUS PART
  236. // ---------------------------------------------------
  237.  
  238. // synchronous control of port writes and reads
  239.  
  240.         always @(posedge cpu_clock) // sync in read and write states
  241.         begin
  242.                 rddataport[2:0] <= { rddataport[1:0], zxdataport&(~zxiord_n) };
  243.                 wrdataport[2:0] <= { wrdataport[1:0], zxdataport&(~zxiowr_n) };
  244.                 wrcommport[2:0] <= { wrcommport[1:0], zxcommport&(~zxiowr_n) };
  245.         end
  246.  
  247.         // data_bit
  248.         always @(posedge cpu_clock)
  249.         begin
  250.                 if( rddataport[2:1]==2'b10 )
  251.                 begin
  252.                         data_bit <= 1'b0; // clear on data port reading by ZX (after end of cycle)
  253.                 end
  254.                 else if( wrdataport[2:1]==2'b10 )
  255.                 begin
  256.                         data_bit <= 1'b1; // set on data port writing by ZX
  257.                 end
  258.                 else if( data_bit_wr==1'b1 )
  259.                 begin
  260.                         data_bit <= data_bit_in; // or load from internal NGS operation
  261.                 end
  262.         end
  263.         // +
  264.  
  265.         // command bit
  266.         always @(posedge cpu_clock)
  267.         begin
  268.                 if( wrcommport[2:1]==2'b10 )
  269.                 begin
  270.                         command_bit <= 1'b1; // set on command port writing by ZX
  271.                 end
  272.                 else if( command_bit_wr==1'b1 )
  273.                 begin
  274.                         command_bit <= command_bit_in; // or load from internal NGS operation
  275.                 end
  276.         end
  277.         // +
  278.  
  279.  
  280.  
  281.  
  282.  
  283. ///////////////////////////////
  284. // handle reset/nmi port $33 //
  285. ///////////////////////////////
  286.  
  287.         always @(negedge rst_n,posedge zxiowr_n)
  288.         begin
  289.                 if( !rst_n )
  290.                 begin
  291.                         async_rst_toggle <= 1'b0;
  292.                         async_nmi_toggle <= 1'b0;
  293.                         async_led_toggle <= 1'b0;
  294.                 end
  295.                 else if( zxrstport )
  296.                 begin
  297.                         if( dbin[7:5]==3'b100 )
  298.                                 async_rst_toggle <= ~async_rst_toggle;
  299.  
  300.                         if( dbin[7:5]==3'b010 )
  301.                                 async_nmi_toggle <= ~async_nmi_toggle;
  302.  
  303.                         if( dbin[7:5]==3'b001 )
  304.                                 async_led_toggle <= ~async_led_toggle;
  305.                 end
  306.         end
  307.         // +
  308.  
  309.  
  310.  
  311.         always @(negedge rst_n, posedge cpu_clock)
  312.         begin
  313.                 if( !rst_n )
  314.                 begin
  315.                         sync_rst_toggle[2:0] <= 3'd0;
  316.                         sync_nmi_toggle[2:0] <= 3'd0;
  317.                         sync_led_toggle[2:0] <= 3'd0;
  318.                         nmi_counter[NMI_CNT_SIZE:0] <= 32'hFFFFFFFF;
  319.                         prezxrst1 <= 1'b1;
  320.                         nmi_n <= 1'b1;
  321.  
  322.                         led_toggle <= 1'b0;
  323.                 end
  324.                 else // rst_n=1
  325.                 begin
  326.                         sync_rst_toggle[2:0] <= { sync_rst_toggle[1:0], async_rst_toggle };
  327.                         sync_nmi_toggle[2:0] <= { sync_nmi_toggle[1:0], async_nmi_toggle };
  328.                         sync_led_toggle[2:0] <= { sync_led_toggle[1:0], async_led_toggle };
  329.  
  330.                     if( sync_rst_toggle[2] != sync_rst_toggle[1] )
  331.                     begin
  332.                                 prezxrst1 <= 1'b0;
  333.                     end
  334.  
  335.                         if( sync_nmi_toggle[2] != sync_nmi_toggle[1] )
  336.                     begin
  337.                                 nmi_counter[NMI_CNT_SIZE:0] <= 0;
  338.                     end
  339.                         else
  340.                         begin
  341.                                 if( !nmi_counter[NMI_CNT_SIZE] )
  342.                                         nmi_counter <= nmi_counter + 1;
  343.                         end
  344.  
  345.                         nmi_n <= nmi_counter[NMI_CNT_SIZE];
  346.  
  347.  
  348.                         if( sync_led_toggle[2] != sync_led_toggle[1] )
  349.                                 led_toggle <= 1'b1;
  350.                         else
  351.                                 led_toggle <= 1'b0;
  352.                 end
  353.         end
  354.         // +
  355.  
  356.         always @(posedge cpu_clock)
  357.         begin
  358.                 prezxrst2     <= prezxrst1;
  359.                 rst_from_zx_n <= prezxrst2;
  360.         end
  361.         // +
  362.  
  363.  
  364. endmodule
  365.  
  366.