Minimig NTSC
alexh (070727) thinks:
- Change the master clock (mclk) crystal from 4.433619 MHz PAL crystal to 3.579545 MHz NTSC. These crystals are standard very common, should be easy to source.
- The next thing to do is change the FPGA Digital Clock Module (DCM) which is a feature of the FPGA which can create clocks with zero skew.
- If you look in minimig1.v (the top level) you can see where the DCM is instantiated and thanks to Dennis's great comments you can see that all the clocks are derived from a 28 MHz clock (c_28). The DCM generates this 28MHz clock by multiplying mclk by 32 and then dividing by 5.
- Now that we've changed mclk to 3.579545 MHz we need to change the DCM so that it generates it by multiplying by 8.
- Nothing needs to change in the file minimig1.v except the comments, Code changes needed: Minimig NTSC fix code0 minimig1.v.
- Change the DCM parameters to make it multiply by 8. The Xilinx FPGA Webpack has a GUI tool called Xilinx 'Architecture Wizard' to do this but you can sort of get the idea if you look at the clock_dmc.v file.
- You can see that you need to change the multiplier from 32 to 8 and the divider to 1. (Use the GUI in case other values need to change)
- These changes alone are not be enough.
- Need to change some constants (horbeam and verbeam comparisons) in agnus.v for NTSC timing. Perhaps some other register values also.
- If you look in agnus.v for the module "beamcounter" this is where the constants are encoded.
- Again Dennis's brilliant comments make it relatively easy to change the constants. Bear in mind when changing the constants that the clk frequency is no 7.15909MHz
alexh (070727):
- The first thing is the SOF (Start of Frame) signals.
- In PAL they are on lines 312 & 313, and in NTSC they are on 262 and 263.
- So I think this change would be required.
//generate start of frame signal always @(verbeam or lof or sol) if((verbeam==261) && !lof && sol)//end of short frame sof=1; else if((verbeam==262) && lof && sol)//end of long frame sof=1; else sof=0;
How did the later Amigas support both NTSC & PAL?, Piru (070727):
- Only the video output changes, so they don't actually support the other system 100%.
- ECS added beamcon0 bit 5 to toggle between PAL and NTSC preprogrammed modes. See BEAMCON0 bit 5 (PAL).
VBL interrupt is affected.
alexh (070727):
When you select 60Hz (NTSC) the Amiga bus clock changes too. Very noticable as some music playback routines go faster etc. A trick in 3D games was to select NTSC to make them go faster. (Less area to render AND a faster albeit slightly CPU)
alexh (070727):
Most PC LCD monitors will not function below 56Hz which means unless the PAL version of MiniMig can be made to do 60Hz it wont work on PC VGA LCD monitors.
Dennis (070727):
The mclk has to be changed to the NTSC color frequency (and the DCM reprogrammed) and you'll have to make the frames shorter by changing the verbeam compares. But, if I look in the hardware reference manual (page 18, copper), it states that on NTSC machines, the horizontal lines are not all 227 color clocks long. (on Minimig that means 454 bus clocks) Every other line is a long line (228 clocks) from the system's point of view. The display/tv however sees only 227.5 clock lines. So, you will have to do some stuff with the horbeam compares and horizontal sync generator too. That should be all though.
Dennis (070727):
It should be possible to generate both clocks from a single 20Mhz or 50Mhz source. (20Mhz would be better) Someone on the old minimig thread suggested a possible setting of the DCM to do just that; generate all PAL clocks from a single 50Mhz clock using the DCM. If I recall, he was only a couple of ppm off, which should be good enough. You could de the same for NTSC, hence all could be done in software/verilog.
FrenchShark 070729:
Here is the solution I have found based on the ITU-601/656 standards:
Clock source: 27MHz.
27,000,000 / 429 x 455 = 28,636,363 (NTSC clock, 0 ppm)
27,000,000 / 432 x 454 = 28,375,000 (PAL clock, 6 ppm)
Illuwatar 080102:
The DCM of the XC3S400 (and XCS500E) does have some limitation to the divider and multiplier used for internal clock generation (see the datasheet). The multiplier (CLKFX_MULTIPLY) goes from 2 to 30 and the divider (CLKFX_DIVIDE) goes from 1 to 32. Only integers are allowed.
So, using the DCM vaules suggested by FrenchShark will not work as they are too high. I have made a small VB-script in Excel to test all possible frequencies for a given value of the external clock oscillator (MCLK). The closest value at 27 MHz is 28.35 MHz at DCM settings = 21/20. The other two frequencies of interest gave these results:
20 MHz: 28.333333 MHz @ 17/12
50 MHz: 28.333333 MHz @ 17/30
Some other frequencies (based on CFPS-69 SMD crystal oscillators):
14.7456 MHz: 28.356923 MHz @ 25/13
16.384 MHz : 28.398933 MHz @ 26/15
24.000 MHz : 28.363636 MHz @ 13/11 <- NTSC clock, same as at the suggested 27 MHz above
40.000 MHz : 28.387097 MHz @ 22/31
None of these are close enough to the PAL clock of 28.375162 MHz. So, for PAL, we have to stay with the 4.433619 MHz crystal. For NTSC, 24 MHz is an option (and is avaiable as a single component oscillator). For the portable one I'm planning, I have to find a way to loose the 4060 and replace it with something physically smaller.
By the way - the NTSC trick described at the beginning of this page was not working for me. I did exactly as described (I edited the clock_dmc.v directly as I could not find that guide) and loaded it up on my board. The main oscillator got a socket so I could swap crystals. A 3.579545 MHz crystal was found and used and I could see that the system started up correctly. But not with a stable picture at a analog 60 Hz screen (my VGA monitor complained about frequency out of range). So, either I got a faulty crystal (will buy some new ones) or the method described above aren't enough.
Alexh 080212:
We'd also to change the Agnus ID in the VPOSR register to OCS NTSC. in Agnus.v
http://www.winnicki.net/amiga/memmap/VPOSR.html
//beamcounter read registers VPOSR and VHPOSR always @(regaddressin or lof or verbeam or horbeam) if(regaddressin[8:1]==VPOSR[8:1]) dataout[15:0]={lof,2'b0,1'b1,11'b0,verbeam[8]}; else if(regaddressin[8:1]==VHPOSR[8:1]) dataout[15:0]={verbeam[7:0],horbeam[8:1]}; else dataout[15:0]=0;