Subversion Repositories pentevo

Rev

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

  1. // PentEvo project (c) NedoPC 2008-2011
  2. //
  3. // Z80 clocking module, also contains some wait-stating when 14MHz
  4. //
  5. // IDEAL:
  6. // fclk    _/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\_/`\
  7. //          |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
  8. // zclk     /```\___/```\___/```\___/```````\_______/```````\_______/```````````````\_______________/```````````````\_______________/`
  9. //          |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
  10. // zpos     `\___/```\___/```\___/```\___________/```\___________/```\___________________________/```\___________________________/```\
  11. //          |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
  12. // zneg     _/```\___/```\___/```\_______/```\___________/```\___________________/```\___________________________/```\________________
  13.  
  14. // clock phasing:
  15. // cend must be zpos for 7mhz, therefore post_cbeg - zneg
  16. // for 3.5 mhz, cend is both zpos and zneg (alternating)
  17.  
  18.  
  19.  
  20.  
  21. // 14MHz rulez:
  22. // 1. do variable stalls for memory access.
  23. // 2. do fallback on 7mhz for external IO accesses
  24. // 3. clock switch 14-7-3.5 only at RFSH
  25.  
  26.  
  27.  
  28. `include "../include/tune.v"
  29.  
  30. module zclock(
  31.  
  32.         input fclk,
  33.         input rst_n,
  34.  
  35.         input zclk, // Z80 clock, buffered via act04 and returned back to the FPGA
  36.  
  37.         input rfsh_n, // switch turbo modes in RFSH part of m1
  38.  
  39.  
  40.         output reg zclk_out, // generated Z80 clock - passed through inverter externally!
  41.  
  42.         output reg zpos,
  43.         output reg zneg,
  44.  
  45.  
  46.         input  wire zclk_stall,
  47.  
  48.  
  49.  
  50.  
  51.         input [1:0] turbo, // 2'b00 -  3.5 MHz
  52.                            // 2'b01 -  7.0 MHz
  53.                            // 2'b1x - 14.0 MHz
  54.  
  55.         output reg [1:0] int_turbo, // internal turbo, switched on /RFSH
  56.  
  57.  
  58.         // input signals for 14MHz external IORQ waits
  59.         input  wire external_port,
  60.         input  wire iorq_n,
  61.         input  wire m1_n,
  62.  
  63.  
  64.         input cbeg,
  65.         input pre_cend // syncing signals, taken from arbiter.v and dram.v
  66. );
  67.  
  68.  
  69.         reg precend_cnt;
  70.         wire h_precend_1; // to take every other pulse of pre_cend
  71.         wire h_precend_2; // to take every other pulse of pre_cend
  72.  
  73.         reg [2:0] zcount; // counter for generating 3.5 and 7 MHz z80 clocks
  74.  
  75.  
  76.         reg old_rfsh_n;
  77.  
  78.  
  79.         wire stall;
  80.  
  81.  
  82.         reg clk14_src; // source for 14MHz clock
  83.  
  84.  
  85.  
  86.  
  87.  
  88.         wire pre_zpos_35,
  89.              pre_zneg_35;
  90.  
  91.         wire pre_zpos_70,
  92.              pre_zneg_70;
  93.  
  94.         wire pre_zpos_140,
  95.              pre_zneg_140;
  96.  
  97.  
  98.  
  99.  
  100. `ifdef SIMULATE
  101.         initial // simulation...
  102.         begin
  103.                 precend_cnt = 1'b0;
  104.                 int_turbo   = 2'b00;
  105.                 old_rfsh_n  = 1'b1;
  106.                 clk14_src   = 1'b0;
  107.  
  108.                 zclk_out = 1'b0;
  109.         end
  110. `endif
  111.  
  112.         // switch clock only at predefined time
  113.         always @(posedge fclk) if(zpos)
  114.         begin
  115.                 old_rfsh_n <= rfsh_n;
  116.  
  117.                 if( old_rfsh_n && !rfsh_n )
  118.                         int_turbo <= turbo;
  119.         end
  120.  
  121.  
  122.  
  123.  
  124.         // make 14MHz iorq wait
  125.         reg [3:0] io_wait_cnt;
  126.        
  127.         reg io_wait;
  128.  
  129.         wire io;
  130.         reg  io_r;
  131.  
  132.         assign io = (~iorq_n) & m1_n & external_port;
  133.  
  134.         always @(posedge fclk)
  135.         if( zpos )
  136.                 io_r <= io;
  137.  
  138.         always @(posedge fclk, negedge rst_n)
  139.         if( ~rst_n )
  140.                 io_wait_cnt <= 4'd0;
  141.         else if( io && (!io_r) && zpos && int_turbo[1] )
  142.                 io_wait_cnt[3] <= 1'b1;
  143.         else if( io_wait_cnt[3] )
  144.                 io_wait_cnt <= io_wait_cnt + 4'd1;
  145.  
  146.         always @(posedge fclk)
  147.         case( io_wait_cnt )
  148.                 4'b1000: io_wait <= 1'b1;
  149.                 4'b1001: io_wait <= 1'b1;
  150.                 4'b1010: io_wait <= 1'b1;
  151.                 4'b1011: io_wait <= 1'b1;
  152.                 4'b1100: io_wait <= 1'b1;
  153.                 4'b1101: io_wait <= 1'b0;
  154.                 4'b1110: io_wait <= 1'b1;
  155.                 4'b1111: io_wait <= 1'b0;
  156.                 default: io_wait <= 1'b0;              
  157.         endcase
  158.  
  159.  
  160.  
  161.  
  162.         assign stall = zclk_stall | io_wait;
  163.  
  164.  
  165.  
  166.         // 14MHz clocking
  167.         always @(posedge fclk)
  168.         if( !stall )
  169.                 clk14_src <= ~clk14_src;
  170.         //
  171.         assign pre_zpos_140 =   clk14_src ;
  172.         assign pre_zneg_140 = (~clk14_src);
  173.  
  174.  
  175.  
  176.         // take every other pulse of pre_cend (make half pre_cend)
  177.         always @(posedge fclk) if( pre_cend )
  178.                 precend_cnt <= ~precend_cnt;
  179.  
  180.         assign h_precend_1 =  precend_cnt && pre_cend;
  181.         assign h_precend_2 = !precend_cnt && pre_cend;
  182.  
  183.  
  184.         assign pre_zpos_35 = h_precend_2;
  185.         assign pre_zneg_35 = h_precend_1;
  186.  
  187.         assign pre_zpos_70 = pre_cend;
  188.         assign pre_zneg_70 = cbeg;
  189.  
  190.  
  191.         assign pre_zpos = int_turbo[1] ? pre_zpos_140 : ( int_turbo[0] ? pre_zpos_70 : pre_zpos_35 );
  192.         assign pre_zneg = int_turbo[1] ? pre_zneg_140 : ( int_turbo[0] ? pre_zneg_70 : pre_zneg_35 );
  193.  
  194.  
  195.  
  196.         always @(posedge fclk)
  197.         begin
  198.                 zpos <= (~stall) & pre_zpos & zclk_out;
  199.         end
  200.  
  201.         always @(posedge fclk)
  202.         begin
  203.                 zneg <= (~stall) & pre_zneg & (~zclk_out);
  204.         end
  205.  
  206.        
  207.  
  208.  
  209.  
  210.  
  211.         // make Z80 clock: account for external inversion and make some leading of clock
  212.         // 9.5 ns propagation delay: from fclk posedge to zclk returned back any edge
  213.         // (1/28)/2=17.9ns half a clock lead
  214.         // 2.6ns lag because of non-output register emitting of zclk_out
  215.         // total: 5.8 ns lead of any edge of zclk relative to posedge of fclk => ACCOUNT FOR THIS WHEN DOING INTER-CLOCK DATA TRANSFERS
  216.         //
  217.  
  218.         always @(negedge fclk)
  219.         begin
  220.                 if( zpos )
  221.                         zclk_out <= 1'b0;
  222.  
  223.                 if( zneg )
  224.                         zclk_out <= 1'b1;
  225.         end
  226.  
  227.  
  228. endmodule
  229.  
  230.