use work.task.all; | use work.task.all; | ||||
use work.float.all; | use work.float.all; | ||||
entity fft is | |||||
generic ( | |||||
-- input data width of real/img part | |||||
input_data_width : integer := 32; | |||||
-- output data width of real/img part | |||||
output_data_width : integer := 32 | |||||
); | |||||
port ( | |||||
clk : in std_logic; | |||||
reset : in std_logic; | |||||
task_start : in std_logic; | |||||
task_state : out work.task.State; | |||||
signal_read : out std_logic; | |||||
signal_readdata : in std_logic_vector( 31 downto 0 ); | |||||
signal_write : out std_logic; | |||||
signal_writedata : out std_logic_vector( 31 downto 0 ) | |||||
); | |||||
end entity fft; | |||||
architecture rtl of fft is | architecture rtl of fft is | ||||
signal next_task_state : work.task.State; | signal next_task_state : work.task.State; | ||||
signal index : integer range 0 to work.task.STREAM_LEN; | signal index : integer range 0 to work.task.STREAM_LEN; | ||||
--own signals: | |||||
--signal input_re : float(31 downto 0); | |||||
--use xxx.lib?; --componenteninstanziierung FFT IP-Core r22sdf | |||||
--component foo is | |||||
--generic (...) | |||||
--port(...); | |||||
--end component; | |||||
component fftmain is | |||||
generic ( | |||||
-- input data width of real/img part | |||||
input_data_width : integer := 32; | |||||
-- output data width of real/img part | |||||
output_data_width : integer := 32 | |||||
); | |||||
port ( | |||||
clk : in std_logic; | |||||
reset : in std_logic; | |||||
di_en : in std_logic; | |||||
di_re : in std_logic_vector(input_data_width-1 downto 0); | |||||
di_im : in std_logic_vector(input_data_width-1 downto 0); | |||||
do_en : in std_logic; | |||||
do_re : in std_logic_vector(input_data_width-1 downto 0); | |||||
do_im : in std_logic_vector(input_data_width-1 downto 0) | |||||
--task_start : in std_logic; | |||||
--task_state : out work.task.State; | |||||
--signal_read : out std_logic; | |||||
--signal_readdata : in std_logic_vector( 31 downto 0 ); | |||||
--signal_write : out std_logic; | |||||
--signal_writedata : out std_logic_vector( 31 downto 0 ) | |||||
); | |||||
end component fftmain; | |||||
---State machine ---------------------------------- | |||||
TYPE State_type IS (A, B, C, D); -- Define the states | |||||
SIGNAL State : State_Type; -- Create a signal that uses | |||||
-- the different states | |||||
begin | begin | ||||
u_fft : fftmain | |||||
port map ( | |||||
clock => clk, | |||||
reset => fft_reset, | |||||
di_en => fft_input_data_enable, | |||||
di_re => diata_in_re, | |||||
di_im => data_in_im, | |||||
do_en => fft_output_valid, | |||||
do_re => data_out_re, | |||||
do_im => data_out_im | |||||
); | |||||
u_fft_mag_calc : entity work.fft_magnitude_calc | |||||
port map ( | |||||
clk => clk, | |||||
reset => reset, | |||||
input_valid => fft_output_valid, | |||||
input_re => data_out_re, | |||||
input_im => data_out_im, | |||||
output_valid => fft_mag_calc_valid, | |||||
output_magnitude => fft_mag_calc_result | |||||
); | |||||
task_state_transitions : process ( current_task_state, task_start, index ) is | task_state_transitions : process ( current_task_state, task_start, index ) is | ||||
begin | begin | ||||
next_task_state <= current_task_state; | next_task_state <= current_task_state; |
task_start : in std_logic; | task_start : in std_logic; | ||||
task_state : out work.task.State; | task_state : out work.task.State; | ||||
step_size : in work.reg32.word; | |||||
phase : in work.reg32.word; | |||||
amplitude : in work.reg32.word; | |||||
step_size : in work.reg32.word; --Parameter, übergeben aus task_sine | |||||
phase : in work.reg32.word; --Parameter, übergeben aus task_sine | |||||
amplitude : in work.reg32.word; --Parameter, übergeben aus task_sine | |||||
signal_write : out std_logic; | signal_write : out std_logic; | ||||
signal_writedata : out std_logic_vector( 31 downto 0 ) | signal_writedata : out std_logic_vector( 31 downto 0 ) | ||||
signal current_task_state : work.task.State; | signal current_task_state : work.task.State; | ||||
signal next_task_state : work.task.State; | signal next_task_state : work.task.State; | ||||
signal index : integer range 0 to work.task.STREAM_LEN; | signal index : integer range 0 to work.task.STREAM_LEN; | ||||
--own signals: | |||||
signal data_valid : std_logic; | |||||
signal busy : std_logic; | |||||
signal angle : signed(31 downto 0); | |||||
signal result_valid : std_logic; | |||||
signal sine_value : signed(31 downto 0); | |||||
signal output_value : signed(31 downto 0); | |||||
signal output_flag : std_logic; | |||||
--signal exp : signed(7 downto 0); | |||||
--signal tmp : signed(7 downto 0); | |||||
---State machine ---------------------------------- | |||||
TYPE State_type IS (A, B, C, D); -- Define the states | |||||
SIGNAL State : State_Type; -- Create a signal that uses | |||||
-- the different states | |||||
begin | begin | ||||
u_float_sine : entity work.float_sine | |||||
generic map ( | |||||
ITERATIONS => 8 | |||||
) | |||||
port map( | |||||
clk => clk, | |||||
reset => reset, | |||||
data_valid => data_valid, | |||||
angle => angle, | |||||
busy => busy, | |||||
result_valid => result_valid, | |||||
sine => sine_value | |||||
); | |||||
PROCESS (clk, reset) | |||||
BEGIN | |||||
If (reset = '1') THEN --RESET: State to A | |||||
data_valid <= '0'; | |||||
output_flag <= '0'; | |||||
angle <= x"00000000";--x"1FFFFFFF"; | |||||
State <= A; | |||||
ELSIF rising_edge(clk) THEN -- if there is a rising edge of the | |||||
-- clock, then do the stuff below | |||||
-- The CASE statement checks the value of the State variable, | |||||
-- and based on the value and any other control signals, changes | |||||
-- to a new state. | |||||
CASE State IS | |||||
-- If the current state is A and P is set to 1, then the | |||||
-- next state is B | |||||
WHEN A => --set data_valid to 1 for one clock cycle | |||||
IF index = 0 THEN | |||||
angle <= signed(phase); | |||||
ELSE | |||||
--angle <= angle;--x"1FFFFFFF"; --debug: 1,5 --> should result in sin() = 1 | |||||
END IF; | |||||
IF data_valid ='0' AND current_task_state = TASK_RUNNING THEN | |||||
data_valid <= '1'; | |||||
State <= B; | |||||
END IF; | |||||
-- If the current state is B and P is set to 1, then the | |||||
-- next state is C | |||||
WHEN B => | |||||
IF data_valid ='1' THEN | |||||
data_valid <= '0'; | |||||
State <= C; | |||||
END IF; | |||||
-- If the current state is C and P is set to 1, then the | |||||
-- next state is D | |||||
WHEN C => | |||||
IF result_valid = '1' AND busy = '0' THEN | |||||
--sine_value <= sine; | |||||
output_flag <= '1'; | |||||
data_valid <= '0'; | |||||
angle <= angle + signed(step_size); --winkel neu zuweisen | |||||
State <= D; | |||||
END IF; | |||||
-- If the current state is D and P is set to 1, then the | |||||
-- next state is B. | |||||
-- If the current state is D and P is set to 0, then the | |||||
-- next state is A. | |||||
WHEN D=> | |||||
IF data_valid = '0' THEN | |||||
output_flag <= '0'; | |||||
State <= A; | |||||
--ELSE | |||||
--State <= A; | |||||
END IF; | |||||
--WHEN others => | |||||
--State <= A; | |||||
END CASE; | |||||
END IF; | |||||
END PROCESS; | |||||
--end of state machine______________________________________ | |||||
--do not change | |||||
task_state_transitions : process ( current_task_state, task_start, index ) is | task_state_transitions : process ( current_task_state, task_start, index ) is | ||||
begin | begin | ||||
next_task_state <= current_task_state; | next_task_state <= current_task_state; | ||||
next_task_state <= work.task.TASK_RUNNING; | next_task_state <= work.task.TASK_RUNNING; | ||||
end if; | end if; | ||||
when work.task.TASK_RUNNING => | when work.task.TASK_RUNNING => | ||||
if ( index = work.task.STREAM_LEN - 1 ) then | |||||
if ( index = work.task.STREAM_LEN ) then -- changed from index = work.task.STREAM_LEN - 1 | |||||
next_task_state <= work.task.TASK_DONE; | next_task_state <= work.task.TASK_DONE; | ||||
end if; | end if; | ||||
when work.task.TASK_DONE => | when work.task.TASK_DONE => | ||||
if ( task_start = '1' ) then | if ( task_start = '1' ) then | ||||
next_task_state <= work.task.TASK_RUNNING; | next_task_state <= work.task.TASK_RUNNING; | ||||
end if; | end if; | ||||
end case; | end case; | ||||
end process task_state_transitions; | end process task_state_transitions; | ||||
--end of no not change | |||||
sync : process ( clk, reset ) is | |||||
sync : process ( clk, reset , signal_writedata) is | |||||
begin | begin | ||||
if ( reset = '1' ) then | if ( reset = '1' ) then | ||||
current_task_state <= work.task.TASK_IDLE; | current_task_state <= work.task.TASK_IDLE; | ||||
when work.task.TASK_IDLE => | when work.task.TASK_IDLE => | ||||
index <= 0; | index <= 0; | ||||
signal_write <= '0'; | signal_write <= '0'; | ||||
when work.task.TASK_RUNNING => | when work.task.TASK_RUNNING => | ||||
index <= index + 1; | |||||
signal_write <= '1'; | |||||
signal_writedata <= ( others => '0' ); | |||||
--output: | |||||
IF output_flag = '1' THEN | |||||
index <= index + 1; | |||||
signal_write <= '1'; | |||||
output_value <= sine_value; | |||||
output_value(30 downto 23) <= sine_value(30 downto 23) + (signed(amplitude(30 downto 23)) - 127); --change from +2 to correct exponent | |||||
--wenn 1: +0, wenn 2: +1, wenn 4:2, wenn 8: 3 = Bit | |||||
ELSE | |||||
signal_write <= '0'; | |||||
END IF; | |||||
--signal_writedata <= std_logic_vector(to_unsigned(2, signal_writedata'length)); --test | |||||
when work.task.TASK_DONE => | when work.task.TASK_DONE => | ||||
index <= 0; | index <= 0; | ||||
signal_write <= '0'; | |||||
signal_write <= '0'; | |||||
end case; | end case; | ||||
end if; | end if; | ||||
end process sync; | end process sync; | ||||
task_state <= current_task_state; | task_state <= current_task_state; | ||||
signal_writedata <= std_logic_vector(output_value);--x"40800000";--( others => '0' ); | |||||
end architecture rtl; | end architecture rtl; |
#include "system/data_channel.h" | #include "system/data_channel.h" | ||||
#include "system/float_word.h" | #include "system/float_word.h" | ||||
#include <math.h> | |||||
#include <stdio.h> | |||||
typedef struct { | |||||
float value; | |||||
} Result; | |||||
void generateSinusCurve(float samples_per_period, float phase, float amplitude, Result res[]) { | |||||
float delta_phase = 2.0 * M_PI / samples_per_period; | |||||
float current_phase = phase; | |||||
for (int i = 0; i < DATA_CHANNEL_DEPTH; ++i) { | |||||
res[i].value = amplitude * sinf(current_phase); | |||||
current_phase += delta_phase; | |||||
} | |||||
} | |||||
int task_sine_run( void * data ) { | int task_sine_run( void * data ) { | ||||
// TODO | |||||
sine_config * task = (sine_config *) data; | |||||
uint32_t data_channel_base = task -> base.sink; | |||||
data_channel_clear( data_channel_base ); | |||||
float_word res; | |||||
//float samples_per_period = 32.0; | |||||
float samples_per_period = task ->samples_per_periode; | |||||
float phase = task-> phase; | |||||
float amplitude = task -> amplitude; | |||||
Result results[DATA_CHANNEL_DEPTH]; | |||||
generateSinusCurve(samples_per_period, phase, amplitude, results); | |||||
for (int i = 0; i < DATA_CHANNEL_DEPTH; ++i) { | |||||
//printf("Wert %d: %f\n", i, results[i].value); | |||||
res.value = results[i].value; | |||||
data_channel_write( data_channel_base, res.word); | |||||
} | |||||
return 0; | return 0; | ||||
} | } | ||||
.sink = DATA_CHANNEL_0_BASE, | .sink = DATA_CHANNEL_0_BASE, | ||||
.cycle_count = 0 }, | .cycle_count = 0 }, | ||||
.samples_per_periode = 32, | .samples_per_periode = 32, | ||||
.phase = 0.0, | |||||
.phase = 0, | |||||
.amplitude = 4.0 }; | .amplitude = 4.0 }; | ||||
sine_config COSINE_CONFIG = { | sine_config COSINE_CONFIG = { |
.PHONY: sim clean | .PHONY: sim clean | ||||
sim: ${verilog_objs} ${vhdl_objs} | sim: ${verilog_objs} ${vhdl_objs} | ||||
@vsim -gCHECK_RESULTS=${CHECK_RESULTS} -voptargs=+acc -c work.${main} -do "set StdArithNoWarnings 1; set NumericStdNoWarnings 1; run -all" \ | |||||
| ../../scripts/highlight_test_results.sh | |||||
@vsim -gCHECK_RESULTS=${CHECK_RESULTS} -voptargs=+acc -c work.${main} -do "set StdArithNoWarnings 1; set NumericStdNoWarnings 1; run -all" | |||||
#| ../../scripts/highlight_test_results.sh | |||||
gui: ${verilog_objs} ${vhdl_objs} | gui: ${verilog_objs} ${vhdl_objs} | ||||
@vsim -gCHECK_RESULTS=${CHECK_RESULTS} -gGUI_MODE=true -voptargs=+acc work.${main} -do "do vsim.wave; set StdArithNoWarnings 1; set NumericStdNoWarnings 1; run -all" | @vsim -gCHECK_RESULTS=${CHECK_RESULTS} -gGUI_MODE=true -voptargs=+acc work.${main} -do "do vsim.wave; set StdArithNoWarnings 1; set NumericStdNoWarnings 1; run -all" |
vhdl_srcs = \ | vhdl_srcs = \ | ||||
../../../hardware/system/reg32.vhd \ | ../../../hardware/system/reg32.vhd \ | ||||
../test_utility.vhd \ | |||||
../test_avalon_slave.vhd \ | |||||
../../../hardware/system/avalon_slave.vhd \ | ../../../hardware/system/avalon_slave.vhd \ | ||||
../../hardware/test_data_channel.vhd \ | |||||
../../../hardware/system/avalon_slave_transitions.vhd \ | ../../../hardware/system/avalon_slave_transitions.vhd \ | ||||
../../../hardware/system/task.vhd \ | ../../../hardware/system/task.vhd \ | ||||
../../../hardware/system/hardware_task_control.vhd \ | ../../../hardware/system/hardware_task_control.vhd \ | ||||
../test_utility.vhd \ | ../test_utility.vhd \ | ||||
../test_avalon_slave.vhd \ | ../test_avalon_slave.vhd \ | ||||
../test_hardware_task.vhd \ | ../test_hardware_task.vhd \ | ||||
../../hardware/test_data_channel.vhd \ | |||||
../../data/add_rand.vhd \ | ../../data/add_rand.vhd \ | ||||
../../data/sine.vhd \ | ../../data/sine.vhd \ | ||||
../../data/fft.vhd \ | ../../data/fft.vhd \ |