Blame | Last modification | View Log | Download | RSS feed
`include "../include/tune.v"// PentEvo project (c) NedoPC 2008-2009//// vg93 interface//// #1F - vg93 command/state reg {0,0} - not here!// #3F - vg93 track register {0,1} - not here!// #5F - vg93 sector register {1,0} - not here!// #7F - vg93 data register {1,1} - not here!// #FF - output "system" reg/input (DRQ+IRQ) reg// output: d6 - FM/MFM - NOT USED ANYWHERE! -> skipped// d4 - disk side - inverted out// d3 - head load - for HRDY pin of vg93// d2 - /RESET for vg93 - must be zero at system reset// d1:d0 - disk drive select - to the 74138// input: d7 - /INTRQ - resynced at CPU clock// d6 - /DRQ - .....................//// current limitations:// 1. read clock regenerator is made of simple counter, as in pentagon128// 1. write precompensation is based only on SL/SR/TR43 signalsmodule vg93(input zclk, // Z80 cpu clockinput rst_n,input fclk, // fpga 28 MHz clockoutput vg_clk,output reg vg_res_n,input [7:0] din, // data input from CPUoutput intrq,drq, // output signals for the read #FF (not here)input vg_wrFF, // when TRDOS port #FF written - positive strobeoutput reg vg_hrdy,output reg vg_rclk,output reg vg_rawr,output reg [1:0] vg_a, // disk drive selectionoutput reg vg_wrd,output reg vg_side,input step, // step signal from VG93input vg_sl,vg_sr,vg_tr43,input rdat_n,input vg_wf_de,input vg_drq,input vg_irq,input vg_wd);localparam WRDELAY_OUTER_LEFT = 4'd4;localparam WRDELAY_OUTER_RIGHT = 4'd11;localparam WRDELAY_INNER_LEFT = 4'd0; // minimal delay is for maximum shift leftlocalparam WRDELAY_INNER_RIGHT = 4'd14; // maximal delay is for maximum shift rightlocalparam WRDELAY_STANDARD = 4'd7; // no-shiftreg [2:0] vgclk_div7;wire vgclk_strobe7;reg [1:0] vgclk_div4;reg [2:0] step_pulse;reg [2:0] drq_pulse;wire step_pospulse;wire drq_pospulse;reg turbo_state;reg [1:0] intrq_sync;reg [1:0] drq_sync;reg [1:0] sl_sync,sr_sync,tr43_sync;reg [2:0] wd_sync;wire sl,sr,tr43,wd;reg [3:0] wrdelay_cnt;wire delay_end;reg [3:0] wrwidth_cnt;wire wrwidth_ena;reg [4:0] rdat_sync;reg rdat_edge1, rdat_edge2;wire rdat;reg [3:0] rwidth_cnt;wire rwidth_ena;reg [5:0] rclk_cnt;wire rclk_strobe;// VG93 clocking and turbo-modealways @(posedge fclk)beginstep_pulse[2:0] <= { step_pulse[1:0], step};drq_pulse[2:0] <= { drq_pulse[1:0], vg_drq};endassign step_pospulse = ( step_pulse[1] & (~step_pulse[2]) );assign drq_pospulse = ( drq_pulse[1] & ( ~drq_pulse[2]) );always @(posedge fclk,negedge rst_n)beginif( !rst_n )turbo_state <= 1'b0;elsebeginif( drq_pospulse )turbo_state <= 1'b0;else if( step_pospulse )turbo_state <= 1'b1;endendassign vgclk_strobe7 = (vgclk_div7[2:1] == 2'b11); // 28/7=4MHz freq strobealways @(posedge fclk)beginif( vgclk_strobe7 )vgclk_div7 <= 3'd0;elsevgclk_div7 <= vgclk_div7 + 3'd1;endalways @(posedge fclk)beginif( vgclk_strobe7 )beginvgclk_div4[0] <= ~vgclk_div4[1];if( turbo_state )vgclk_div4[1] <= ~vgclk_div4[1];elsevgclk_div4[1] <= vgclk_div4[0];endendassign vg_clk = vgclk_div4[1];// input/output for TR-DOS port #FFalways @(posedge zclk, negedge rst_n) // CHANGE IF GO TO THE positive/negative strobes instead of zclk!beginif( !rst_n )vg_res_n <= 1'b0;else if( vg_wrFF ){ vg_side, vg_hrdy, vg_res_n, vg_a } <= { (~din[4]),din[3],din[2],din[1:0] };endalways @(posedge zclk)beginintrq_sync[1:0] <= {intrq_sync[0],vg_irq};drq_sync[1:0] <= {drq_sync[0],vg_drq};endassign intrq = intrq_sync[1];assign drq = drq_sync[1];// write precompensation// delay times are as in WRDELAY_* parameters, vg_wrd width is always 7 clocksalways @(posedge fclk)beginsl_sync[1:0] <= { sl_sync[0], vg_sl };sr_sync[1:0] <= { sr_sync[0], vg_sr };tr43_sync[1:0] <= { tr43_sync[0], vg_tr43 };wd_sync[2:0] <= { wd_sync[1:0], vg_wd };endassign sl = sl_sync[1]; // just state signalsassign sr = sr_sync[1]; //assign tr43 = tr43_sync[1]; //assign wd = wd_sync[1] & (~wd_sync[2]); // strobe: beginning of vg_wd// make delayalways @(posedge fclk)beginif( wd )case( {sl, tr43, sr} )3'b100: // shift left, outer trackswrdelay_cnt <= WRDELAY_OUTER_LEFT;3'b001: // shift right, outer trackswrdelay_cnt <= WRDELAY_OUTER_RIGHT;3'b110: // shift left, inner trackswrdelay_cnt <= WRDELAY_INNER_LEFT;3'b011: // shift right, inner trackswrdelay_cnt <= WRDELAY_INNER_RIGHT;default: // no shiftwrdelay_cnt <= WRDELAY_STANDARD;endcaseelse if( !delay_end )wrdelay_cnt <= wrdelay_cnt - 4'd1;endassign delay_end = (wrdelay_cnt==4'd0);// make vg_wdr impulse after a delayalways @(posedge fclk)if( wrwidth_ena )beginif( wd )wrwidth_cnt <= 4'd0;elsewrwidth_cnt <= wrwidth_cnt + 4'd1;endassign wrwidth_ena = wd | ( delay_end & (~wrwidth_cnt[3]) );always @(posedge fclk)vg_wrd <= | wrwidth_cnt[2:0]; // only 7 clocks is the lendth of vg_wrd// RCLK/RAWR restore// currently simplest counter method, no PLL whatsoever now//// RCLK period must be 112 clocks (@28 MHz), or 56 clocks for each state// RAWR on time is 4 clocks// digital filter - removing glitchesalways @(posedge fclk)rdat_sync[4:0] <= { rdat_sync[3:0], (~rdat_n) };always @(posedge fclk)beginif( rdat_sync[4:1]==4'b1111 ) // filter beginning of stroberdat_edge1 <= 1'b1;else if( rclk_strobe ) // filter any more strobes during same strobe half-perionrdat_edge1 <= 1'b0;// else if( rdat_sync[4:1]==4'b0000 )// rdat_edge1 <= 1'b0;rdat_edge2 <= rdat_edge1;endassign rdat = rdat_edge1 & (~rdat_edge2);// assign rdat = rdat_sync[1] & (~rdat_sync[2]);always @(posedge fclk)if( rwidth_ena )beginif( rdat )rwidth_cnt <= 4'd0;elserwidth_cnt <= rwidth_cnt + 4'd1;endassign rwidth_ena = rdat | (~rwidth_cnt[2]); // [2] - 140ns, [3] - 280nsassign rclk_strobe = (rclk_cnt==6'd0);always @(posedge fclk)beginif( rdat )rclk_cnt <= 6'd29; // (56/2)-1 plus halfwidth of RAWRelse if( rclk_strobe )rclk_cnt <= 6'd55; // period is 56 clockselserclk_cnt <= rclk_cnt - 6'd1;endreg [5:0] counter = 0;wire[5:0] delta = 27 - counter;wire[5:0] shift = { delta[5], delta[5], delta[4:1] }; // sign divwire[5:0] inc = rawr_sr[1:0] == 2'b10 ? shift : 1;reg [3:0] rawr_sr;always @ (posedge clk)beginrawr_sr <= { rawr_sr[2:0], rdat_n };vg_rawr <= !(rawr_sr[3] && !rawr_sr[0] ); // rawr 100nsendalways @ (posedge fclk)beginif (counter < 55)counter <= counter + inc;elsebegincounter <= 0;vg_rclk <= ~vg_rclk;endendendmodule