SVF for C64 found, but it's in verilog...


veqtor

Recommended Posts

The C64 still needs a SVF for it to be complete, but I found one at the fpga.synth.net wiki:

http://fpga.synth.ne...n=FPGASynth.SVF

Unfortunatly it's in verilog so I wouldn't know how to work it into the netsid code.

Looking at the block diagram it seems to me it's just about right. Very little is known about the C64 svf, except it was vanillla and probably done with CMOS inverters and used a crude R2R dac as a variable resistor to control the cutoff. Putting more effort into emulation of that particular svf design could yield somewhat more authentic results but I doubt there'd be much of a difference tbh, what could account for some of character is the output dac from the chip and also the multiplying dac after the filter. Any DC offset on the pre-filter dac would make the filter do weird things while sweeping etc.

looks like the bp and hp outs aren't implemented yet, but that should be easy enough...

edit: just to clarify how to get the other outputs:

HP out could be grabbed from this part:


3'd0:
begin
mA <= f;
mB <= ((DataIn << 18) - mP - z2) >>> 17;
end

where HP is being sent to mB (multiplier b input). Take out that step and send it to a HP register besides sending it to mB.

BP out would be pulled from here:


3'd1:
begin
mA <= f;
mB <= z1 >>> 17;
z1 <= mP + z1;
end

Besides sending mP + z1 back into z1, write it to a BP register.

All that is left then is to make a MUX that sums the various outs so that notch (LP+HP) and such variants can be created.

I hope this can be of some help! ;)

Link to comment
Share on other sites

ISE accept mix language. You should be able to add this filter to NetSID project :

The filter have this prototype in verilog :

// extract from SVF.v

[...]

module SVF(

clk, // system clock

ena, // Tell the filter to go

f, // f (not Hz, but usable to control frequency)

q, // q (1/Q)

DataIn,

DataOut

);

input clk;

input ena;

input signed [17:0] f;

input signed [17:0] q;

input signed [17:0] DataIn; // Data input for one calculation cycle.

output signed [17:0] DataOut; // Data output from this calculation cycle.

[...]

So to use this verilog component into a top instance in vhdl. You need to declare the component prototype

as :

component SVF

port (

clk : in std_logic;

ena : in std_logic;

f : in std_logic_vector (17 downto 0);

q : in std_logic_vector (17 downto 0);

DataIn : in std_logic_vector ( 17 downto 0);

output : std_logic_vector (17 downto 0)

);

end component;

The you can use it in your architecture definition:

[...]

filter_svf : SVF

port map (

clk => clk_DAC,

ena => filter_enable,

f => cut_frequency,

q => quality_factor,

DataIn => sid6581_audio_data,

DataOut => filter_out_to_pwm_sddac

);

[...]

You need to change a little bit NetSID_top.vhd to be able to change f and q of your filter.

But also you need to change the instantiation of u_sid6581. You need to use audio_data to feed your filter and let audio_out 'open'.

A new pwm_sddac should be add to connect the ouput of your filter and the ouput io of the fpga.

So no need to translate the original source file into a vhdl source.

Link to comment
Share on other sites

Good find veqtor, I bookmarked that page. I should be getting close to the point with the RetroCade project where I can start working on adding the analog filters to the SID definition and that should help out. :)

Tb_ is right, its real easy to use verilog in a vhdl design, it's as easy as adding the verilog file to your project then right clicking on it and choosing the option to make the VHDL definition for you. It will create the VHDL component definition and instantiation code for you so you don't have to worry about it.

Jack.

Link to comment
Share on other sites

I came across that SVF filter at that site a while ago and (after of course translating it to VHDL) I promptly expanded the test jig with more input waveforms and implemented all filter type outputs. So as inputs I can select noise, sqware, sine and sawtooth and for outputs I can select lowpass, bandpass, highpass and notch (band stop).

I dug up the test code and made a

to show what it can do. The parameters of the filter are, fsample=800Khz, Q=1 and you can clearly see that even at Q=1 it still amplifies the signal at the filter's cut off frequency. Due to the internal number representation use I cannot lower the Q any more and of course increasing the Q will cause even more amplification to the point of overdriving the output (causing math overflows).

This post has been promoted to an article

Link to comment
Share on other sites

  • 2 months later...

Wicked!

 

I guess the next steps are to pull that into the RetroCade code and look into adding support to play SID files.

 

I see two approaches for SID files:

1) Have AcidSid dump the files into an easy to handle format that just writes to the registers directly. The benefit of that is it will use less processing power on the ZPUino.

2) I started working on getting the tinySID library to work on the RetroCade. It emulates a C64 and can interpret the ASM stored in SID files and in turn write to the SID registers.

 

tinySID has already been ported to the PIC and should be straight forward to do the same to ZPUino:

http://code.google.com/p/dangerous-prototypes-open-hardware/source/browse/trunk/Web_Platform/firmware/SID/

 

I actually started down that route but ran into problems with floating point and never got the time to ping Alvaro about any solutions he already might have in place.

 

Jack.

Link to comment
Share on other sites

Heh the video turns out to be a bit misleading. The filter is not ready for prime time as it too has problems with floating point. Some SID files seem to play ok others will have the filter cause massive distortion so heaps more work need to be done.

If anyone is volunteering to help out it may happen sooner otherwise I'll work on it on and off as time permits.

Link to comment
Share on other sites

Here is what I have so far. This needs a Papilio One because the Xilinx RS232 IP core just won't compile and work properly on the LX9. The .ucf is for a standard Megawing.

 

I have added a "tests" directory with a few SID files that should give the filter a good workout. I suggest you listen to them with a proper SID player (I recommend ACID64/Jsidplay combo on Windows) to see what sound you should expect. The sounds produced by the FPGA are tantalizingly close but not quite there. For example "Hell Machine" produces clicks every so often, possibly math over/under flow, "Exkrement" playing just channel 1 shows that the filtered voice sounds almost correct after filtering.

 
The reason some voices are close but not quite there is because I'm feeding the SID FC register value directly to the filter's F1 value. Neither of these is in fact the "Filter Cutoff" value. The SID register value can go from 0 to 2047 and represents a filter cutoff value between 30 - 10000 Hz so I guess the SID FC converts to Fc with approximately Fc = FC * 10Khz  / 2047
 
The internal filter F1 value is related to the filter Fc value by the approximate formula F1 = 2 * pi * Fc / Fs where Fs is the filter sampling rate (1Mhz here) so subsituting the SID conversion from above we have F1 = FC / 32579 which would imply the use of a float or fixed point arithmetic.
 
Link to comment
Share on other sites

  • 5 years later...

Sorry to bring a very old thread back to life but this looks like just what I need. I'm working on another 70s Atari arcade game called Subs and need a SVF filter for the sonar ping sound circuits, this is the only part I have not yet completed. I'm a novice when it comes to DSP techniques and until this came up I was actually not familiar with the concept of the SVF filter at all, it's an interesting concept though.

 

Anyway what I need is a pair of filters (two separate input and output channels) bandpass with a 1kHz center frequency. The source is a decaying envelope of white noise from a LFSR which I can make any width necessary. Could somebody give me a few pointers on integrating the filter out of this project into my own and setting up the parameters? I will of course share the code for my project when I'm finished.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.