Subversion Repositories pentevo

Rev

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

  1. `include "../include/tune.v"
  2.  
  3. // PentEvo project (c) NedoPC 2008-2009
  4. //
  5. // vg93 interface
  6. //
  7. // #1F - vg93 command/state reg {0,0} - not here!
  8. // #3F - vg93 track register    {0,1} - not here!
  9. // #5F - vg93 sector register   {1,0} - not here!
  10. // #7F - vg93 data register     {1,1} - not here!
  11. // #FF - output "system" reg/input (DRQ+IRQ) reg
  12. //   output: d6 - FM/MFM               - NOT USED ANYWHERE! -> skipped
  13. //           d4 - disk side            - inverted out
  14. //           d3 - head load            - for HRDY pin of vg93
  15. //           d2 - /RESET for vg93      - must be zero at system reset
  16. //           d1:d0 - disk drive select - to the 74138
  17. //    input: d7 - /INTRQ - resynced at CPU clock
  18. //           d6 - /DRQ   - .....................
  19. //
  20. // current limitations:
  21. //  1. read clock regenerator is made of simple counter, as in pentagon128
  22. //  1. write precompensation is based only on SL/SR/TR43 signals
  23.  
  24. module vg93(
  25.  
  26.         input zclk, // Z80 cpu clock
  27.         input rst_n,
  28.         input fclk, // fpga 28 MHz clock
  29.  
  30.         output vg_clk,
  31.         output reg vg_res_n,
  32.  
  33.         input [7:0] din,  // data input from CPU
  34.         output intrq,drq, // output signals for the read #FF (not here)
  35.         input vg_wrFF,    // when TRDOS port #FF written - positive strobe
  36.  
  37.  
  38.         output reg  vg_hrdy,
  39.         output wire vg_rclk,
  40.         output wire vg_rawr,
  41.         output reg  [1:0] vg_a, // disk drive selection
  42.         output reg  vg_wrd,
  43.         output reg  vg_side,
  44.  
  45.         input step, // step signal from VG93
  46.         input vg_sl,vg_sr,vg_tr43,
  47.         input rdat_n,
  48.         input vg_wf_de,
  49.         input vg_drq,
  50.         input vg_irq,
  51.         input vg_wd
  52. );
  53.  
  54.  
  55.         localparam WRDELAY_OUTER_LEFT  = 4'd4;
  56.         localparam WRDELAY_OUTER_RIGHT = 4'd11;
  57.         localparam WRDELAY_INNER_LEFT  = 4'd0;  // minimal delay is for maximum shift left
  58.         localparam WRDELAY_INNER_RIGHT = 4'd14; // maximal delay is for maximum shift right
  59.         localparam WRDELAY_STANDARD    = 4'd7;  // no-shift
  60.  
  61.  
  62.  
  63.  
  64.         reg [2:0] vgclk_div7;
  65.         wire vgclk_strobe7;
  66.         reg [1:0] vgclk_div4;
  67.  
  68.         reg [2:0] step_pulse;
  69.         reg [2:0] drq_pulse;
  70.         wire step_pospulse;
  71.         wire  drq_pospulse;
  72.         reg turbo_state;
  73.  
  74.         reg [1:0] intrq_sync;
  75.         reg [1:0] drq_sync;
  76.  
  77.         reg [1:0] sl_sync,sr_sync,tr43_sync;
  78.         reg [2:0] wd_sync;
  79.         wire sl,sr,tr43,wd;
  80.  
  81.         reg [3:0] wrdelay_cnt;
  82.         wire delay_end;
  83.  
  84.         reg [3:0] wrwidth_cnt;
  85.         wire wrwidth_ena;
  86.  
  87.  
  88. //      reg [4:0] rdat_sync;
  89. //      reg rdat_edge1, rdat_edge2;
  90. //      wire rdat;
  91.  
  92. //      reg [3:0] rwidth_cnt;
  93. //      wire rwidth_ena;
  94. //      reg [5:0] rclk_cnt;
  95. //      wire rclk_strobe;
  96.  
  97.  
  98.  
  99.         // VG93 clocking and turbo-mode
  100.  
  101.         always @(posedge fclk)
  102.         begin
  103.                 step_pulse[2:0] <= { step_pulse[1:0], step};
  104.                  drq_pulse[2:0] <= {  drq_pulse[1:0], vg_drq};
  105.         end
  106.  
  107.         assign step_pospulse = ( step_pulse[1] & (~step_pulse[2]) );
  108.         assign  drq_pospulse = (  drq_pulse[1] & ( ~drq_pulse[2]) );
  109.  
  110.         always @(posedge fclk,negedge rst_n)
  111.         begin
  112.                 if( !rst_n )
  113.                         turbo_state <= 1'b0;
  114.                 else
  115.                 begin
  116.                         if( drq_pospulse )
  117.                                 turbo_state <= 1'b0;
  118.                         else if( step_pospulse )
  119.                                 turbo_state <= 1'b1;
  120.                 end
  121.         end
  122.  
  123.  
  124.  
  125.         assign vgclk_strobe7 = (vgclk_div7[2:1] == 2'b11); // 28/7=4MHz freq strobe
  126.  
  127.         always @(posedge fclk)
  128.         begin
  129.                 if( vgclk_strobe7 )
  130.                         vgclk_div7 <= 3'd0;
  131.                 else
  132.                         vgclk_div7 <= vgclk_div7 + 3'd1;
  133.         end
  134.  
  135.         always @(posedge fclk)
  136.         begin
  137.                 if( vgclk_strobe7 )
  138.                 begin
  139.                         vgclk_div4[0] <= ~vgclk_div4[1];
  140.  
  141.                         if( turbo_state )
  142.                                 vgclk_div4[1] <= ~vgclk_div4[1];
  143.                         else
  144.                                 vgclk_div4[1] <= vgclk_div4[0];
  145.                 end
  146.         end
  147.  
  148.         assign vg_clk = vgclk_div4[1];
  149.  
  150.  
  151.         // input/output for TR-DOS port #FF
  152.  
  153.         always @(posedge zclk, negedge rst_n) // CHANGE IF GO TO THE positive/negative strobes instead of zclk!
  154.         begin
  155.                 if( !rst_n )
  156.                         vg_res_n <= 1'b0;
  157.                 else if( vg_wrFF )
  158.                         { vg_side, vg_hrdy, vg_res_n, vg_a } <= { (~din[4]),din[3],din[2],din[1:0] };
  159.         end
  160.  
  161.         always @(posedge zclk)
  162.         begin
  163.                 intrq_sync[1:0] <= {intrq_sync[0],vg_irq};
  164.                 drq_sync[1:0] <= {drq_sync[0],vg_drq};
  165.         end
  166.  
  167.         assign intrq = intrq_sync[1];
  168.         assign drq   =   drq_sync[1];
  169.  
  170.  
  171.  
  172.  
  173.         // write precompensation
  174.         // delay times are as in WRDELAY_* parameters, vg_wrd width is always 7 clocks
  175.  
  176.         always @(posedge fclk)
  177.         begin
  178.                   sl_sync[1:0] <= {   sl_sync[0],   vg_sl   };
  179.                   sr_sync[1:0] <= {   sr_sync[0],   vg_sr   };
  180.                 tr43_sync[1:0] <= { tr43_sync[0],   vg_tr43 };
  181.                   wd_sync[2:0] <= {   wd_sync[1:0], vg_wd   };
  182.         end
  183.  
  184.         assign   sl =   sl_sync[1]; // just state signals
  185.         assign   sr =   sr_sync[1]; //
  186.         assign tr43 = tr43_sync[1]; //
  187.  
  188.         assign   wd =   wd_sync[1] & (~wd_sync[2]); // strobe: beginning of vg_wd
  189.  
  190.  
  191.         // make delay
  192.         always @(posedge fclk)
  193.         begin
  194.                 if( wd )
  195.                         case( {sl, tr43, sr} )
  196.                         3'b100:  // shift left, outer tracks
  197.                                 wrdelay_cnt <= WRDELAY_OUTER_LEFT;
  198.                         3'b001:  // shift right, outer tracks
  199.                                 wrdelay_cnt <= WRDELAY_OUTER_RIGHT;
  200.                         3'b110:  // shift left, inner tracks
  201.                                 wrdelay_cnt <= WRDELAY_INNER_LEFT;
  202.                         3'b011:  // shift right, inner tracks
  203.                                 wrdelay_cnt <= WRDELAY_INNER_RIGHT;
  204.                         default: // no shift
  205.                                 wrdelay_cnt <= WRDELAY_STANDARD;
  206.                         endcase
  207.                 else if( !delay_end )
  208.                         wrdelay_cnt <= wrdelay_cnt - 4'd1;
  209.         end
  210.  
  211.         assign delay_end = (wrdelay_cnt==4'd0);
  212.  
  213.  
  214.         // make vg_wdr impulse after a delay
  215.  
  216.         always @(posedge fclk)
  217.                 if( wrwidth_ena )
  218.                 begin
  219.                         if( wd )
  220.                                 wrwidth_cnt <= 4'd0;
  221.                         else
  222.                                 wrwidth_cnt <= wrwidth_cnt + 4'd1;
  223.                 end
  224.  
  225.         assign wrwidth_ena = wd | ( delay_end & (~wrwidth_cnt[3]) );
  226.  
  227.         always @(posedge fclk)
  228.                 vg_wrd <= | wrwidth_cnt[2:0]; // only 7 clocks is the lendth of vg_wrd
  229.  
  230.  
  231.  
  232.  
  233. /*      fapch_counter dpll
  234.         (
  235.                 .fclk   (fclk   ),
  236.  
  237.                 .rdat_n (rdat_n ),
  238.  
  239.                 .vg_rclk(vg_rclk),
  240.                 .vg_rawr(vg_rawr)
  241.         );
  242. */
  243.  
  244.         fapch_zek     dpll
  245.         (
  246.                 .fclk   (fclk   ),
  247.  
  248.                 .rdat_n (rdat_n ),
  249.  
  250.                 .vg_rclk(vg_rclk),
  251.                 .vg_rawr(vg_rawr)
  252.         );
  253.  
  254.  
  255.  
  256.  
  257. endmodule
  258.  
  259.