Subversion Repositories pentevo

Rev

Rev 467 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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 fclk,
  51.         input rst_n,
  52.  
  53.         input zclk, // Z80 clock, buffered via act04 and returned back to the FPGA
  54.  
  55.         input rfsh_n, // switch turbo modes in RFSH part of m1
  56.  
  57.  
  58.         output reg zclk_out, // generated Z80 clock - passed through inverter externally!
  59.  
  60.         output reg zpos,
  61.         output reg zneg,
  62.  
  63.  
  64.         input  wire zclk_stall,
  65.  
  66.  
  67.  
  68.  
  69.         input [1:0] turbo, // 2'b00 -  3.5 MHz
  70.                            // 2'b01 -  7.0 MHz
  71.                            // 2'b1x - 14.0 MHz
  72.  
  73.         output reg [1:0] int_turbo, // internal turbo, switched on /RFSH
  74.  
  75.  
  76.         // input signals for 14MHz external IORQ waits
  77.         input  wire external_port,
  78.         input  wire iorq_n,
  79.         input  wire m1_n,
  80.  
  81.  
  82.         input cbeg,
  83.         input pre_cend // syncing signals, taken from arbiter.v and dram.v
  84. );
  85.  
  86.  
  87.         reg precend_cnt;
  88.         wire h_precend_1; // to take every other pulse of pre_cend
  89.         wire h_precend_2; // to take every other pulse of pre_cend
  90.  
  91.         reg [2:0] zcount; // counter for generating 3.5 and 7 MHz z80 clocks
  92.  
  93.  
  94.         reg old_rfsh_n;
  95.  
  96.  
  97.         wire stall;
  98.  
  99.  
  100.         reg clk14_src; // source for 14MHz clock
  101.  
  102.  
  103.  
  104.  
  105.  
  106.         wire pre_zpos_35,
  107.              pre_zneg_35;
  108.  
  109.         wire pre_zpos_70,
  110.              pre_zneg_70;
  111.  
  112.         wire pre_zpos_140,
  113.              pre_zneg_140;
  114.  
  115.  
  116.  
  117.  
  118. `ifdef SIMULATE
  119.         initial // simulation...
  120.         begin
  121.                 precend_cnt = 1'b0;
  122.                 int_turbo   = 2'b00;
  123.                 old_rfsh_n  = 1'b1;
  124.                 clk14_src   = 1'b0;
  125.  
  126.                 zclk_out = 1'b0;
  127.         end
  128. `endif
  129.  
  130.         // switch clock only at predefined time
  131.         always @(posedge fclk) if(zpos)
  132.         begin
  133.                 old_rfsh_n <= rfsh_n;
  134.  
  135.                 if( old_rfsh_n && !rfsh_n )
  136.                         int_turbo <= turbo;
  137.         end
  138.  
  139.  
  140.  
  141.  
  142.         // make 14MHz iorq wait
  143.         reg [3:0] io_wait_cnt;
  144.        
  145.         reg io_wait;
  146.  
  147.         wire io;
  148.         reg  io_r;
  149.  
  150.         assign io = (~iorq_n) & m1_n & external_port;
  151.  
  152.         always @(posedge fclk)
  153.         if( zpos )
  154.                 io_r <= io;
  155.  
  156.         always @(posedge fclk, negedge rst_n)
  157.         if( ~rst_n )
  158.                 io_wait_cnt <= 4'd0;
  159.         else if( io && (!io_r) && zpos && int_turbo[1] )
  160.                 io_wait_cnt[3] <= 1'b1;
  161.         else if( io_wait_cnt[3] )
  162.                 io_wait_cnt <= io_wait_cnt + 4'd1;
  163.  
  164.         always @(posedge fclk)
  165.         case( io_wait_cnt )
  166.                 4'b1000: io_wait <= 1'b1;
  167.                 4'b1001: io_wait <= 1'b1;
  168.                 4'b1010: io_wait <= 1'b1;
  169.                 4'b1011: io_wait <= 1'b1;
  170.                 4'b1100: io_wait <= 1'b1;
  171.                 4'b1101: io_wait <= 1'b0;
  172.                 4'b1110: io_wait <= 1'b1;
  173.                 4'b1111: io_wait <= 1'b0;
  174.                 default: io_wait <= 1'b0;              
  175.         endcase
  176.  
  177.  
  178.  
  179.  
  180.         assign stall = zclk_stall | io_wait;
  181.  
  182.  
  183.  
  184.         // 14MHz clocking
  185.         always @(posedge fclk)
  186.         if( !stall )
  187.                 clk14_src <= ~clk14_src;
  188.         //
  189.         assign pre_zpos_140 =   clk14_src ;
  190.         assign pre_zneg_140 = (~clk14_src);
  191.  
  192.  
  193.  
  194.         // take every other pulse of pre_cend (make half pre_cend)
  195.         always @(posedge fclk) if( pre_cend )
  196.                 precend_cnt <= ~precend_cnt;
  197.  
  198.         assign h_precend_1 =  precend_cnt && pre_cend;
  199.         assign h_precend_2 = !precend_cnt && pre_cend;
  200.  
  201.  
  202.         assign pre_zpos_35 = h_precend_2;
  203.         assign pre_zneg_35 = h_precend_1;
  204.  
  205.         assign pre_zpos_70 = pre_cend;
  206.         assign pre_zneg_70 = cbeg;
  207.  
  208.  
  209.         assign pre_zpos = int_turbo[1] ? pre_zpos_140 : ( int_turbo[0] ? pre_zpos_70 : pre_zpos_35 );
  210.         assign pre_zneg = int_turbo[1] ? pre_zneg_140 : ( int_turbo[0] ? pre_zneg_70 : pre_zneg_35 );
  211.  
  212.  
  213.  
  214.         always @(posedge fclk)
  215.         begin
  216.                 zpos <= (~stall) & pre_zpos & zclk_out;
  217.         end
  218.  
  219.         always @(posedge fclk)
  220.         begin
  221.                 zneg <= (~stall) & pre_zneg & (~zclk_out);
  222.         end
  223.  
  224.        
  225.  
  226.  
  227.  
  228.  
  229.         // make Z80 clock: account for external inversion and make some leading of clock
  230.         // 9.5 ns propagation delay: from fclk posedge to zclk returned back any edge
  231.         // (1/28)/2=17.9ns half a clock lead
  232.         // 2.6ns lag because of non-output register emitting of zclk_out
  233.         // total: 5.8 ns lead of any edge of zclk relative to posedge of fclk => ACCOUNT FOR THIS WHEN DOING INTER-CLOCK DATA TRANSFERS
  234.         //
  235.  
  236.         always @(negedge fclk)
  237.         begin
  238.                 if( zpos )
  239.                         zclk_out <= 1'b0;
  240.  
  241.                 if( zneg )
  242.                         zclk_out <= 1'b1;
  243.         end
  244.  
  245.  
  246. endmodule
  247.  
  248.