hamster

Content Count
504 
Joined

Last visited

Days Won
79
Posts posted by hamster


Phew... not putting a space for "the perfect frequency" clock isn't a worry anymore, as 12MHz * 64 / 31.25 = 25.576MHz, the required for 48kHz sample rate and this is just within the range of the MMCM block.
Most likely has lessthanideal jitter and noise specs for hifi buffs, but should be perfectly adequate for my needs.

I've got a few project ideas around a digital crossover for biamped speakers...
I had the DACs left over from building a few stereo I2S boards with PMOD interfaces, but found using many of them at once was getting impractical  if I had to tidy my desk I would waste a lot of time connecting things up again when I got back to playing with them.
The other reason for these chips is they are really, really dumb and simple to use. No preamp or signal routing to configure, no I2C management needed  just send the correct clocks and they send back the correct data.
Dumb parts are also cheap parts  the DACs were $0.50, the ADCs are ~$1.00, the sockets are $0.40, making this around a $20 project...
I've just had that pang of "I've sent the board away too early".
On thing I should have done is added a few extra pads to allow for strapping resistors on the ADCs to configure them, but is is unclear to me how they will interact with the FPGA's pin's default state while the FPGA is being configured.
I should have also have added a 24.576 MHz Oscillator too,... so I could run at 48kHz, not the 46.875KHz I'll be running at from the onboard 12MHz clock.
Oh, and then...
... maybe I should have added a version number on the PCB too!


Maybe remove the 'reg' from the Verilog port definition?

I've done it before without issue, and all I can suggest is that you look carefully at your component/module names and especially uppercase / lowercase.
Maybe add some code snippets to the thread?

The Vivado virtual logic analyser is very easy to set up and use, and will give you the most accurate result for minimal effort

This little project might give you some ideas  it controls the speed of the dev board's fan based on the XADC reading. It also uses no IP blocks so everything is exposed.

As a gross oversimplification, FPGAs only have clocked flipflops that can store state information.
You can use variables to store state rather than signals, but they have to be used in such a way that they can be mapped down to flipflops.
Without using a clock edge in the HDL code this can't happen, and all sorts of weird stuff happens.

Hi again,
Changed the XDC file, and to run it on a board  it didn't work for me either.
There are a few synthesis issues that need to be addressed (both of which were pointed out as warning in the logs, BTW):
1. input needs to be added on this process's sensitivity list:
process(present_state,data,clk,rst,start, input)
2. The major problem  you are updating count and index_reg inside the async process:
count:=count+1;
and
index:=index+1;
You can't do this, as conceptually the process is "run" each time any of the input signals change state. If you want to work with the similar structure you need to assign count_next and index_next inside the async process, then assign them to count and index in the clocked one.
Oh, and another tiny issue  if you want to do something every 10400 cycles, you need to count from 0 to 10399.

Looking at the reference manual, if you intend to use the onboard USB to serial Bridge then your output pin should be A18
https://reference.digilentinc.com/basys3/refmanual

I wrote a quick test bench. I couldn''t get it out of 'idle' state because of this code:
if start='1' and rst='0' then count:=count+1; if count=clk_max then next_state<=start_state; count:=0; end if; end if;
I asserted 'start' for only one cycle, and nothing happened. I see now that I need to assert it for up to 10,400 cycles before it will send data. Will let you know how testing progresses.
Also, the async reset is a slightly unusual design pattern for FPGA designs. Synchronous resets (with a properly synchronised reset signal) work better.
Here is the test bench so far.
library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity tb is end tb; architecture Behavioral of tb is component rs232_omo is generic(clk_max:integer:=10400); for baudrate port( clk : in std_logic; rst : in std_logic; start : in std_logic; input : in std_logic_vector(7 downto 0); done : out std_logic; output : out std_logic; showstates : out std_logic_vector(3 downto 0) ); end component ; signal clk : std_logic; signal rst : std_logic := '0'; signal start : std_logic := '0'; signal input : std_logic_vector(7 downto 0) := x"55"; signal done : std_logic; signal output : std_logic; signal showstates : std_logic_vector(3 downto 0); begin process begin clk <= '0'; wait for 5ns; clk <= '1'; wait for 5ns; end process; process begin wait for 100ns; rst <= '1'; wait for 20ns; rst <= '0'; wait for 100ns; start <= '1'; wait for 10ns; start <= '0'; wait; end process; uut: rs232_omo generic map (clk_max => 10400) port map( clk => clk, rst => rst, start => start, input => input, done => done, output => output, showstates => showstates ); end Behavioral;

I haven't looks at the code too much, but I did notice that you don't appear to have synchronizers on your external connections that control the state machine (start and reset).
Although this is most likely not your problem it will cause inconsistent behaviour.
Are you also sure you haven't got the Tx/Rx pins back to front, as naming depends on the designer perspective and whims on the day

1 hour ago, Ahmed Alfadhel said:Hi ,
Thank u @hamster for your elaboration about Hilbert Transform. I modified your code to work with my design , as follow:
Hilbert Transformer library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity hilbert_transformer is Port ( clk : in STD_LOGIC; real_in : in STD_LOGIC_VECTOR (23 downto 0); real_out : out STD_LOGIC_VECTOR (24 downto 0) := (others => '0'); imag_out : out STD_LOGIC_VECTOR (24 downto 0) := (others => '0')); end hilbert_transformer; architecture Behavioral of hilbert_transformer is  Constants are 2/(n * pi) * 512, for n of 7,5,3,1,1,3,5,7 constant kernel0 : signed(real_in'length1 downto 0) := to_signed( 47, real_in'length); constant kernel2 : signed(real_in'length1 downto 0) := to_signed( 66, real_in'length); constant kernel4 : signed(real_in'length1 downto 0) := to_signed(109, real_in'length); constant kernel6 : signed(real_in'length1 downto 0) := to_signed(326, real_in'length); constant kernel8 : signed(real_in'length1 downto 0) := to_signed( 326, real_in'length); constant kernel10 : signed(real_in'length1 downto 0) := to_signed( 109, real_in'length); constant kernel12 : signed(real_in'length1 downto 0) := to_signed( 66, real_in'length); constant kernel14 : signed(real_in'length1 downto 0) := to_signed( 47, real_in'length); type a_delay is array (0 to 14) of signed(real_in'high downto 0); signal delay : a_delay := (others => (others => '0')); signal tap0 : signed(real_in'length+kernel0'length1 downto 0) := (others => '0'); signal tap2 : signed(real_in'length+kernel2'length1 downto 0) := (others => '0'); signal tap4 : signed(real_in'length+kernel4'length1 downto 0) := (others => '0'); signal tap6 : signed(real_in'length+kernel6'length1 downto 0) := (others => '0'); signal tap8 : signed(real_in'length+kernel8'length1 downto 0) := (others => '0'); signal tap10 : signed(real_in'length+kernel10'length1 downto 0) := (others => '0'); signal tap12 : signed(real_in'length+kernel12'length1 downto 0) := (others => '0'); signal tap14 : signed(real_in'length+kernel14'length1 downto 0) := (others => '0'); begin process(clk) variable imag_tmp : signed(real_in'length*21 downto 0); begin if rising_edge(clk) then real_out <= std_logic_vector(resize(delay(8),real_out'length));  deliberatly advanced by one due to latency imag_tmp := tap0 + tap2 + tap4 + tap6 + tap8 + tap10 + tap12 + tap14; imag_out <= std_logic_vector(imag_tmp(imag_tmp'high downto imag_tmp'highimag_out'high)); tap0 <= delay(0) * kernel0; tap2 <= delay(2) * kernel2; tap4 <= delay(4) * kernel4; tap6 <= delay(6) * kernel6; tap8 <= delay(8) * kernel8; tap10 <= delay(10) * kernel10; tap12 <= delay(12) * kernel12; tap14 <= delay(14) * kernel14;  Update the delay line delay(1 to 14) <= delay(0 to 13) ; delay(0) <= signed(real_in); end if; end process; end Behavioral;
and
 magnitude IP library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity magnitude is Port ( clk : in std_logic; x_in : in std_logic_vector(24 downto 0); y_in : in std_logic_vector(24 downto 0); x_out : out std_logic_vector(24 downto 0) := (others => '0'); y_out : out std_logic_vector(24 downto 0) := (others => '0'); magnitude_out : out std_logic_vector(24 downto 0) := (others => '0')  Accurate to 5 bits or so ); end magnitude; architecture Behavioral of magnitude is type a_x is array(0 to 5) of signed(x_in'high+1 downto 0); type a_y is array(0 to 5) of signed(y_in'high+1 downto 0); type a_x_delay is array(0 to 5) of std_logic_vector(x_in'high downto 0); type a_y_delay is array(0 to 5) of std_logic_vector(y_in'high downto 0);  line 23 (error occured here) signal x : a_x(24 downto 0) := (others => (others => '0')); signal y : a_y(24 downto 0) := (others => (others => '0')); signal x_delay : a_x_delay(24 downto 0) := (others => (others => '0')); signal y_delay : a_y_delay(24 downto 0) := (others => (others => '0')); begin magnitude_out <= std_logic_vector(y(5)); x_out <= x_delay(x_delay'high); y_out <= y_delay(y_delay'high); process(clk) begin if rising_edge(clk) then if x(4) >= 0 then  x(5) is not needed y(5) <= y(4) + x(4)(x(4)'high downto 4); else  x(5) is not needed y(5) <= y(4)  x(4)(x(4)'high downto 4); end if; if x(3) >= 0 then x(4) <= x(3)  y(3)(y(3)'high downto 3); y(4) <= y(3) + x(3)(x(3)'high downto 3); else x(4) <= x(3) + y(3)(y(3)'high downto 3); y(4) <= y(3)  x(3)(x(3)'high downto 3); end if; if x(2) >= 0 then x(3) <= x(2)  y(2)(y(2)'high downto 2); y(3) <= y(2) + x(2)(x(2)'high downto 2); else x(3) <= x(2) + y(2)(y(2)'high downto 2); y(3) <= y(2)  x(2)(x(2)'high downto 2); end if; if x(1) >= 0 then x(2) <= x(1)  y(1)(y(1)'high downto 1); y(2) <= y(1) + x(1)(x(1)'high downto 1); else x(2) <= x(1) + y(1)(y(1)'high downto 1); y(2) <= y(1)  x(1)(x(1)'high downto 1); end if; if x(0) >= 0 then x(1) <= x(0)  y(0)(y(0)'high downto 0); y(1) <= y(0) + x(0)(x(0)'high downto 0); else x(1) <= x(0) + y(0)(y(0)'high downto 0); y(1) <= y(0)  x(0)(x(0)'high downto 0); end if; if y_in(y_in'high) = '1' then x(0) <= signed(x_in(x_in'high) & x_in); y(0) <= signed(to_signed(0,y_in'length+1)signed(y_in)); else x(0) <= signed(x_in(x_in'high) & x_in); y(0) <= signed(y_in(y_in'high) & y_in); end if;  Delay to output the inputs, so they are aligned with the magnitudes x_delay(1 to 5) <= x_delay(0 to 4); y_delay(1 to 5) <= y_delay(0 to 4); x_delay(0) <= x_in; y_delay(0) <= y_in; end if; end process; end Behavioral;
and I used my own test bench :
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.numeric_std.all; use std.textio.all ; use ieee.std_logic_textio.all ;  Entity entity FHSS_TX_Test_Bench_sim is end;  Architecture architecture test of FHSS_TX_Test_Bench_sim is  Our UART Transmitter Design Instantiation component FH_modem_wrapper port ( BFSK : out STD_LOGIC_VECTOR ( 7 downto 0 ); FH : out STD_LOGIC_VECTOR ( 7 downto 0 ); spreaded_signal : out STD_LOGIC_VECTOR ( 7 downto 0 ); despreaded : out STD_LOGIC_VECTOR ( 7 downto 0 ); IF_BPF : out STD_LOGIC_VECTOR (23 downto 0); x : out STD_LOGIC_VECTOR ( 24 downto 0 ); y : out STD_LOGIC_VECTOR ( 24 downto 0 ); mag_out : out STD_LOGIC_VECTOR ( 24 downto 0 ); absolute2 : out STD_LOGIC_VECTOR ( 23 downto 0 ); envelop : out STD_LOGIC_VECTOR ( 47 downto 0 ); sys_clock : in STD_LOGIC; reset : in STD_LOGIC ); end component;  Simulation signals signal clk_sim : std_logic := '0'; signal reset : std_logic := '1'; signal BFSK : std_logic_vector(7 downto 0); signal FH : std_logic_vector(7 downto 0); signal spreaded_signal : std_logic_vector(7 downto 0); signal despreaded : std_logic_vector(7 downto 0); signal IF_BPF : std_logic_vector(23 downto 0); signal x : std_logic_vector(24 downto 0); signal y : std_logic_vector(24 downto 0); signal mag_out : std_logic_vector(24 downto 0); signal absolute2 : STD_LOGIC_VECTOR ( 23 downto 0 ); signal envelop : STD_LOGIC_VECTOR ( 47 downto 0 ); begin  UART Transmitter port mapping dev_to_test: FH_modem_wrapper port map(BFSK, FH, spreaded_signal, despreaded, IF_BPF, x, y, mag_out, absolute2,envelop, clk_sim, reset );  Simulate the input clock to our design clk_proc : process begin wait for 5 ns; clk_sim <= not clk_sim; end process clk_proc; end test;
But when I run the simulation , I get on this error:
[VRFC 109] a_x already imposes an index constraint ["D:/Users/dell/Complex_Envelop_detector_15kHzIF_Fig2/modem/modem.ip_user_files/bd/FH_modem/ipshared/e786/sim/magnitude.vhd":23]
I had pointed to the line 23 by a comment before it.
How to solve this error?
I am looking forward your reply.
Thanks.The error is because the magnitude as to be one bit longer than the inputs, (as the magnitude of (0xFFFFFF, 0xFFFFFF) is 0x16A09E4, which will overflow if you put it into a 25bit signed value.
It will however fit nicely into a 25bit unsigned value, and as it is a magnitude it will be positive. So maybe snip off the top bit in the assignment, but remember it is unsigned!
Ahmed Alfadhel reacted to this 
33 minutes ago, xc6lx45 said:But this would an example where it's trivially easy to generate the reference tone in quadrature. Multiply with the complexvalued reference tone, lowpassfilter to suppress the shifted negative frequency component and there's my analytical ("onesided spectrum") signal for polar processing.
Using a tool for what it is meant to do is easy. Using a tool for something where it isn't suited, that is where the learning begins!
(I now goes back to doing dental surgery with a steamroller, or maybe digging a tunnel with a teaspoon).
Ahmed Alfadhel reacted to this 
Oh, a quick hack of a CORDIC magnitude
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity magnitude is Port ( clk : in std_logic; x_in : in std_logic_vector; y_in : in std_logic_vector; x_out : out std_logic_vector := (others => '0'); y_out : out std_logic_vector := (others => '0'); magnitude_out : out std_logic_vector := (others => '0')  Accurate to 5 bits or so ); end magnitude; architecture Behavioral of magnitude is type a_x is array(0 to 5) of signed(x_in'high+1 downto 0); type a_y is array(0 to 5) of signed(y_in'high+1 downto 0); type a_x_delay is array(0 to 5) of std_logic_vector(x_in'high downto 0); type a_y_delay is array(0 to 5) of std_logic_vector(y_in'high downto 0); signal x : a_x := (others => (others => '0')); signal y : a_y := (others => (others => '0')); signal x_delay : a_x_delay := (others => (others => '0')); signal y_delay : a_y_delay := (others => (others => '0')); begin magnitude_out <= std_logic_vector(y(5)); x_out <= x_delay(x_delay'high); y_out <= y_delay(y_delay'high); process(clk) begin if rising_edge(clk) then if x(4) >= 0 then  x(5) is not needed y(5) <= y(4) + x(4)(x(4)'high downto 4); else  x(5) is not needed y(5) <= y(4)  x(4)(x(4)'high downto 4); end if; if x(3) >= 0 then x(4) <= x(3)  y(3)(y(3)'high downto 3); y(4) <= y(3) + x(3)(x(3)'high downto 3); else x(4) <= x(3) + y(3)(y(3)'high downto 3); y(4) <= y(3)  x(3)(x(3)'high downto 3); end if; if x(2) >= 0 then x(3) <= x(2)  y(2)(y(2)'high downto 2); y(3) <= y(2) + x(2)(x(2)'high downto 2); else x(3) <= x(2) + y(2)(y(2)'high downto 2); y(3) <= y(2)  x(2)(x(2)'high downto 2); end if; if x(1) >= 0 then x(2) <= x(1)  y(1)(y(1)'high downto 1); y(2) <= y(1) + x(1)(x(1)'high downto 1); else x(2) <= x(1) + y(1)(y(1)'high downto 1); y(2) <= y(1)  x(1)(x(1)'high downto 1); end if; if x(0) >= 0 then x(1) <= x(0)  y(0)(y(0)'high downto 0); y(1) <= y(0) + x(0)(x(0)'high downto 0); else x(1) <= x(0) + y(0)(y(0)'high downto 0); y(1) <= y(0)  x(0)(x(0)'high downto 0); end if; if y_in(y_in'high) = '1' then x(0) <= signed(x_in(x_in'high) & x_in); y(0) <= signed(to_signed(0,y_in'length+1)signed(y_in)); else x(0) <= signed(x_in(x_in'high) & x_in); y(0) <= signed(y_in(y_in'high) & y_in); end if;  Delay to output the inputs, so they are aligned with the magnitudes x_delay(1 to 5) <= x_delay(0 to 4); y_delay(1 to 5) <= y_delay(0 to 4); x_delay(0) <= x_in; y_delay(0) <= y_in; end if; end process; end Behavioral;
Chaining the two together, and it seems to work. Top trace is the input, second trace is the delayed input,
Third is the delayed output of the Hilbert filter, and the last is the scaled magnitude of the complex x+iy signal.
NOTE: I know for sure that these are buggy, as they have range overflows), but they should give the idea of how @Ahmed Alfadhel could be implement it.
magnitude.vhd hilbert_transformer.vhd tb_hilbert_transformer.vhd
Ahmed Alfadhel reacted to this 
11 hours ago, D@n said:Not bad, not bad at all ... just some feedback for you though:
 The "official" Hilbert transform tap generation suffers from the same Gibbs phenomena that keeps folks from using the "ideal lowpass filter" (i.e. sin x/x)
 You could "window" the filter to get better performance, or you could try using ParksMcClellan to get better taps. There are tricks to designing filters with quantized taps as well ... however the ones I know are adhoc and probably about the same as what you did above
 There's symmetry in the filter. For half as many multiplies you can take sample differences, and then apply the multiplies to those sample differences.
Other than that, pretty cool! Did you find anything useful to test it on?
Dan
Going to Incorporate it into my (MCU based) guitar tuner... but it is a nice tool to have in the kit.
Ahmed Alfadhel reacted to this 
I was intrigued enough by the Hilbert Transform to actually learn, experiment and implement it in VHDL. The math behind it is pretty nifty.
Here's the very naively implemented example, using a short FIR filter.
You can find this, a test bench and simulation output at http://hamsterworks.co.nz/mediawiki/index.php/Hilbert_Transform
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity hilbert_transformer is Port ( clk : in STD_LOGIC; real_in : in STD_LOGIC_VECTOR (9 downto 0); real_out : out STD_LOGIC_VECTOR (10 downto 0) := (others => '0'); imag_out : out STD_LOGIC_VECTOR (10 downto 0) := (others => '0')); end hilbert_transformer; architecture Behavioral of hilbert_transformer is  Constants are 2/(n * pi) * 512, for n of 7,5,3,1,1,3,5,7 constant kernel0 : signed(real_in'length1 downto 0) := to_signed( 47, real_in'length); constant kernel2 : signed(real_in'length1 downto 0) := to_signed( 66, real_in'length); constant kernel4 : signed(real_in'length1 downto 0) := to_signed(109, real_in'length); constant kernel6 : signed(real_in'length1 downto 0) := to_signed(326, real_in'length); constant kernel8 : signed(real_in'length1 downto 0) := to_signed( 326, real_in'length); constant kernel10 : signed(real_in'length1 downto 0) := to_signed( 109, real_in'length); constant kernel12 : signed(real_in'length1 downto 0) := to_signed( 66, real_in'length); constant kernel14 : signed(real_in'length1 downto 0) := to_signed( 47, real_in'length); type a_delay is array (0 to 14) of signed(real_in'high downto 0); signal delay : a_delay := (others => (others => '0')); signal tap0 : signed(real_in'length+kernel0'length1 downto 0) := (others => '0'); signal tap2 : signed(real_in'length+kernel2'length1 downto 0) := (others => '0'); signal tap4 : signed(real_in'length+kernel4'length1 downto 0) := (others => '0'); signal tap6 : signed(real_in'length+kernel6'length1 downto 0) := (others => '0'); signal tap8 : signed(real_in'length+kernel8'length1 downto 0) := (others => '0'); signal tap10 : signed(real_in'length+kernel10'length1 downto 0) := (others => '0'); signal tap12 : signed(real_in'length+kernel12'length1 downto 0) := (others => '0'); signal tap14 : signed(real_in'length+kernel14'length1 downto 0) := (others => '0'); begin process(clk) variable imag_tmp : signed(real_in'length*21 downto 0); begin if rising_edge(clk) then real_out <= std_logic_vector(resize(delay(8),real_out'length));  deliberatly advanced by one due to latency imag_tmp := tap0 + tap2 + tap4 + tap6 + tap8 + tap10 + tap12 + tap14; imag_out <= std_logic_vector(imag_tmp(imag_tmp'high downto imag_tmp'highimag_out'high)); tap0 <= delay(0) * kernel0; tap2 <= delay(2) * kernel2; tap4 <= delay(4) * kernel4; tap6 <= delay(6) * kernel6; tap8 <= delay(8) * kernel8; tap10 <= delay(10) * kernel10; tap12 <= delay(12) * kernel12; tap14 <= delay(14) * kernel14;  Update the delay line delay(1 to 14) <= delay(0 to 13) ; delay(0) <= signed(real_in); end if; end process; end Behavioral;
Ahmed Alfadhel reacted to this 
Oh, for what it's worth I've been toying with the Hilbert Transform. Here is a example of it;
#include <math.h> #include <stdio.h> #define SAMPLES 1000 #define HALF_WIDTH 11 /* e.g. 11 filters from 11 to 11 */ float x[SAMPLES]; int main(int argc, char *argv[]) { int i; /* Build some test data */ for(i = 0; i < SAMPLES; i++) { x[i] = cos(2*M_PI*i/10.3); } /* Now apply the Hilbert Transform and see what we get */ /* It should be close to sin(2*M_PI*i/10.3) */ for(i = HALF_WIDTH; i < SAMPLESHALF_WIDTH1; i++) { double h = 0; int j; /* Apply the kernel */ for(j = 1; j <= HALF_WIDTH; j+=2) h += (x[ij]x[i+j]) * 2.0/(j*M_PI); /* Print result */ printf("%8.5f, %8.5f\n", x[i], h); } }
Ahmed Alfadhel reacted to this 
Oh having a look at the full signal chain, it looks like you just need to apply a lowpass filter on the absolute value of the signal. It might be just as simple as:
if sample < 0 then filter := filter  filter/64  sample; else filter := filter  filter/64 + sample; end if;
With the value of "64" change depending on your sample rates and desired cutoff frequency. Or if your needs get very complex you might need to use a FIR low pass filter.
Run some sample data through it in Matlab or Excel (or heavens forbid, some C code) and see what happens.
Ahmed Alfadhel reacted to this 
I had the C code handy because I have been working on an atan2(y,x) implementation for FPGAs, and had been testing ideas.
I left it in C because I don't really know your requirements, but I wanted to give you a working algorithm, complete with proof that it does work, and so you can tinker with it, see how it works, and make use of it. Oh, and I must admit that it was also because I am also lazy 😀
But seriously:
 I don't know if you use VHDL or Verilog, or some HLS tool
 I don't know if your inputs are 4 bits or 40 bits long,
 I don''t know if you need the answer to be within 10% or 0.0001%
 I don't know if it has to run at 40Mhz or 400Mhz
 I don't know if you have 1000s of cycles to process each sample, or just one.
 I don't even know if you need the algorithm at all!
But it has been written to be trivially converted to any HDL as it only uses bit shifts and addition/subtraction. But maybe more importantly you can then use it during any subsequent debugging to verify that you correctly implemented it.
For an example of how trivial it is to convert to HDL:
if(x > 0) { x += ty/8; y += tx/8;} else { x += ty/8; y += tx/8;}
could be implemented as
IF x(x'high) = '0' THEN x := x  resize(y(y'high downto 3), y'length); y := y + resize(x(x'high downto 3), x'length); ELSE x := x + resize(y(y'high downto 3), y'length); y := y  resize(x(x'high downto 3), x'length); END IF
My suggestion is that should you choose to use it, compile the C program, making the main() function a sort of test bench, and then work out exactly what you need to implement in your HDL., You will then spend very little time writing, debugging and improving the HDL because you will have a very clear idea of what you are implementing.
Ahmed Alfadhel reacted to this 
Um, are you sure that you are asking the right question?
if the signal is BFSK, it should have pretty much a constant envelope, as only the frequency is changed?

Hi, Sorry to barge in, but if anybody can point me to the Hibbert Transformer info I would be very grateful.
However, here is an FPGA friendly way to calculate mag = sqrt(x*x+y*y), with about a 99% accuracy. You can easily see the pattern to get whatever accuracy you need.
#include <math.h> #include <stdio.h> #define M_SCALE (16) /* Scaling for the magnitude calc */ void cordic_mag(int x,int y, int *mag) { int tx, ty; x *= M_SCALE; y *= M_SCALE; /* This step makes the CORDIC gain about 2 */ if(y < 0) { x = (x+x/4x/32x/256); y = (y+y/4y/32y/256); } else { x = (x+x/4x/32x/256); y = (y+y/4y/32y/256); } tx = x; ty = y; if(x > 0) { x += ty/1; y += tx/1;} else { x += ty/1; y += tx/1;} tx = x; ty = y; if(x > 0) { x += ty/2; y += tx/2;} else { x += ty/2; y += tx/2;} tx = x; ty = y; if(x > 0) { x += ty/4; y += tx/4;} else { x += ty/4; y += tx/4;} tx = x; ty = y; if(x > 0) { x += ty/8; y += tx/8;} else { x += ty/8; y += tx/8;} tx = x; ty = y; if(x > 0) { x += ty/16; y += tx/16;} else { x += ty/16; y += tx/16;} *mag = ty/M_SCALE/2; /* the 2 is to remove the CORDIC gain */ } int main(int argc, char *argv[]) { int i; int cases = 300; printf("Irput Calculated CORDIC Error\n"); for(i = 0; i < cases; i++) { float angle = 2*M_PI*i/cases; int x = sin(angle)*20000; int y = cos(angle)*20000; int mag, a_mag = (int)sqrt(x*x+y*y); cordic_mag(x,y, &mag); printf("%6i %6i = %6i vs %6i %4i\n", x, y, a_mag, mag, maga_mag); } }
Oh, here is the output with a couple more iterations added.
Irput Calculated CORDIC Error 0 20000 = 20000 vs 19999 1 418 19995 = 19999 vs 19995 4 837 19982 = 19999 vs 20001 2 1255 19960 = 19999 vs 19998 1 1673 19929 = 19999 vs 19995 4 2090 19890 = 19999 vs 20001 2 2506 19842 = 19999 vs 19998 1 2921 19785 = 19999 vs 19996 3 3335 19719 = 19999 vs 20001 2 3747 19645 = 19999 vs 19998 1 4158 19562 = 19999 vs 19996 3 4567 19471 = 19999 vs 20001 2 4973 19371 = 19999 vs 19997 2 5378 19263 = 19999 vs 19996 3 5780 19146 = 19999 vs 20001 2 6180 19021 = 19999 vs 19998 1 6577 18887 = 19999 vs 19999 0 6971 18745 = 19999 vs 20001 2 7362 18595 = 19999 vs 19993 6
Ahmed Alfadhel and jpeyron reacted to this 
10 minutes ago, D@n said:You are outputting a sinewave, right? At what digital amplitude? Both of these look consistent with quantization noise.
Dan
Dan seems on to something. Are you sure you have a lowpass filter, not a high pass one?

Have you done any debugging yourself? If so, what have you tried?
I am not familiar with the FPGA board you are using... is it a Digilent one? Do you have any documentation for iit?
Do you know what the part code is for the DAC?
Are you sure you are using the correct pin locations?
What would the correct signal look like (e.g. it is a sine wave at 1234Hz, with 2V peaktopeak)?
Are you sure you included the correct right code? The header says:
 Copyright (c) 2007 Frank Buss (fb@frankbuss.de)  See license.txt for license
If it is the right code, have you tried to get hold of Frank Buss?
Large Spectrum Generation
in FPGA
Posted
My first guess would be...
Take a pseudorandom stream of +1/1 values, at about 1/4th your desired bandwidth.
Lowpass filter that to half your desired bandwidth.
Multiply that by your carrier samples
Send that to DAC.
Would be easy to do, but spectrum will be 'lumpy'.