Electronics > FPGA

FPGA VGA Controller for 8-bit computer

<< < (686/725) > >>

BrianHG:
Here is a snipet of my floating point clock divider:

--- Code: ---// Forcing 64 bits is required due to a ModelSim internal bug where if 'PLL1_OUT_TRUE_HZ*4096' exceedes 31 bits, it's considered negative and cropped
// when computing the localparam.  So, never use 'localparam int' when going above 2 billion anywhere inside, or you will get bogus results.
localparam bit [63:0] aud_per_x4096  = PLL1_OUT_TRUE_HZ*4096/HDPLL_AUDIO_HZ ;                               // Determine the audio period 4096 fold.
localparam bit [63:0] aud_per_round  = aud_per_x4096 + 2048 ;                                               // Prepare a rounded version.
localparam bit [12:0] aud_per_int    = HDPLL_AUDIO_TCK_FLOAT ? aud_per_x4096[24:12] : aud_per_round[24:12]; // Select between the rounded integer period or true integer period.
localparam bit [11:0] aud_per_f      = HDPLL_AUDIO_TCK_FLOAT ? aud_per_x4096[11:0]  : 12'd0  ;              // select between no floating point and floating point adjusted audio clock generation.
localparam bit [63:0] aud_tru_hz     = PLL1_OUT_TRUE_HZ*4096 / (aud_per_int*4096+aud_per_f)  ;              // Calculate the true audio output clock based on oscilator frequencies & HDPLL_AUDIO_TCK_FLOAT settings.

assign          clk_audio_true_hz    = 32'( aud_tru_hz );        // pass the true audio sample frequency to an output port.
assign          clk_pixel_true_hz    = 32'( PLL1_OUT_TRUE_HZ ) ; // pass the true pixel clock frequency to an output port.

logic   [12:0]  aud_cnt_m  = 13'd0;
logic   [12:0]  aud_cnt_n  = 13'd0;

always_ff @(posedge clk_pixel) begin

if ( aud_cnt_m == (aud_per_int - !aud_cnt_n[12]) ) begin                          // Add 1 extra count to the period if the carry flag aud_cnt_n[12] is set.
                                        aud_cnt_m        <= 13'd0;
                                        audio_ena        <= 1'b1;
                                        clk_audio        <= 1'b1;
                                        aud_cnt_n        <= aud_cnt_n[11:0] + (aud_per_f) ; // add the floating point period while clearing the carry flag aud_cnt_n[12].
                        end else begin
                                        aud_cnt_m        <= aud_cnt_m + 1'b1;
                                        audio_ena        <= 1'b0;
                        if (aud_cnt_m[11:0]==aud_per_int[12:1]) clk_audio <= 1'b0; // generate an aproximate 50/50 duty cycle clk_audio output.
                        end

end
--- End code ---

You need to simulate this one on it's own, making a testbench which provides a 100mhz clock and counting the ' audio_ena ' over a 0.1 second and 1 second optional.  You may use your clock divider instead.

You will need to add the input and output ports on the module.  Maybe a reset as well.  Rename the pixel clock to clk.  Add 2 parameters, a clock frequency in parameter and a clock output parameter in hz.

Once tested as is, we will increase the floating point bits from 12 to 16 or 24 depending on your tolerance for the final average frequency error of the output 1.78MHz.

Let's see your edits and sim just for this module.

This code was located at the bottom on my 'HDMI_PLL.sv' inside my HDMI serializer project.

BrianHG:
Line 956:

--- Code: ---ym2149_audio ARYA(

   // inputs
   .clk_i        ( CMD_CLK     ), // system clock
   .en_clk_psg_i ( strb_ovrd   ), // PSG clock enable strobe - 1.6875 MHz
   .sel_n_i      ( 1'b1        ), // divide select, 0 = clock-enable/2
   .reset_n_i    ( !reset      ), // active low
   .bc_i         ( psg_ctrl[0] ), // bus control
   .bdir_i       ( psg_ctrl[1] ), // bus direction
   .data_i       ( psg_data_i  ), // (7:0)
   // outputs
   .data_r_o     ( psg_data_o  ), // (7:0) -- registered output data
   .ch_a_o       (             ), // (11:0)
   .ch_b_o       (             ), // (11:0)
   .ch_c_o       (             ), // (11:0)
   .mix_audio_o  (             ), // (13:0)
   .pcm14s_o     ( pcm_14_o    ), // (13:0)   <<<<<<<<<<<<<<<<<<<<

--- End code ---

Instead of the pcm14s_o, shouldn't you be using the mix_audio_o ?

Also, I looked at your 'clock_strobe', don't you want the 1.789MHz?

Also, you cannot use a clock enable to cross clock domains from the CLK_54MHz CMD_CLK, which may be 100MHz, or 75MHz, or 150Mhz.  This will cause random tone glitch clocking assuming my guesses about how the PSG works is correct.

Fix up my example code in the above post and run it from the CMD_CLK and create proper parameter inputs and a test bench to time the output and see how it works so you may extend it's precision.

nockieboy:

--- Quote from: BrianHG on July 10, 2022, 12:37:49 am ---Instead of the pcm14s_o, shouldn't you be using the mix_audio_o ?
--- End quote ---

Maybe? :-\  Have switched to the mixed output (adding 2 LSbs to make it 16-bit).  Seems to sound more authentic now. :-+


--- Quote from: BrianHG on July 10, 2022, 12:37:49 am ---Also, I looked at your 'clock_strobe', don't you want the 1.789MHz?
--- End quote ---

As close to it as I can get, but for testing it's not essential.  It'll just move the sound output higher or lower in the pitch range compared to the target systems of the 80's.  It's pretty much on the nose as far as I can tell, using SignalTap to calculate the pulse width (it needs to be 559ns).  Ignore the comments with other frequencies, I forgot to change/update them before posting that code, sorry. ::)


--- Quote from: BrianHG on July 10, 2022, 12:37:49 am ---Also, you cannot use a clock enable to cross clock domains from the CLK_54MHz CMD_CLK, which may be 100MHz, or 75MHz, or 150Mhz.  This will cause random tone glitch clocking assuming my guesses about how the PSG works is correct.
--- End quote ---

Yes, I suspect this is the cause of a fair bit of interference in the output currently.  I think the PSG updates and outputs a new value every clock enable, so random/out-of-sync pulses on that line will cause glitches.  I knew this would be an issue when I initially solved the problem of the PSG missing IO RD/WRs from the host because of its slow clock speed. Injecting clk_ens to force the PSG to react to asynchronous IO interactions is, no doubt, causing sound issues too.  These are the two big problems I know I need to fix.

The interface speed issue will require some clever thinking, or editing of the PSG module itself to accept asynchronous interface commands and respond to them immediately (or on the next clock enable if the sound registers are being updated).  :-/O

nockieboy:

--- Quote from: nockieboy on July 10, 2022, 07:54:54 am ---Yes, I suspect this is the cause of a fair bit of interference in the output currently.  I think the PSG updates and outputs a new value every clock enable, so random/out-of-sync pulses on that line will cause glitches.  I knew this would be an issue when I initially solved the problem of the PSG missing IO RD/WRs from the host because of its slow clock speed. Injecting clk_ens to force the PSG to react to asynchronous IO interactions is, no doubt, causing sound issues too.  These are the two big problems I know I need to fix.

The interface speed issue will require some clever thinking, or editing of the PSG module itself to accept asynchronous interface commands and respond to them immediately (or on the next clock enable if the sound registers are being updated).  :-/O
--- End quote ---

That being said, switching from CLK_54 to CMDCLK for the PSG clock source seems to have cleared up just about all the problems.  I just need to sort out the correct divisor, but the tone output I got just now was really good.  My concerns re: the interface and botching asynchronous IO interactions actually seems to have a really minor, if any, effect. ^-^

BrianHG:

--- Quote from: nockieboy on July 10, 2022, 08:03:26 am ---
--- Quote from: nockieboy on July 10, 2022, 07:54:54 am ---Yes, I suspect this is the cause of a fair bit of interference in the output currently.  I think the PSG updates and outputs a new value every clock enable, so random/out-of-sync pulses on that line will cause glitches.  I knew this would be an issue when I initially solved the problem of the PSG missing IO RD/WRs from the host because of its slow clock speed. Injecting clk_ens to force the PSG to react to asynchronous IO interactions is, no doubt, causing sound issues too.  These are the two big problems I know I need to fix.

The interface speed issue will require some clever thinking, or editing of the PSG module itself to accept asynchronous interface commands and respond to them immediately (or on the next clock enable if the sound registers are being updated).  :-/O
--- End quote ---

That being said, switching from CLK_54 to CMDCLK for the PSG clock source seems to have cleared up just about all the problems.  I just need to sort out the correct divisor, but the tone output I got just now was really good.  My concerns re: the interface and botching asynchronous IO interactions actually seems to have a really minor, if any, effect. ^-^

--- End quote ---
Read my clock divider code at the top of this page.........
Adapt it....
Clean it up a little.....
Use it......
It will make any frequency you like with 2 parameter inputs.
Simulate it and see.
Show me your work.
Also, with a sample rate of 1.7Mhz for the PSG, a little jitter of +/-5ns there would not be heard.


As for sending commands, aren't they an async separate event from the 1.7mhz strobe?
Don't they take effect immediately, or aren't they latched once a block is sent?
You do have the link I sent earlier to the Verilog version of the PSG, right?

Navigation

[0] Message Index

[#] Next page

[*] Previous page

There was an error while thanking
Thanking...
Go to full version