Subversion Repositories pentevo

Rev

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

  1. // ZX-Evo Base Configuration (c) NedoPC 2008,2009,2010,2011,2012,2013,2014
  2. //
  3. // Z80 clocking module, also contains some wait-stating when 14MHz
  4.  
  5. /*
  6.     This file is part of ZX-Evo Base Configuration firmware.
  7.  
  8.     ZX-Evo Base Configuration firmware is free software:
  9.     you can redistribute it and/or modify it under the terms of
  10.     the GNU General Public License as published by
  11.     the Free Software Foundation, either version 3 of the License, or
  12.     (at your option) any later version.
  13.  
  14.     ZX-Evo Base Configuration firmware is distributed in the hope that
  15.     it will be useful, but WITHOUT ANY WARRANTY; without even
  16.     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17.     See the GNU General Public License for more details.
  18.  
  19.     You should have received a copy of the GNU General Public License
  20.     along with ZX-Evo Base Configuration firmware.
  21.     If not, see <http://www.gnu.org/licenses/>.
  22. */
  23.  
  24.  
  25. //
  26. // IDEAL:
  27. // fclk    _/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\
  28. //          |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
  29. // zclk     /```\___/```\___/```\___/```````\_______/```````\_______/```````````````\_______________/```````````````\_______________/`
  30. //          |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
  31. // zpos     `\___/```\___/```\___/```\___________/```\___________/```\___________________________/```\___________________________/```\
  32. //          |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
  33. // zneg     _/```\___/```\___/```\_______/```\___________/```\___________________/```\___________________________/```\________________
  34.  
  35. // clock phasing:
  36. // cend must be zpos for 7mhz, therefore post_cbeg - zneg
  37. // for 3.5 mhz, cend is both zpos and zneg (alternating)
  38.  
  39.  
  40. // 14MHz rulez:
  41. // 1. do variable stalls for memory access.
  42. // 2. do fallback on 7mhz for external IO accesses
  43. // 3. clock switch 14-7-3.5 only at RFSH
  44.  
  45.  
  46. `include "../include/tune.v"
  47.  
  48. module zclock(
  49.  
  50.         input  wire        fclk,
  51.         input  wire        rst_n,
  52.  
  53.         input  wire        zclk, // Z80 clock, buffered via act04 and returned back to the FPGA
  54.  
  55.         input  wire [15:0] a, // for contention
  56.  
  57.         input  wire [ 1:0] modes_raster,
  58.         input  wire        mode_contend_type,
  59.         input  wire        mode_contend_ena,
  60.         input  wire [ 2:0] mode_7ffd_bits,    // low 3 bits of 7FFD for 128k contention
  61.  
  62.         input  wire        contend,
  63.  
  64.         input  wire        mreq_n,
  65.         input  wire        iorq_n,
  66.         input  wire        m1_n,
  67.         input  wire        rfsh_n, // switch turbo modes in RFSH part of m1
  68.  
  69.  
  70.         output reg         zclk_out, // generated Z80 clock - passed through inverter externally!
  71.  
  72.         output reg         zpos,
  73.         output reg         zneg,
  74.  
  75.  
  76.         input  wire        zclk_stall,
  77.  
  78.  
  79.  
  80.  
  81.         input  wire [ 1:0] turbo, // 2'b00 -  3.5 MHz
  82.                                   // 2'b01 -  7.0 MHz
  83.                                   // 2'b1x - 14.0 MHz
  84.  
  85.         output reg  [ 1:0] int_turbo, // internal turbo, switched on /RFSH
  86.  
  87.  
  88.         // input signals for 14MHz external IORQ waits
  89.         input  wire        external_port,
  90.  
  91.  
  92.         input  wire        cbeg,
  93.         input  wire        pre_cend // syncing signals, taken from arbiter.v and dram.v
  94. );
  95.  
  96.  
  97.         reg precend_cnt;
  98.         wire h_precend_1; // to take every other pulse of pre_cend
  99.         wire h_precend_2; // to take every other pulse of pre_cend
  100.  
  101.         reg [2:0] zcount; // counter for generating 3.5 and 7 MHz z80 clocks
  102.  
  103.         reg old_rfsh_n;
  104.  
  105.         wire stall;
  106.  
  107.         reg clk14_src; // source for 14MHz clock
  108.  
  109.         wire pre_zpos_35,
  110.              pre_zneg_35;
  111.  
  112.         wire pre_zpos_70,
  113.              pre_zneg_70;
  114.  
  115.         wire pre_zpos_140,
  116.              pre_zneg_140;
  117.  
  118.  
  119.         reg  r_mreq_n;
  120.         wire iorq_n_a;
  121.         reg  r_iorq_n_a;
  122.         wire contend_wait;
  123.         wire contend_mem;
  124.         wire contend_io;
  125.         wire contend_addr;
  126.  
  127.         reg [2:0] p7ffd; // resync to 14MHz
  128.  
  129.  
  130. `ifdef SIMULATE
  131.         initial // simulation...
  132.         begin
  133.                 precend_cnt = 1'b0;
  134.                 int_turbo   = 2'b00;
  135.                 old_rfsh_n  = 1'b1;
  136.                 clk14_src   = 1'b0;
  137.  
  138.                 zclk_out = 1'b0;
  139.         end
  140. `endif
  141.  
  142.         // switch clock only at predefined time
  143.         always @(posedge fclk) if(zpos)
  144.         begin
  145.                 old_rfsh_n <= rfsh_n;
  146.  
  147.                 if( old_rfsh_n && !rfsh_n )
  148.                         int_turbo <= turbo;
  149.         end
  150.  
  151.  
  152.         // resync p7ffd
  153.         always @(posedge fclk)
  154.                 p7ffd <= mode_7ffd_bits;
  155.  
  156.  
  157.  
  158.         // make 14MHz iorq wait
  159.         reg [3:0] io_wait_cnt;
  160.        
  161.         reg io_wait;
  162.  
  163.         wire io;
  164.         reg  io_r;
  165.  
  166.         assign io = (~iorq_n) & m1_n & external_port;
  167.  
  168.         always @(posedge fclk)
  169.         if( zpos )
  170.                 io_r <= io;
  171.  
  172.         always @(posedge fclk, negedge rst_n)
  173.         if( ~rst_n )
  174.                 io_wait_cnt <= 4'd0;
  175.         else if( io && (!io_r) && zpos && int_turbo[1] )
  176.                 io_wait_cnt[3] <= 1'b1;
  177.         else if( io_wait_cnt[3] )
  178.                 io_wait_cnt <= io_wait_cnt + 4'd1;
  179.  
  180.         always @(posedge fclk)
  181.         case( io_wait_cnt )
  182.                 4'b1000: io_wait <= 1'b1;
  183.                 4'b1001: io_wait <= 1'b1;
  184.                 4'b1010: io_wait <= 1'b1;
  185.                 4'b1011: io_wait <= 1'b1;
  186.                 4'b1100: io_wait <= 1'b1;
  187.                 4'b1101: io_wait <= 1'b0;
  188.                 4'b1110: io_wait <= 1'b1;
  189.                 4'b1111: io_wait <= 1'b0;
  190.                 default: io_wait <= 1'b0;              
  191.         endcase
  192.  
  193.  
  194.  
  195.  
  196.         assign stall = zclk_stall | io_wait | contend_wait;
  197.  
  198.  
  199.  
  200.         // 14MHz clocking
  201.         always @(posedge fclk)
  202.         if( !stall )
  203.                 clk14_src <= ~clk14_src;
  204.         //
  205.         assign pre_zpos_140 =   clk14_src ;
  206.         assign pre_zneg_140 = (~clk14_src);
  207.  
  208.  
  209.  
  210.         // take every other pulse of pre_cend (make half pre_cend)
  211.         always @(posedge fclk) if( pre_cend )
  212.                 precend_cnt <= ~precend_cnt;
  213.  
  214.         assign h_precend_1 =  precend_cnt && pre_cend;
  215.         assign h_precend_2 = !precend_cnt && pre_cend;
  216.  
  217.  
  218.         assign pre_zpos_35 = h_precend_2;
  219.         assign pre_zneg_35 = h_precend_1;
  220.  
  221.         assign pre_zpos_70 = pre_cend;
  222.         assign pre_zneg_70 = cbeg;
  223.  
  224.  
  225.         assign pre_zpos = int_turbo[1] ? pre_zpos_140 : ( int_turbo[0] ? pre_zpos_70 : pre_zpos_35 );
  226.         assign pre_zneg = int_turbo[1] ? pre_zneg_140 : ( int_turbo[0] ? pre_zneg_70 : pre_zneg_35 );
  227.  
  228.  
  229.  
  230.         always @(posedge fclk)
  231.         begin
  232.                 zpos <= (~stall) & pre_zpos & zclk_out;
  233.         end
  234.  
  235.         always @(posedge fclk)
  236.         begin
  237.                 zneg <= (~stall) & pre_zneg & (~zclk_out);
  238.         end
  239.  
  240.        
  241.  
  242.  
  243.  
  244.  
  245.         // make Z80 clock: account for external inversion and make some leading of clock
  246.         // 9.5 ns propagation delay: from fclk posedge to zclk returned back any edge
  247.         // (1/28)/2=17.9ns half a clock lead
  248.         // 2.6ns lag because of non-output register emitting of zclk_out
  249.         // total: 5.8 ns lead of any edge of zclk relative to posedge of fclk => ACCOUNT FOR THIS WHEN DOING INTER-CLOCK DATA TRANSFERS
  250.         //
  251.  
  252.         always @(negedge fclk)
  253.         begin
  254.                 if( zpos )
  255.                         zclk_out <= 1'b0;
  256.  
  257.                 if( zneg )
  258.                         zclk_out <= 1'b1;
  259.         end
  260.  
  261.  
  262.  
  263.  
  264.  
  265.         // contention emulation -- only 48k by now, TODO 128k pages and +2a/+3!
  266.         //
  267.         assign iorq_n_a = iorq_n || (a[0]==1'b1);
  268.         //
  269.         always @(posedge fclk)
  270.         if( zpos )
  271.         begin
  272.                 r_mreq_n   <= mreq_n;
  273.                 r_iorq_n_a <= iorq_n_a;
  274.         end
  275.         //
  276.         assign contend_addr = (modes_raster[0]==1'b0) ? ( a[15:14]==2'b01                                  ) : // 48k mode
  277.                                                         ( a[15:14]==2'b01 || (a[15:14]==2'b11 && p7ffd[0]) ) ; // 128k mode (yet only 128/+2)
  278.         //
  279.         assign contend_mem = contend_addr && r_mreq_n;
  280.         assign contend_io  = !iorq_n_a && r_iorq_n_a;
  281.         //
  282.         assign contend_wait = contend && (contend_mem || contend_io) && !int_turbo && modes_raster[1] && mode_contend_ena;
  283.         //
  284.         // TODO: contend is 28MHz signal, while we'd better have here
  285.         //       3.5MHz-synced r_contend signal, which should be synced
  286.         //       to free-running 3.5MHz zpos/zneg sequence (not affected by stall)
  287.  
  288. endmodule
  289.  
  290.