@@ -0,0 +1,20 @@ | |||
.qsys_edit/ | |||
c5_pin_model_dump.txt | |||
db/ | |||
incremental_db/ | |||
*.bak | |||
niosII.sopcinfo | |||
niosII/ | |||
output_files/ | |||
__pycache__/ | |||
*.pyc | |||
.assembler | |||
.fitter | |||
.map | |||
.sta | |||
*.log | |||
*.o | |||
*.oo | |||
*.swp | |||
*.elf | |||
@@ -0,0 +1,199 @@ | |||
# Check for the required nios2-download command | |||
# The command is only available in nios2_command_shell | |||
ifeq (, $(shell which nios2-download)) | |||
$(error "This makefile must be executed within the nios2_command_shell") | |||
endif | |||
uname = $(shell uname -r) | |||
ifneq (,$(findstring Microsoft,${uname})) | |||
exe_suffix=.exe | |||
endif | |||
# Programm pathes | |||
quartus_root ?= ${QUARTUS_ROOTDIR} | |||
intel_root ?= $(quartus_root)/.. | |||
sopc_root = $(quartus_root)/sopc_builder | |||
# Tools | |||
qsys_generate = $(sopc_root)/bin/qsys-generate$(exe_suffix) | |||
niosii_bsp = $(intel_root)/nios2eds/sdk2/bin/nios2-bsp | |||
quartus_map = quartus_map$(exe_suffix) | |||
quartus_fit = quartus_fit$(exe_suffix) | |||
quartus_asm = quartus_asm$(exe_suffix) | |||
quartus_sta = quartus_sta$(exe_suffix) | |||
nios2_bsp_generate_files = nios2-bsp-generate-files$(exe_suffix) | |||
quartus_pgm = quartus_pgm$(exe_suffix) | |||
nios2_download = nios2-download$(exe_suffix) | |||
nios2_terminal = nios2-terminal$(exe_suffix) | |||
# Directories | |||
niosii_dir = niosII | |||
bsp_dir = software/signal_processing_bsp | |||
app_dir = software/signal_processing | |||
hw_test_dir = tests/hardware | |||
sw_test_dir = tests/software | |||
# Settings | |||
quartus_project = signal_processing | |||
signal_processing_qsf = signal_processing.qsf | |||
# Sources | |||
niosii_qsys = niosII.qsys | |||
# Targets | |||
niosii_qip = $(niosii_dir)/synthesis/niosII.qip | |||
niosii_info = niosII.sopcinfo | |||
bsp_settings = $(bsp_dir)/settings.bsp | |||
bsp_makefile = $(bsp_dir)/Makefile | |||
# VHDL source files | |||
hdl_src += \ | |||
hardware/system/sync_ff.vhd \ | |||
hardware/system/sync_rst.vhd \ | |||
hardware/system/pll/pll_main.vhd \ | |||
hardware/system/reg32.vhd \ | |||
hardware/system/avalon_slave_transitions.vhd \ | |||
hardware/system/avalon_slave.vhd \ | |||
hardware/system/data_sink_mux.vhd \ | |||
hardware/system/fifo.vhd \ | |||
hardware/system/data_source_mux.vhd \ | |||
hardware/system/data_channel_control.vhd \ | |||
hardware/system/data_channel.vhd \ | |||
hardware/system/hardware_timestamp.vhd \ | |||
hardware/system/task.vhd \ | |||
hardware/system/float.vhd \ | |||
hardware/system/hardware_task_control.vhd \ | |||
hardware/system/hardware_task.vhd \ | |||
hardware/system/float_add.vhd \ | |||
hardware/signal_processing/add.vhd \ | |||
hardware/system/task_add.vhd \ | |||
hardware/signal_processing/rand.vhd \ | |||
hardware/system/task_rand.vhd \ | |||
hardware/system/cordic_pkg.vhd \ | |||
hardware/system/cordic.vhd \ | |||
hardware/system/fixed_sine.vhd \ | |||
hardware/system/float_sine.vhd \ | |||
hardware/signal_processing/sine.vhd \ | |||
hardware/system/task_sine.vhd \ | |||
hardware/system/Butterfly.v \ | |||
hardware/system/DelayBuffer.v \ | |||
hardware/system/FFT1024_32B.v \ | |||
hardware/system/Multiply.v \ | |||
hardware/system/SdfUnit2.v \ | |||
hardware/system/SdfUnit.v \ | |||
hardware/system/Twiddle1024_32B.v \ | |||
hardware/system/squareRoot_pipe.vhd \ | |||
hardware/system/fft_magnitude_calc.vhd \ | |||
hardware/signal_processing/fft.vhd \ | |||
hardware/system/task_fft.vhd \ | |||
hardware/signal_processing/crc.vhd \ | |||
hardware/system/task_crc.vhd \ | |||
hardware/signal_processing/signal_processing.vhd \ | |||
# | |||
clean_items += \ | |||
$(niosii_dir) \ | |||
$(niosii_info) \ | |||
.map \ | |||
.fitter \ | |||
.assembler \ | |||
.sta \ | |||
.qsys_edit/ \ | |||
db/ \ | |||
incremental_db/ \ | |||
output_files/ \ | |||
.PHONY: all \ | |||
niosII \ | |||
fpga \ | |||
program \ | |||
clean \ | |||
app \ | |||
download \ | |||
run \ | |||
tests \ | |||
all: run | |||
#------------------------------------------------------------------------------ | |||
# Create the NiosII system from the description file | |||
niosII: $(niosii_info) | |||
# Create the NiosII sources from the description file | |||
$(niosii_qip): $(niosii_qsys) | |||
@echo Generating the NiosII system from $< ... | |||
@$(qsys_generate) -syn=VHDL $< | |||
# The NiosII system information file is created in parallel to the .qip file. | |||
$(niosii_info): $(niosii_qip) | |||
#------------------------------------------------------------------------------ | |||
# Quartus FPGA toolchain contains the mapper, fitter, assembler and static | |||
# timing analysis (sta). | |||
# | |||
fpga: .sta | |||
# Anaylze and synthesis of the QuartusII project | |||
.map: $(hdl_src) $(niosii_info) $(signal_processing_qsf) | |||
@rm -f $@ | |||
@$(quartus_map) --read_settings_files=on --write_settings_files=off $(quartus_project) -c $(quartus_project) && date > $@ | |||
# Run the quartus fitter on the project | |||
.fitter: .map $(sdc_src) $(signal_processing_qsf) | |||
@rm -f $@ | |||
@$(quartus_fit) --read_settings_files=on --write_settings_files=off $(quartus_project) -c $(quartus_project) && date > $@ | |||
.assembler: .fitter | |||
@rm -f $@ | |||
@$(quartus_asm) --read_settings_files=off --write_settings_files=off $(quartus_project) -c $(quartus_project)&& date > $@ | |||
.sta: .assembler | |||
@rm -f $@ | |||
@$(quartus_sta) $(quartus_project) -c $(quartus_project) && date > $@ | |||
output_files/signal_processing_time_limited.sof: .sta | |||
# Create the BSP from the sopc description | |||
bsp: ${bsp_makefile} | |||
$(bsp_settings): $(niosii_info) | |||
@echo Generating the NiosII BSP from $< ... | |||
@$(niosii_bsp) hal $(bsp_dir) $< | |||
$(bsp_makefile): $(bsp_settings) | |||
@$(nios2_bsp_generate_files) --settings software/signal_processing_bsp/settings.bsp --bsp-dir software/signal_processing_bsp/ | |||
app: $(bsp_makefile) | |||
${MAKE} -C $(app_dir) | |||
# Programme the FPGA design | |||
program: output_files/signal_processing_time_limited.sof | |||
@$(quartus_pgm) signal_processing.cdf | |||
# Programme the NiosII software design | |||
download: app | |||
@$(nios2-download) $(app_dir)/signal_processing.elf -g | |||
# Programme the NiosII software design | |||
run: fpga download | |||
@$(nios2-terminal) | |||
sw_tests: | |||
@${MAKE} -C tests/software | |||
hw_tests: | |||
@${MAKE} -C tests/hardware | |||
device_tests: | |||
@${MAKE} -C tests/device | |||
tests: sw_tests hw_tests device_tests | |||
clean: | |||
@rm -rf $(clean_items) | |||
@${MAKE} -C ${hw_test_dir} clean | |||
@${MAKE} -C ${sw_test_dir} clean | |||
@${MAKE} -C ${app_dir} clean | |||
@${MAKE} -C ${bsp_dir} clean | |||
@@ -0,0 +1,195 @@ | |||
# TCL File Generated by Component Editor 21.1 | |||
# Fri Sep 09 13:42:23 CEST 2022 | |||
# DO NOT MODIFY | |||
# | |||
# data_channel "data_channel" v1.0 | |||
# Johannes Kutning 2022.09.09.13:42:23 | |||
# A data channel for signal data transport | |||
# | |||
# | |||
# request TCL package from ACDS 16.1 | |||
# | |||
package require -exact qsys 16.1 | |||
# | |||
# module data_channel | |||
# | |||
set_module_property DESCRIPTION "A data channel for signal data transport" | |||
set_module_property NAME data_channel | |||
set_module_property VERSION 1.0 | |||
set_module_property INTERNAL false | |||
set_module_property OPAQUE_ADDRESS_MAP true | |||
set_module_property GROUP signal_processing | |||
set_module_property AUTHOR "Johannes Kutning" | |||
set_module_property DISPLAY_NAME data_channel | |||
set_module_property INSTANTIATE_IN_SYSTEM_MODULE true | |||
set_module_property EDITABLE true | |||
set_module_property REPORT_TO_TALKBACK false | |||
set_module_property ALLOW_GREYBOX_GENERATION false | |||
set_module_property REPORT_HIERARCHY false | |||
# | |||
# file sets | |||
# | |||
add_fileset QUARTUS_SYNTH QUARTUS_SYNTH "" "" | |||
set_fileset_property QUARTUS_SYNTH TOP_LEVEL data_channel | |||
set_fileset_property QUARTUS_SYNTH ENABLE_RELATIVE_INCLUDE_PATHS false | |||
set_fileset_property QUARTUS_SYNTH ENABLE_FILE_OVERWRITE_MODE false | |||
add_fileset_file data_channel.vhd VHDL PATH hardware/system/data_channel.vhd TOP_LEVEL_FILE | |||
# | |||
# parameters | |||
# | |||
add_parameter DEPTH POSITIVE 1024 | |||
set_parameter_property DEPTH DEFAULT_VALUE 1024 | |||
set_parameter_property DEPTH DISPLAY_NAME DEPTH | |||
set_parameter_property DEPTH TYPE POSITIVE | |||
set_parameter_property DEPTH UNITS None | |||
set_parameter_property DEPTH ALLOWED_RANGES 1:2147483647 | |||
set_parameter_property DEPTH HDL_PARAMETER true | |||
# | |||
# display items | |||
# | |||
# | |||
# connection point clock | |||
# | |||
add_interface clock clock end | |||
set_interface_property clock clockRate 0 | |||
set_interface_property clock ENABLED true | |||
set_interface_property clock EXPORT_OF "" | |||
set_interface_property clock PORT_NAME_MAP "" | |||
set_interface_property clock CMSIS_SVD_VARIABLES "" | |||
set_interface_property clock SVD_ADDRESS_GROUP "" | |||
add_interface_port clock clk clk Input 1 | |||
# | |||
# connection point reset | |||
# | |||
add_interface reset reset end | |||
set_interface_property reset associatedClock clock | |||
set_interface_property reset synchronousEdges DEASSERT | |||
set_interface_property reset ENABLED true | |||
set_interface_property reset EXPORT_OF "" | |||
set_interface_property reset PORT_NAME_MAP "" | |||
set_interface_property reset CMSIS_SVD_VARIABLES "" | |||
set_interface_property reset SVD_ADDRESS_GROUP "" | |||
add_interface_port reset reset reset Input 1 | |||
# | |||
# connection point ctrl | |||
# | |||
add_interface ctrl avalon end | |||
set_interface_property ctrl addressUnits WORDS | |||
set_interface_property ctrl associatedClock clock | |||
set_interface_property ctrl associatedReset reset | |||
set_interface_property ctrl bitsPerSymbol 8 | |||
set_interface_property ctrl burstOnBurstBoundariesOnly false | |||
set_interface_property ctrl burstcountUnits WORDS | |||
set_interface_property ctrl explicitAddressSpan 0 | |||
set_interface_property ctrl holdTime 0 | |||
set_interface_property ctrl linewrapBursts false | |||
set_interface_property ctrl maximumPendingReadTransactions 0 | |||
set_interface_property ctrl maximumPendingWriteTransactions 0 | |||
set_interface_property ctrl readLatency 0 | |||
set_interface_property ctrl readWaitTime 1 | |||
set_interface_property ctrl setupTime 0 | |||
set_interface_property ctrl timingUnits Cycles | |||
set_interface_property ctrl writeWaitTime 0 | |||
set_interface_property ctrl ENABLED true | |||
set_interface_property ctrl EXPORT_OF "" | |||
set_interface_property ctrl PORT_NAME_MAP "" | |||
set_interface_property ctrl CMSIS_SVD_VARIABLES "" | |||
set_interface_property ctrl SVD_ADDRESS_GROUP "" | |||
add_interface_port ctrl ctrl_address address Input 4 | |||
add_interface_port ctrl ctrl_read read Input 1 | |||
add_interface_port ctrl ctrl_readdata readdata Output 32 | |||
add_interface_port ctrl ctrl_write write Input 1 | |||
add_interface_port ctrl ctrl_writedata writedata Input 32 | |||
set_interface_assignment ctrl embeddedsw.configuration.isFlash 0 | |||
set_interface_assignment ctrl embeddedsw.configuration.isMemoryDevice 0 | |||
set_interface_assignment ctrl embeddedsw.configuration.isNonVolatileStorage 0 | |||
set_interface_assignment ctrl embeddedsw.configuration.isPrintableDevice 0 | |||
# | |||
# connection point hw_sink | |||
# | |||
add_interface hw_sink avalon end | |||
set_interface_property hw_sink addressUnits WORDS | |||
set_interface_property hw_sink associatedClock clock | |||
set_interface_property hw_sink associatedReset reset | |||
set_interface_property hw_sink bitsPerSymbol 8 | |||
set_interface_property hw_sink burstOnBurstBoundariesOnly false | |||
set_interface_property hw_sink burstcountUnits WORDS | |||
set_interface_property hw_sink explicitAddressSpan 0 | |||
set_interface_property hw_sink holdTime 0 | |||
set_interface_property hw_sink linewrapBursts false | |||
set_interface_property hw_sink maximumPendingReadTransactions 0 | |||
set_interface_property hw_sink maximumPendingWriteTransactions 0 | |||
set_interface_property hw_sink readLatency 0 | |||
set_interface_property hw_sink readWaitTime 1 | |||
set_interface_property hw_sink setupTime 0 | |||
set_interface_property hw_sink timingUnits Cycles | |||
set_interface_property hw_sink writeWaitTime 0 | |||
set_interface_property hw_sink ENABLED true | |||
set_interface_property hw_sink EXPORT_OF "" | |||
set_interface_property hw_sink PORT_NAME_MAP "" | |||
set_interface_property hw_sink CMSIS_SVD_VARIABLES "" | |||
set_interface_property hw_sink SVD_ADDRESS_GROUP "" | |||
add_interface_port hw_sink hw_sink_write write Input 1 | |||
add_interface_port hw_sink hw_sink_writedata writedata Input 32 | |||
set_interface_assignment hw_sink embeddedsw.configuration.isFlash 0 | |||
set_interface_assignment hw_sink embeddedsw.configuration.isMemoryDevice 0 | |||
set_interface_assignment hw_sink embeddedsw.configuration.isNonVolatileStorage 0 | |||
set_interface_assignment hw_sink embeddedsw.configuration.isPrintableDevice 0 | |||
# | |||
# connection point hw_source | |||
# | |||
add_interface hw_source avalon end | |||
set_interface_property hw_source addressUnits WORDS | |||
set_interface_property hw_source associatedClock clock | |||
set_interface_property hw_source associatedReset reset | |||
set_interface_property hw_source bitsPerSymbol 8 | |||
set_interface_property hw_source burstOnBurstBoundariesOnly false | |||
set_interface_property hw_source burstcountUnits WORDS | |||
set_interface_property hw_source explicitAddressSpan 0 | |||
set_interface_property hw_source holdTime 0 | |||
set_interface_property hw_source linewrapBursts false | |||
set_interface_property hw_source maximumPendingReadTransactions 0 | |||
set_interface_property hw_source maximumPendingWriteTransactions 0 | |||
set_interface_property hw_source readLatency 0 | |||
set_interface_property hw_source readWaitTime 1 | |||
set_interface_property hw_source setupTime 0 | |||
set_interface_property hw_source timingUnits Cycles | |||
set_interface_property hw_source writeWaitTime 0 | |||
set_interface_property hw_source ENABLED true | |||
set_interface_property hw_source EXPORT_OF "" | |||
set_interface_property hw_source PORT_NAME_MAP "" | |||
set_interface_property hw_source CMSIS_SVD_VARIABLES "" | |||
set_interface_property hw_source SVD_ADDRESS_GROUP "" | |||
add_interface_port hw_source hw_source_read read Input 1 | |||
add_interface_port hw_source hw_source_readdata readdata Output 32 | |||
set_interface_assignment hw_source embeddedsw.configuration.isFlash 0 | |||
set_interface_assignment hw_source embeddedsw.configuration.isMemoryDevice 0 | |||
set_interface_assignment hw_source embeddedsw.configuration.isNonVolatileStorage 0 | |||
set_interface_assignment hw_source embeddedsw.configuration.isPrintableDevice 0 | |||
@@ -0,0 +1,32 @@ | |||
# External clock clk_50 has a frequency of 50 MHz | |||
create_clock -period 20 [get_ports clk_input] | |||
derive_pll_clocks | |||
set clk_main u_pll_200|pll_200|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk | |||
# Input delays for singals in 50 MHz domain | |||
set_input_delay \ | |||
-clock { clk_input } \ | |||
2 \ | |||
[get_ports {reset_n}] | |||
# Input delays for singals in 200 MHz domain | |||
set_false_path \ | |||
-from \ | |||
[get_ports {key_start}] | |||
# Output delays for singals in 200 MHz domain | |||
set_false_path \ | |||
-to \ | |||
[get_ports { \ | |||
leds[0] \ | |||
leds[1] \ | |||
leds[2] \ | |||
leds[3] \ | |||
leds[4] \ | |||
leds[5] \ | |||
leds[6] \ | |||
leds[7] \ | |||
}] | |||
@@ -0,0 +1,77 @@ | |||
library ieee; | |||
use ieee.std_logic_1164.all; | |||
use ieee.numeric_std.all; | |||
library work; | |||
use work.reg32.all; | |||
use work.task.all; | |||
entity add is | |||
port ( | |||
clk : in std_logic; | |||
reset : in std_logic; | |||
task_start : in std_logic; | |||
task_state : out work.task.State; | |||
signal_a_read : out std_logic; | |||
signal_a_readdata : in std_logic_vector( 31 downto 0 ); | |||
signal_b_read : out std_logic; | |||
signal_b_readdata : in std_logic_vector( 31 downto 0 ); | |||
signal_write : out std_logic; | |||
signal_writedata : out std_logic_vector( 31 downto 0 ) | |||
); | |||
end entity add; | |||
architecture rtl of add is | |||
signal current_task_state : work.task.State; | |||
signal next_task_state : work.task.State; | |||
signal index : integer range 0 to work.task.STREAM_LEN; | |||
begin | |||
task_state_transitions : process ( current_task_state, task_start, index ) is | |||
begin | |||
next_task_state <= current_task_state; | |||
case current_task_state is | |||
when work.task.TASK_IDLE => | |||
if ( task_start = '1' ) then | |||
next_task_state <= work.task.TASK_RUNNING; | |||
end if; | |||
when work.task.TASK_RUNNING => | |||
if ( index = work.task.STREAM_LEN - 1 ) then | |||
next_task_state <= work.task.TASK_DONE; | |||
end if; | |||
when work.task.TASK_DONE => | |||
if ( task_start = '1' ) then | |||
next_task_state <= work.task.TASK_RUNNING; | |||
end if; | |||
end case; | |||
end process task_state_transitions; | |||
sync : process ( clk, reset ) is | |||
begin | |||
if ( reset = '1' ) then | |||
current_task_state <= work.task.TASK_IDLE; | |||
index <= 0; | |||
elsif ( rising_edge( clk ) ) then | |||
current_task_state <= next_task_state; | |||
case next_task_state is | |||
when work.task.TASK_IDLE => | |||
index <= 0; | |||
signal_write <= '0'; | |||
when work.task.TASK_RUNNING => | |||
index <= index + 1; | |||
signal_write <= '1'; | |||
signal_writedata <= ( others => '0' ); | |||
when work.task.TASK_DONE => | |||
index <= 0; | |||
signal_write <= '0'; | |||
end case; | |||
end if; | |||
end process sync; | |||
task_state <= current_task_state; | |||
end architecture rtl; |
@@ -0,0 +1,76 @@ | |||
library ieee; | |||
use ieee.std_logic_1164.all; | |||
use ieee.numeric_std.all; | |||
library work; | |||
use work.reg32.all; | |||
use work.task.all; | |||
entity crc is | |||
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 crc; | |||
architecture rtl of crc is | |||
signal current_task_state : work.task.State; | |||
signal next_task_state : work.task.State; | |||
signal index : integer range 0 to work.task.STREAM_LEN; | |||
begin | |||
task_state_transitions : process ( current_task_state, task_start, index ) is | |||
begin | |||
next_task_state <= current_task_state; | |||
case current_task_state is | |||
when work.task.TASK_IDLE => | |||
if ( task_start = '1' ) then | |||
next_task_state <= work.task.TASK_RUNNING; | |||
end if; | |||
when work.task.TASK_RUNNING => | |||
if ( index = work.task.STREAM_LEN - 1 ) then | |||
next_task_state <= work.task.TASK_DONE; | |||
end if; | |||
when work.task.TASK_DONE => | |||
if ( task_start = '1' ) then | |||
next_task_state <= work.task.TASK_RUNNING; | |||
end if; | |||
end case; | |||
end process task_state_transitions; | |||
sync : process ( clk, reset ) is | |||
begin | |||
if ( reset = '1' ) then | |||
current_task_state <= work.task.TASK_IDLE; | |||
index <= 0; | |||
elsif ( rising_edge( clk ) ) then | |||
current_task_state <= next_task_state; | |||
case next_task_state is | |||
when work.task.TASK_IDLE => | |||
index <= 0; | |||
signal_write <= '0'; | |||
when work.task.TASK_RUNNING => | |||
index <= index + 1; | |||
signal_write <= '1'; | |||
signal_writedata <= ( others => '0' ); | |||
when work.task.TASK_DONE => | |||
index <= 0; | |||
signal_write <= '0'; | |||
end case; | |||
end if; | |||
end process sync; | |||
task_state <= current_task_state; | |||
end architecture rtl; | |||
@@ -0,0 +1,97 @@ | |||
------------------------------------------------------------------------ | |||
-- fft | |||
-- | |||
-- calculation of FFT magnitude | |||
-- | |||
-- Inputs: | |||
-- 32-Bit Floating Point number in range +-16 expected (loaded from FIFO) | |||
-- | |||
-- Outputs | |||
-- 32-Bit Floating Point number in range +-16 calculated (stored in FIFO) | |||
-- | |||
----------------------------------------------------------------------- | |||
library ieee; | |||
use ieee.std_logic_1164.all; | |||
use ieee.numeric_std.all; | |||
library work; | |||
use work.reg32.all; | |||
use work.task.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 | |||
signal current_task_state : work.task.State; | |||
signal next_task_state : work.task.State; | |||
signal index : integer range 0 to work.task.STREAM_LEN; | |||
begin | |||
task_state_transitions : process ( current_task_state, task_start, index ) is | |||
begin | |||
next_task_state <= current_task_state; | |||
case current_task_state is | |||
when work.task.TASK_IDLE => | |||
if ( task_start = '1' ) then | |||
next_task_state <= work.task.TASK_RUNNING; | |||
end if; | |||
when work.task.TASK_RUNNING => | |||
if ( index = work.task.STREAM_LEN - 1 ) then | |||
next_task_state <= work.task.TASK_DONE; | |||
end if; | |||
when work.task.TASK_DONE => | |||
if ( task_start = '1' ) then | |||
next_task_state <= work.task.TASK_RUNNING; | |||
end if; | |||
end case; | |||
end process task_state_transitions; | |||
sync : process ( clk, reset ) is | |||
begin | |||
if ( reset = '1' ) then | |||
current_task_state <= work.task.TASK_IDLE; | |||
index <= 0; | |||
elsif ( rising_edge( clk ) ) then | |||
current_task_state <= next_task_state; | |||
case next_task_state is | |||
when work.task.TASK_IDLE => | |||
index <= 0; | |||
signal_write <= '0'; | |||
when work.task.TASK_RUNNING => | |||
index <= index + 1; | |||
signal_write <= '1'; | |||
signal_writedata <= ( others => '0' ); | |||
when work.task.TASK_DONE => | |||
index <= 0; | |||
signal_write <= '0'; | |||
end case; | |||
end if; | |||
end process sync; | |||
task_state <= current_task_state; | |||
end architecture rtl; |
@@ -0,0 +1,73 @@ | |||
library ieee; | |||
use ieee.std_logic_1164.all; | |||
use ieee.numeric_std.all; | |||
library work; | |||
use work.reg32.all; | |||
use work.task.all; | |||
entity rand is | |||
port ( | |||
clk : in std_logic; | |||
reset : in std_logic; | |||
task_start : in std_logic; | |||
task_state : out work.task.State; | |||
seed : in work.reg32.word; | |||
signal_write : out std_logic; | |||
signal_writedata : out std_logic_vector( 31 downto 0 ) | |||
); | |||
end entity rand; | |||
architecture rtl of rand is | |||
signal current_task_state : work.task.State; | |||
signal next_task_state : work.task.State; | |||
signal index : integer range 0 to work.task.STREAM_LEN; | |||
begin | |||
task_state_transitions : process ( current_task_state, task_start, index ) is | |||
begin | |||
next_task_state <= current_task_state; | |||
case current_task_state is | |||
when work.task.TASK_IDLE => | |||
if ( task_start = '1' ) then | |||
next_task_state <= work.task.TASK_RUNNING; | |||
end if; | |||
when work.task.TASK_RUNNING => | |||
if ( index = work.task.STREAM_LEN - 1 ) then | |||
next_task_state <= work.task.TASK_DONE; | |||
end if; | |||
when work.task.TASK_DONE => | |||
if ( task_start = '1' ) then | |||
next_task_state <= work.task.TASK_RUNNING; | |||
end if; | |||
end case; | |||
end process task_state_transitions; | |||
sync : process ( clk, reset ) is | |||
begin | |||
if ( reset = '1' ) then | |||
current_task_state <= work.task.TASK_IDLE; | |||
index <= 0; | |||
elsif ( rising_edge( clk ) ) then | |||
current_task_state <= next_task_state; | |||
case next_task_state is | |||
when work.task.TASK_IDLE => | |||
index <= 0; | |||
signal_write <= '0'; | |||
when work.task.TASK_RUNNING => | |||
index <= index + 1; | |||
signal_write <= '1'; | |||
signal_writedata <= ( others => '0' ); | |||
when work.task.TASK_DONE => | |||
index <= 0; | |||
signal_write <= '0'; | |||
end case; | |||
end if; | |||
end process sync; | |||
task_state <= current_task_state; | |||
end architecture rtl; |
@@ -0,0 +1,363 @@ | |||
--! Use ieee library for std_logic types. | |||
library ieee; | |||
use ieee.std_logic_1164.all; | |||
--! Use the niosII library for all processor system components | |||
library niosII; | |||
--! Use the pll_200 library for the PLL 200 MHz clock generation | |||
library pll_main; | |||
entity signal_processing is | |||
port | |||
( | |||
clk_input : in std_logic; | |||
reset_n : in std_logic; | |||
--! Push button key_0 used to start a single execution of the signal | |||
--! processing. | |||
key_start : in std_logic; | |||
leds : out std_logic_vector( 7 downto 0 ) | |||
); | |||
end entity signal_processing; | |||
architecture struct of signal_processing is | |||
--! input clock synchronous reset | |||
signal sync_reset : std_logic; | |||
--! main clock for the NiosII system | |||
signal clk_main : std_logic; | |||
--! main clock from PLL is locked and the system reset can be released. | |||
signal locked_main : std_logic; | |||
--! main clock synchronous reset | |||
signal sync_reset_main : std_logic; | |||
signal sync_reset_main_n : std_logic; | |||
signal sw_leds : std_logic_vector( 7 downto 0 ); | |||
signal hw_leds : std_logic_vector( 7 downto 0 ); | |||
signal hardware_task_0_address : std_logic_vector(3 downto 0); | |||
signal hardware_task_0_read : std_logic; | |||
signal hardware_task_0_readdata : std_logic_vector(31 downto 0); | |||
signal hardware_task_0_write : std_logic; | |||
signal hardware_task_0_writedata : std_logic_vector(31 downto 0); | |||
signal hardware_task_1_address : std_logic_vector(3 downto 0); | |||
signal hardware_task_1_read : std_logic; | |||
signal hardware_task_1_readdata : std_logic_vector(31 downto 0); | |||
signal hardware_task_1_write : std_logic; | |||
signal hardware_task_1_writedata : std_logic_vector(31 downto 0); | |||
signal hardware_task_2_address : std_logic_vector(3 downto 0); | |||
signal hardware_task_2_read : std_logic; | |||
signal hardware_task_2_readdata : std_logic_vector(31 downto 0); | |||
signal hardware_task_2_write : std_logic; | |||
signal hardware_task_2_writedata : std_logic_vector(31 downto 0); | |||
signal hardware_task_3_address : std_logic_vector(3 downto 0); | |||
signal hardware_task_3_read : std_logic; | |||
signal hardware_task_3_readdata : std_logic_vector(31 downto 0); | |||
signal hardware_task_3_write : std_logic; | |||
signal hardware_task_3_writedata : std_logic_vector(31 downto 0); | |||
signal hardware_task_4_address : std_logic_vector(3 downto 0); | |||
signal hardware_task_4_read : std_logic; | |||
signal hardware_task_4_readdata : std_logic_vector(31 downto 0); | |||
signal hardware_task_4_write : std_logic; | |||
signal hardware_task_4_writedata : std_logic_vector(31 downto 0); | |||
signal hardware_task_5_address : std_logic_vector(3 downto 0); | |||
signal hardware_task_5_read : std_logic; | |||
signal hardware_task_5_readdata : std_logic_vector(31 downto 0); | |||
signal hardware_task_5_write : std_logic; | |||
signal hardware_task_5_writedata : std_logic_vector(31 downto 0); | |||
signal hardware_task_6_address : std_logic_vector(3 downto 0); | |||
signal hardware_task_6_read : std_logic; | |||
signal hardware_task_6_readdata : std_logic_vector(31 downto 0); | |||
signal hardware_task_6_write : std_logic; | |||
signal hardware_task_6_writedata : std_logic_vector(31 downto 0); | |||
signal data_channel_0_hw_sink_write : std_logic; | |||
signal data_channel_0_hw_sink_writedata : std_logic_vector(31 downto 0); | |||
signal data_channel_0_hw_source_read : std_logic; | |||
signal data_channel_0_hw_source_readdata : std_logic_vector(31 downto 0); | |||
signal data_channel_1_hw_sink_write : std_logic; | |||
signal data_channel_1_hw_sink_writedata : std_logic_vector(31 downto 0); | |||
signal data_channel_1_hw_source_read : std_logic; | |||
signal data_channel_1_hw_source_readdata : std_logic_vector(31 downto 0); | |||
signal data_channel_2_hw_sink_write : std_logic; | |||
signal data_channel_2_hw_sink_writedata : std_logic_vector(31 downto 0); | |||
signal data_channel_2_hw_source_read : std_logic; | |||
signal data_channel_2_hw_source_readdata : std_logic_vector(31 downto 0); | |||
signal data_channel_3_hw_sink_write : std_logic; | |||
signal data_channel_3_hw_sink_writedata : std_logic_vector(31 downto 0); | |||
signal data_channel_3_hw_source_read : std_logic; | |||
signal data_channel_3_hw_source_readdata : std_logic_vector(31 downto 0); | |||
signal data_channel_4_hw_sink_write : std_logic; | |||
signal data_channel_4_hw_sink_writedata : std_logic_vector(31 downto 0); | |||
signal data_channel_4_hw_source_read : std_logic; | |||
signal data_channel_4_hw_source_readdata : std_logic_vector(31 downto 0); | |||
signal data_channel_5_hw_sink_write : std_logic; | |||
signal data_channel_5_hw_sink_writedata : std_logic_vector(31 downto 0); | |||
signal data_channel_5_hw_source_read : std_logic; | |||
signal data_channel_5_hw_source_readdata : std_logic_vector(31 downto 0); | |||
signal data_channel_6_hw_sink_write : std_logic; | |||
signal data_channel_6_hw_sink_writedata : std_logic_vector(31 downto 0); | |||
signal data_channel_6_hw_source_read : std_logic; | |||
signal data_channel_6_hw_source_readdata : std_logic_vector(31 downto 0); | |||
begin | |||
-- Synchronize the external reset to the external clock domain | |||
u_sync_rst_50: entity work.sync_rst | |||
port map | |||
( | |||
clk => clk_input, | |||
reset => not reset_n, | |||
rst_sync => sync_reset | |||
); | |||
-- PLL for the main system clock | |||
u_pll_main: entity pll_main.pll_main | |||
port map | |||
( | |||
refclk => clk_input, -- in std_logic | |||
rst => sync_reset, -- in std_logic | |||
outclk_0 => clk_main, -- out std_logic | |||
locked => locked_main -- out std_logic | |||
); | |||
-- Synchronize the main reset to the main clock domain | |||
u_sync_rst_main: entity work.sync_rst | |||
port map | |||
( | |||
clk => clk_main, | |||
reset => not locked_main and sync_reset, | |||
rst_sync => sync_reset_main | |||
); | |||
sync_reset_main_n <= not sync_reset_main; | |||
-- NiosII system | |||
u_niosII : entity niosii.niosII | |||
port map | |||
( | |||
clk_clk => clk_main, | |||
reset_reset_n => sync_reset_main_n, | |||
key_start_export => key_start, | |||
leds_export => sw_leds, | |||
data_channel_0_hw_sink_write => data_channel_0_hw_sink_write, | |||
data_channel_0_hw_sink_writedata => data_channel_0_hw_sink_writedata, | |||
data_channel_0_hw_source_read => data_channel_0_hw_source_read, | |||
data_channel_0_hw_source_readdata => data_channel_0_hw_source_readdata, | |||
data_channel_1_hw_sink_write => data_channel_1_hw_sink_write, | |||
data_channel_1_hw_sink_writedata => data_channel_1_hw_sink_writedata, | |||
data_channel_1_hw_source_read => data_channel_1_hw_source_read, | |||
data_channel_1_hw_source_readdata => data_channel_1_hw_source_readdata, | |||
data_channel_2_hw_sink_write => data_channel_2_hw_sink_write, | |||
data_channel_2_hw_sink_writedata => data_channel_2_hw_sink_writedata, | |||
data_channel_2_hw_source_read => data_channel_2_hw_source_read, | |||
data_channel_2_hw_source_readdata => data_channel_2_hw_source_readdata, | |||
data_channel_3_hw_sink_write => data_channel_3_hw_sink_write, | |||
data_channel_3_hw_sink_writedata => data_channel_3_hw_sink_writedata, | |||
data_channel_3_hw_source_read => data_channel_3_hw_source_read, | |||
data_channel_3_hw_source_readdata => data_channel_3_hw_source_readdata, | |||
data_channel_4_hw_sink_write => data_channel_4_hw_sink_write, | |||
data_channel_4_hw_sink_writedata => data_channel_4_hw_sink_writedata, | |||
data_channel_4_hw_source_read => data_channel_4_hw_source_read, | |||
data_channel_4_hw_source_readdata => data_channel_4_hw_source_readdata, | |||
data_channel_5_hw_sink_write => data_channel_5_hw_sink_write, | |||
data_channel_5_hw_sink_writedata => data_channel_5_hw_sink_writedata, | |||
data_channel_5_hw_source_read => data_channel_5_hw_source_read, | |||
data_channel_5_hw_source_readdata => data_channel_5_hw_source_readdata, | |||
data_channel_6_hw_sink_write => data_channel_6_hw_sink_write, | |||
data_channel_6_hw_sink_writedata => data_channel_6_hw_sink_writedata, | |||
data_channel_6_hw_source_read => data_channel_6_hw_source_read, | |||
data_channel_6_hw_source_readdata => data_channel_6_hw_source_readdata, | |||
hardware_task_0_task_address => hardware_task_0_address, | |||
hardware_task_0_task_read => hardware_task_0_read, | |||
hardware_task_0_task_readdata => hardware_task_0_readdata, | |||
hardware_task_0_task_write => hardware_task_0_write, | |||
hardware_task_0_task_writedata => hardware_task_0_writedata, | |||
hardware_task_1_task_address => hardware_task_1_address, | |||
hardware_task_1_task_read => hardware_task_1_read, | |||
hardware_task_1_task_readdata => hardware_task_1_readdata, | |||
hardware_task_1_task_write => hardware_task_1_write, | |||
hardware_task_1_task_writedata => hardware_task_1_writedata, | |||
hardware_task_2_task_address => hardware_task_2_address, | |||
hardware_task_2_task_read => hardware_task_2_read, | |||
hardware_task_2_task_readdata => hardware_task_2_readdata, | |||
hardware_task_2_task_write => hardware_task_2_write, | |||
hardware_task_2_task_writedata => hardware_task_2_writedata, | |||
hardware_task_3_task_address => hardware_task_3_address, | |||
hardware_task_3_task_read => hardware_task_3_read, | |||
hardware_task_3_task_readdata => hardware_task_3_readdata, | |||
hardware_task_3_task_write => hardware_task_3_write, | |||
hardware_task_3_task_writedata => hardware_task_3_writedata, | |||
hardware_task_4_task_address => hardware_task_4_address, | |||
hardware_task_4_task_read => hardware_task_4_read, | |||
hardware_task_4_task_readdata => hardware_task_4_readdata, | |||
hardware_task_4_task_write => hardware_task_4_write, | |||
hardware_task_4_task_writedata => hardware_task_4_writedata, | |||
hardware_task_5_task_address => hardware_task_5_address, | |||
hardware_task_5_task_read => hardware_task_5_read, | |||
hardware_task_5_task_readdata => hardware_task_5_readdata, | |||
hardware_task_5_task_write => hardware_task_5_write, | |||
hardware_task_5_task_writedata => hardware_task_5_writedata, | |||
hardware_task_6_task_address => hardware_task_6_address, | |||
hardware_task_6_task_read => hardware_task_6_read, | |||
hardware_task_6_task_readdata => hardware_task_6_readdata, | |||
hardware_task_6_task_write => hardware_task_6_write, | |||
hardware_task_6_task_writedata => hardware_task_6_writedata | |||
); | |||
u_task_sine: entity work.task_sine | |||
port map ( | |||
clk => clk_main, | |||
reset => sync_reset_main, | |||
address => hardware_task_0_address, | |||
read => hardware_task_0_read, | |||
readdata => hardware_task_0_readdata, | |||
write => hardware_task_0_write, | |||
writedata => hardware_task_0_writedata, | |||
signal_write => data_channel_0_hw_sink_write , | |||
signal_writedata => data_channel_0_hw_sink_writedata | |||
); | |||
u_task_cosine: entity work.task_sine | |||
port map ( | |||
clk => clk_main, | |||
reset => sync_reset_main, | |||
address => hardware_task_1_address, | |||
read => hardware_task_1_read, | |||
readdata => hardware_task_1_readdata, | |||
write => hardware_task_1_write, | |||
writedata => hardware_task_1_writedata, | |||
signal_write => data_channel_1_hw_sink_write , | |||
signal_writedata => data_channel_1_hw_sink_writedata | |||
); | |||
u_task_rand: entity work.task_rand | |||
port map ( | |||
clk => clk_main, | |||
reset => sync_reset_main, | |||
address => hardware_task_2_address, | |||
read => hardware_task_2_read, | |||
readdata => hardware_task_2_readdata, | |||
write => hardware_task_2_write, | |||
writedata => hardware_task_2_writedata, | |||
signal_write => data_channel_2_hw_sink_write , | |||
signal_writedata => data_channel_2_hw_sink_writedata | |||
); | |||
u_task_add_sine_cosine: entity work.task_add | |||
port map ( | |||
clk => clk_main, | |||
reset => sync_reset_main, | |||
address => hardware_task_3_address, | |||
read => hardware_task_3_read, | |||
readdata => hardware_task_3_readdata, | |||
write => hardware_task_3_write, | |||
writedata => hardware_task_3_writedata, | |||
signal_a_read => data_channel_0_hw_source_read, | |||
signal_a_readdata => data_channel_0_hw_source_readdata, | |||
signal_b_read => data_channel_1_hw_source_read, | |||
signal_b_readdata => data_channel_1_hw_source_readdata, | |||
signal_write => data_channel_3_hw_sink_write , | |||
signal_writedata => data_channel_3_hw_sink_writedata | |||
); | |||
u_task_add_rand: entity work.task_add | |||
port map ( | |||
clk => clk_main, | |||
reset => sync_reset_main, | |||
address => hardware_task_4_address, | |||
read => hardware_task_4_read, | |||
readdata => hardware_task_4_readdata, | |||
write => hardware_task_4_write, | |||
writedata => hardware_task_4_writedata, | |||
signal_a_read => data_channel_2_hw_source_read, | |||
signal_a_readdata => data_channel_2_hw_source_readdata, | |||
signal_b_read => data_channel_3_hw_source_read, | |||
signal_b_readdata => data_channel_3_hw_source_readdata, | |||
signal_write => data_channel_4_hw_sink_write , | |||
signal_writedata => data_channel_4_hw_sink_writedata | |||
); | |||
u_task_fft: entity work.task_fft | |||
port map ( | |||
clk => clk_main, | |||
reset => sync_reset_main, | |||
address => hardware_task_5_address, | |||
read => hardware_task_5_read, | |||
readdata => hardware_task_5_readdata, | |||
write => hardware_task_5_write, | |||
writedata => hardware_task_5_writedata, | |||
signal_read => data_channel_4_hw_source_read, | |||
signal_readdata => data_channel_4_hw_source_readdata, | |||
signal_write => data_channel_5_hw_sink_write , | |||
signal_writedata => data_channel_5_hw_sink_writedata | |||
); | |||
u_task_crc: entity work.task_crc | |||
port map ( | |||
clk => clk_main, | |||
reset => sync_reset_main, | |||
address => hardware_task_6_address, | |||
read => hardware_task_6_read, | |||
readdata => hardware_task_6_readdata, | |||
write => hardware_task_6_write, | |||
writedata => hardware_task_6_writedata, | |||
signal_read => data_channel_5_hw_source_read, | |||
signal_readdata => data_channel_5_hw_source_readdata, | |||
signal_write => data_channel_6_hw_sink_write , | |||
signal_writedata => data_channel_6_hw_sink_writedata | |||
); | |||
hw_leds <= ( 0 => reset_n, 1 => sync_reset, 2 => locked_main, 3 => sync_reset_main, others => '0' ); | |||
leds <= sw_leds or hw_leds; | |||
end architecture struct; | |||
@@ -0,0 +1,77 @@ | |||
library ieee; | |||
use ieee.std_logic_1164.all; | |||
use ieee.numeric_std.all; | |||
library work; | |||
use work.reg32.all; | |||
use work.float.all; | |||
use work.task.all; | |||
entity sine is | |||
port ( | |||
clk : in std_logic; | |||
reset : in std_logic; | |||
task_start : in std_logic; | |||
task_state : out work.task.State; | |||
step_size : in work.reg32.word; | |||
phase : in work.reg32.word; | |||
amplitude : in work.reg32.word; | |||
signal_write : out std_logic; | |||
signal_writedata : out std_logic_vector( 31 downto 0 ) | |||
); | |||
end entity sine; | |||
architecture rtl of sine is | |||
signal current_task_state : work.task.State; | |||
signal next_task_state : work.task.State; | |||
signal index : integer range 0 to work.task.STREAM_LEN; | |||
begin | |||
task_state_transitions : process ( current_task_state, task_start, index ) is | |||
begin | |||
next_task_state <= current_task_state; | |||
case current_task_state is | |||
when work.task.TASK_IDLE => | |||
if ( task_start = '1' ) then | |||
next_task_state <= work.task.TASK_RUNNING; | |||
end if; | |||
when work.task.TASK_RUNNING => | |||
if ( index = work.task.STREAM_LEN - 1 ) then | |||
next_task_state <= work.task.TASK_DONE; | |||
end if; | |||
when work.task.TASK_DONE => | |||
if ( task_start = '1' ) then | |||
next_task_state <= work.task.TASK_RUNNING; | |||
end if; | |||
end case; | |||
end process task_state_transitions; | |||
sync : process ( clk, reset ) is | |||
begin | |||
if ( reset = '1' ) then | |||
current_task_state <= work.task.TASK_IDLE; | |||
index <= 0; | |||
elsif ( rising_edge( clk ) ) then | |||
current_task_state <= next_task_state; | |||
case next_task_state is | |||
when work.task.TASK_IDLE => | |||
index <= 0; | |||
signal_write <= '0'; | |||
when work.task.TASK_RUNNING => | |||
index <= index + 1; | |||
signal_write <= '1'; | |||
signal_writedata <= ( others => '0' ); | |||
when work.task.TASK_DONE => | |||
index <= 0; | |||
signal_write <= '0'; | |||
end case; | |||
end if; | |||
end process sync; | |||
task_state <= current_task_state; | |||
end architecture rtl; |
@@ -0,0 +1,32 @@ | |||
//---------------------------------------------------------------------- | |||
// Butterfly: Add/Sub and Scaling | |||
//---------------------------------------------------------------------- | |||
module Butterfly #( | |||
parameter WIDTH = 16, | |||
parameter RH = 0 // Round Half Up | |||
)( | |||
input signed [WIDTH-1:0] x0_re, // Input Data #0 (Real) | |||
input signed [WIDTH-1:0] x0_im, // Input Data #0 (Imag) | |||
input signed [WIDTH-1:0] x1_re, // Input Data #1 (Real) | |||
input signed [WIDTH-1:0] x1_im, // Input Data #1 (Imag) | |||
output signed [WIDTH-1:0] y0_re, // Output Data #0 (Real) | |||
output signed [WIDTH-1:0] y0_im, // Output Data #0 (Imag) | |||
output signed [WIDTH-1:0] y1_re, // Output Data #1 (Real) | |||
output signed [WIDTH-1:0] y1_im // Output Data #1 (Imag) | |||
); | |||
wire signed [WIDTH:0] add_re, add_im, sub_re, sub_im; | |||
// Add/Sub | |||
assign add_re = x0_re + x1_re; | |||
assign add_im = x0_im + x1_im; | |||
assign sub_re = x0_re - x1_re; | |||
assign sub_im = x0_im - x1_im; | |||
// Scaling | |||
assign y0_re = (add_re + RH) >>> 1; | |||
assign y0_im = (add_im + RH) >>> 1; | |||
assign y1_re = (sub_re + RH) >>> 1; | |||
assign y1_im = (sub_im + RH) >>> 1; | |||
endmodule |
@@ -0,0 +1,32 @@ | |||
//---------------------------------------------------------------------- | |||
// DelayBuffer: Generate Constant Delay | |||
//---------------------------------------------------------------------- | |||
module DelayBuffer #( | |||
parameter DEPTH = 32, | |||
parameter WIDTH = 16 | |||
)( | |||
input clock, // Master Clock | |||
input [WIDTH-1:0] di_re, // Data Input (Real) | |||
input [WIDTH-1:0] di_im, // Data Input (Imag) | |||
output [WIDTH-1:0] do_re, // Data Output (Real) | |||
output [WIDTH-1:0] do_im // Data Output (Imag) | |||
); | |||
reg [WIDTH-1:0] buf_re[0:DEPTH-1]; | |||
reg [WIDTH-1:0] buf_im[0:DEPTH-1]; | |||
integer n; | |||
// Shift Buffer | |||
always @(posedge clock) begin | |||
for (n = DEPTH-1; n > 0; n = n - 1) begin | |||
buf_re[n] <= buf_re[n-1]; | |||
buf_im[n] <= buf_im[n-1]; | |||
end | |||
buf_re[0] <= di_re; | |||
buf_im[0] <= di_im; | |||
end | |||
assign do_re = buf_re[DEPTH-1]; | |||
assign do_im = buf_im[DEPTH-1]; | |||
endmodule |
@@ -0,0 +1,89 @@ | |||
//---------------------------------------------------------------------- | |||
// FFT: 1024-Point FFT Using Radix-2^2 Single-Path Delay Feedback | |||
//---------------------------------------------------------------------- | |||
module FFTMAIN #( | |||
parameter WIDTH = 32 | |||
)( | |||
input clock, // Master Clock | |||
input reset, // Active High Asynchronous Reset | |||
input di_en, // Input Data Enable | |||
input [WIDTH-1:0] di_re, // Input Data (Real) | |||
input [WIDTH-1:0] di_im, // Input Data (Imag) | |||
output do_en, // Output Data Enable | |||
output [WIDTH-1:0] do_re, // Output Data (Real) | |||
output [WIDTH-1:0] do_im // Output Data (Imag) | |||
); | |||
//---------------------------------------------------------------------- | |||
// Data must be input consecutively in natural order. | |||
// The result is scaled to 1/N and output in bit-reversed order. | |||
//---------------------------------------------------------------------- | |||
wire su1_do_en; | |||
wire[WIDTH-1:0] su1_do_re; | |||
wire[WIDTH-1:0] su1_do_im; | |||
wire su2_do_en; | |||
wire[WIDTH-1:0] su2_do_re; | |||
wire[WIDTH-1:0] su2_do_im; | |||
wire su3_do_en; | |||
wire[WIDTH-1:0] su3_do_re; | |||
wire[WIDTH-1:0] su3_do_im; | |||
wire su4_do_en; | |||
wire[WIDTH-1:0] su4_do_re; | |||
wire[WIDTH-1:0] su4_do_im; | |||
SdfUnit #(.N(1024),.M(1024),.WIDTH(WIDTH)) SU1 ( | |||
.clock (clock ), // i | |||
.reset (reset ), // i | |||
.di_en (di_en ), // i | |||
.di_re (di_re ), // i | |||
.di_im (di_im ), // i | |||
.do_en (su1_do_en ), // o | |||
.do_re (su1_do_re ), // o | |||
.do_im (su1_do_im ) // o | |||
); | |||
SdfUnit #(.N(1024),.M(256),.WIDTH(WIDTH)) SU2 ( | |||
.clock (clock ), // i | |||
.reset (reset ), // i | |||
.di_en (su1_do_en ), // i | |||
.di_re (su1_do_re ), // i | |||
.di_im (su1_do_im ), // i | |||
.do_en (su2_do_en ), // o | |||
.do_re (su2_do_re ), // o | |||
.do_im (su2_do_im ) // o | |||
); | |||
SdfUnit #(.N(1024),.M(64),.WIDTH(WIDTH)) SU3 ( | |||
.clock (clock ), // i | |||
.reset (reset ), // i | |||
.di_en (su2_do_en ), // i | |||
.di_re (su2_do_re ), // i | |||
.di_im (su2_do_im ), // i | |||
.do_en (su3_do_en ), // o | |||
.do_re (su3_do_re ), // o | |||
.do_im (su3_do_im ) // o | |||
); | |||
SdfUnit #(.N(1024),.M(16),.WIDTH(WIDTH)) SU4 ( | |||
.clock (clock ), // i | |||
.reset (reset ), // i | |||
.di_en (su3_do_en ), // i | |||
.di_re (su3_do_re ), // i | |||
.di_im (su3_do_im ), // i | |||
.do_en (su4_do_en ), // o | |||
.do_re (su4_do_re ), // o | |||
.do_im (su4_do_im ) // o | |||
); | |||
SdfUnit #(.N(1024),.M(4),.WIDTH(WIDTH)) SU5 ( | |||
.clock (clock ), // i | |||
.reset (reset ), // i | |||
.di_en (su4_do_en ), // i | |||
.di_re (su4_do_re ), // i | |||
.di_im (su4_do_im ), // i | |||
.do_en (do_en ), // o | |||
.do_re (do_re ), // o | |||
.do_im (do_im ) // o | |||
); | |||
endmodule |
@@ -0,0 +1,35 @@ | |||
//---------------------------------------------------------------------- | |||
// Multiply: Complex Multiplier | |||
//---------------------------------------------------------------------- | |||
module Multiply #( | |||
parameter WIDTH = 16 | |||
)( | |||
input signed [WIDTH-1:0] a_re, | |||
input signed [WIDTH-1:0] a_im, | |||
input signed [WIDTH-1:0] b_re, | |||
input signed [WIDTH-1:0] b_im, | |||
output signed [WIDTH-1:0] m_re, | |||
output signed [WIDTH-1:0] m_im | |||
); | |||
wire signed [WIDTH*2-1:0] arbr, arbi, aibr, aibi; | |||
wire signed [WIDTH-1:0] sc_arbr, sc_arbi, sc_aibr, sc_aibi; | |||
// Signed Multiplication | |||
assign arbr = a_re * b_re; | |||
assign arbi = a_re * b_im; | |||
assign aibr = a_im * b_re; | |||
assign aibi = a_im * b_im; | |||
// Scaling | |||
assign sc_arbr = arbr >>> (WIDTH-1); | |||
assign sc_arbi = arbi >>> (WIDTH-1); | |||
assign sc_aibr = aibr >>> (WIDTH-1); | |||
assign sc_aibi = aibi >>> (WIDTH-1); | |||
// Sub/Add | |||
// These sub/add may overflow if unnormalized data is input. | |||
assign m_re = sc_arbr - sc_aibi; | |||
assign m_im = sc_arbi + sc_aibr; | |||
endmodule |
@@ -0,0 +1,277 @@ | |||
//---------------------------------------------------------------------- | |||
// SdfUnit: Radix-2^2 Single-Path Delay Feedback Unit for N-Point FFT | |||
//---------------------------------------------------------------------- | |||
module SdfUnit #( | |||
parameter N = 64, // Number of FFT Point | |||
parameter M = 64, // Twiddle Resolution | |||
parameter WIDTH = 16 // Data Bit Length | |||
)( | |||
input clock, // Master Clock | |||
input reset, // Active High Asynchronous Reset | |||
input di_en, // Input Data Enable | |||
input [WIDTH-1:0] di_re, // Input Data (Real) | |||
input [WIDTH-1:0] di_im, // Input Data (Imag) | |||
output do_en, // Output Data Enable | |||
output [WIDTH-1:0] do_re, // Output Data (Real) | |||
output [WIDTH-1:0] do_im // Output Data (Imag) | |||
); | |||
// log2 constant function | |||
function integer log2; | |||
input integer x; | |||
integer value; | |||
begin | |||
value = x-1; | |||
for (log2=0; value>0; log2=log2+1) | |||
value = value>>1; | |||
end | |||
endfunction | |||
localparam LOG_N = log2(N); // Bit Length of N | |||
localparam LOG_M = log2(M); // Bit Length of M | |||
//---------------------------------------------------------------------- | |||
// Internal Regs and Nets | |||
//---------------------------------------------------------------------- | |||
// 1st Butterfly | |||
reg [LOG_N-1:0] di_count; // Input Data Count | |||
wire bf1_bf; // Butterfly Add/Sub Enable | |||
wire[WIDTH-1:0] bf1_x0_re; // Data #0 to Butterfly (Real) | |||
wire[WIDTH-1:0] bf1_x0_im; // Data #0 to Butterfly (Imag) | |||
wire[WIDTH-1:0] bf1_x1_re; // Data #1 to Butterfly (Real) | |||
wire[WIDTH-1:0] bf1_x1_im; // Data #1 to Butterfly (Imag) | |||
wire[WIDTH-1:0] bf1_y0_re; // Data #0 from Butterfly (Real) | |||
wire[WIDTH-1:0] bf1_y0_im; // Data #0 from Butterfly (Imag) | |||
wire[WIDTH-1:0] bf1_y1_re; // Data #1 from Butterfly (Real) | |||
wire[WIDTH-1:0] bf1_y1_im; // Data #1 from Butterfly (Imag) | |||
wire[WIDTH-1:0] db1_di_re; // Data to DelayBuffer (Real) | |||
wire[WIDTH-1:0] db1_di_im; // Data to DelayBuffer (Imag) | |||
wire[WIDTH-1:0] db1_do_re; // Data from DelayBuffer (Real) | |||
wire[WIDTH-1:0] db1_do_im; // Data from DelayBuffer (Imag) | |||
wire[WIDTH-1:0] bf1_sp_re; // Single-Path Data Output (Real) | |||
wire[WIDTH-1:0] bf1_sp_im; // Single-Path Data Output (Imag) | |||
reg bf1_sp_en; // Single-Path Data Enable | |||
reg [LOG_N-1:0] bf1_count; // Single-Path Data Count | |||
wire bf1_start; // Single-Path Output Trigger | |||
wire bf1_end; // End of Single-Path Data | |||
wire bf1_mj; // Twiddle (-j) Enable | |||
reg [WIDTH-1:0] bf1_do_re; // 1st Butterfly Output Data (Real) | |||
reg [WIDTH-1:0] bf1_do_im; // 1st Butterfly Output Data (Imag) | |||
// 2nd Butterfly | |||
reg bf2_bf; // Butterfly Add/Sub Enable | |||
wire[WIDTH-1:0] bf2_x0_re; // Data #0 to Butterfly (Real) | |||
wire[WIDTH-1:0] bf2_x0_im; // Data #0 to Butterfly (Imag) | |||
wire[WIDTH-1:0] bf2_x1_re; // Data #1 to Butterfly (Real) | |||
wire[WIDTH-1:0] bf2_x1_im; // Data #1 to Butterfly (Imag) | |||
wire[WIDTH-1:0] bf2_y0_re; // Data #0 from Butterfly (Real) | |||
wire[WIDTH-1:0] bf2_y0_im; // Data #0 from Butterfly (Imag) | |||
wire[WIDTH-1:0] bf2_y1_re; // Data #1 from Butterfly (Real) | |||
wire[WIDTH-1:0] bf2_y1_im; // Data #1 from Butterfly (Imag) | |||
wire[WIDTH-1:0] db2_di_re; // Data to DelayBuffer (Real) | |||
wire[WIDTH-1:0] db2_di_im; // Data to DelayBuffer (Imag) | |||
wire[WIDTH-1:0] db2_do_re; // Data from DelayBuffer (Real) | |||
wire[WIDTH-1:0] db2_do_im; // Data from DelayBuffer (Imag) | |||
wire[WIDTH-1:0] bf2_sp_re; // Single-Path Data Output (Real) | |||
wire[WIDTH-1:0] bf2_sp_im; // Single-Path Data Output (Imag) | |||
reg bf2_sp_en; // Single-Path Data Enable | |||
reg [LOG_N-1:0] bf2_count; // Single-Path Data Count | |||
reg bf2_start; // Single-Path Output Trigger | |||
wire bf2_end; // End of Single-Path Data | |||
reg [WIDTH-1:0] bf2_do_re; // 2nd Butterfly Output Data (Real) | |||
reg [WIDTH-1:0] bf2_do_im; // 2nd Butterfly Output Data (Imag) | |||
reg bf2_do_en; // 2nd Butterfly Output Data Enable | |||
// Multiplication | |||
wire[1:0] tw_sel; // Twiddle Select (2n/n/3n) | |||
wire[LOG_N-3:0] tw_num; // Twiddle Number (n) | |||
wire[LOG_N-1:0] tw_addr; // Twiddle Table Address | |||
wire[WIDTH-1:0] tw_re; // Twiddle Factor (Real) | |||
wire[WIDTH-1:0] tw_im; // Twiddle Factor (Imag) | |||
reg mu_en; // Multiplication Enable | |||
wire[WIDTH-1:0] mu_a_re; // Multiplier Input (Real) | |||
wire[WIDTH-1:0] mu_a_im; // Multiplier Input (Imag) | |||
wire[WIDTH-1:0] mu_m_re; // Multiplier Output (Real) | |||
wire[WIDTH-1:0] mu_m_im; // Multiplier Output (Imag) | |||
reg [WIDTH-1:0] mu_do_re; // Multiplication Output Data (Real) | |||
reg [WIDTH-1:0] mu_do_im; // Multiplication Output Data (Imag) | |||
reg mu_do_en; // Multiplication Output Data Enable | |||
//---------------------------------------------------------------------- | |||
// 1st Butterfly | |||
//---------------------------------------------------------------------- | |||
always @(posedge clock or posedge reset) begin | |||
if (reset) begin | |||
di_count <= {LOG_N{1'b0}}; | |||
end else begin | |||
di_count <= di_en ? (di_count + 1'b1) : {LOG_N{1'b0}}; | |||
end | |||
end | |||
assign bf1_bf = di_count[LOG_M-1]; | |||
// Set unknown value x for verification | |||
assign bf1_x0_re = bf1_bf ? db1_do_re : {WIDTH{1'bx}}; | |||
assign bf1_x0_im = bf1_bf ? db1_do_im : {WIDTH{1'bx}}; | |||
assign bf1_x1_re = bf1_bf ? di_re : {WIDTH{1'bx}}; | |||
assign bf1_x1_im = bf1_bf ? di_im : {WIDTH{1'bx}}; | |||
Butterfly #(.WIDTH(WIDTH),.RH(0)) BF1 ( | |||
.x0_re (bf1_x0_re ), // i | |||
.x0_im (bf1_x0_im ), // i | |||
.x1_re (bf1_x1_re ), // i | |||
.x1_im (bf1_x1_im ), // i | |||
.y0_re (bf1_y0_re ), // o | |||
.y0_im (bf1_y0_im ), // o | |||
.y1_re (bf1_y1_re ), // o | |||
.y1_im (bf1_y1_im ) // o | |||
); | |||
DelayBuffer #(.DEPTH(2**(LOG_M-1)),.WIDTH(WIDTH)) DB1 ( | |||
.clock (clock ), // i | |||
.di_re (db1_di_re ), // i | |||
.di_im (db1_di_im ), // i | |||
.do_re (db1_do_re ), // o | |||
.do_im (db1_do_im ) // o | |||
); | |||
assign db1_di_re = bf1_bf ? bf1_y1_re : di_re; | |||
assign db1_di_im = bf1_bf ? bf1_y1_im : di_im; | |||
assign bf1_sp_re = bf1_bf ? bf1_y0_re : bf1_mj ? db1_do_im : db1_do_re; | |||
assign bf1_sp_im = bf1_bf ? bf1_y0_im : bf1_mj ? -db1_do_re : db1_do_im; | |||
always @(posedge clock or posedge reset) begin | |||
if (reset) begin | |||
bf1_sp_en <= 1'b0; | |||
bf1_count <= {LOG_N{1'b0}}; | |||
end else begin | |||
bf1_sp_en <= bf1_start ? 1'b1 : bf1_end ? 1'b0 : bf1_sp_en; | |||
bf1_count <= bf1_sp_en ? (bf1_count + 1'b1) : {LOG_N{1'b0}}; | |||
end | |||
end | |||
assign bf1_start = (di_count == (2**(LOG_M-1)-1)); | |||
assign bf1_end = (bf1_count == (2**LOG_N-1)); | |||
assign bf1_mj = (bf1_count[LOG_M-1:LOG_M-2] == 2'd3); | |||
always @(posedge clock) begin | |||
bf1_do_re <= bf1_sp_re; | |||
bf1_do_im <= bf1_sp_im; | |||
end | |||
//---------------------------------------------------------------------- | |||
// 2nd Butterfly | |||
//---------------------------------------------------------------------- | |||
always @(posedge clock) begin | |||
bf2_bf <= bf1_count[LOG_M-2]; | |||
end | |||
// Set unknown value x for verification | |||
assign bf2_x0_re = bf2_bf ? db2_do_re : {WIDTH{1'bx}}; | |||
assign bf2_x0_im = bf2_bf ? db2_do_im : {WIDTH{1'bx}}; | |||
assign bf2_x1_re = bf2_bf ? bf1_do_re : {WIDTH{1'bx}}; | |||
assign bf2_x1_im = bf2_bf ? bf1_do_im : {WIDTH{1'bx}}; | |||
// Negative bias occurs when RH=0 and positive bias occurs when RH=1. | |||
// Using both alternately reduces the overall rounding error. | |||
Butterfly #(.WIDTH(WIDTH),.RH(1)) BF2 ( | |||
.x0_re (bf2_x0_re ), // i | |||
.x0_im (bf2_x0_im ), // i | |||
.x1_re (bf2_x1_re ), // i | |||
.x1_im (bf2_x1_im ), // i | |||
.y0_re (bf2_y0_re ), // o | |||
.y0_im (bf2_y0_im ), // o | |||
.y1_re (bf2_y1_re ), // o | |||
.y1_im (bf2_y1_im ) // o | |||
); | |||
DelayBuffer #(.DEPTH(2**(LOG_M-2)),.WIDTH(WIDTH)) DB2 ( | |||
.clock (clock ), // i | |||
.di_re (db2_di_re ), // i | |||
.di_im (db2_di_im ), // i | |||
.do_re (db2_do_re ), // o | |||
.do_im (db2_do_im ) // o | |||
); | |||
assign db2_di_re = bf2_bf ? bf2_y1_re : bf1_do_re; | |||
assign db2_di_im = bf2_bf ? bf2_y1_im : bf1_do_im; | |||
assign bf2_sp_re = bf2_bf ? bf2_y0_re : db2_do_re; | |||
assign bf2_sp_im = bf2_bf ? bf2_y0_im : db2_do_im; | |||
always @(posedge clock or posedge reset) begin | |||
if (reset) begin | |||
bf2_sp_en <= 1'b0; | |||
bf2_count <= {LOG_N{1'b0}}; | |||
end else begin | |||
bf2_sp_en <= bf2_start ? 1'b1 : bf2_end ? 1'b0 : bf2_sp_en; | |||
bf2_count <= bf2_sp_en ? (bf2_count + 1'b1) : {LOG_N{1'b0}}; | |||
end | |||
end | |||
always @(posedge clock) begin | |||
bf2_start <= (bf1_count == (2**(LOG_M-2)-1)) & bf1_sp_en; | |||
end | |||
assign bf2_end = (bf2_count == (2**LOG_N-1)); | |||
always @(posedge clock) begin | |||
bf2_do_re <= bf2_sp_re; | |||
bf2_do_im <= bf2_sp_im; | |||
end | |||
always @(posedge clock or posedge reset) begin | |||
if (reset) begin | |||
bf2_do_en <= 1'b0; | |||
end else begin | |||
bf2_do_en <= bf2_sp_en; | |||
end | |||
end | |||
//---------------------------------------------------------------------- | |||
// Multiplication | |||
//---------------------------------------------------------------------- | |||
assign tw_sel[1] = bf2_count[LOG_M-2]; | |||
assign tw_sel[0] = bf2_count[LOG_M-1]; | |||
assign tw_num = bf2_count << (LOG_N-LOG_M); | |||
assign tw_addr = tw_num * tw_sel; | |||
Twiddle TW ( | |||
.clock (clock ), // i | |||
.addr (tw_addr), // i | |||
.tw_re (tw_re ), // o | |||
.tw_im (tw_im ) // o | |||
); | |||
// Multiplication is bypassed when twiddle address is 0. | |||
always @(posedge clock) begin | |||
mu_en <= (tw_addr != {LOG_N{1'b0}}); | |||
end | |||
// Set unknown value x for verification | |||
assign mu_a_re = mu_en ? bf2_do_re : {WIDTH{1'bx}}; | |||
assign mu_a_im = mu_en ? bf2_do_im : {WIDTH{1'bx}}; | |||
Multiply #(.WIDTH(WIDTH)) MU ( | |||
.a_re (mu_a_re), // i | |||
.a_im (mu_a_im), // i | |||
.b_re (tw_re ), // i | |||
.b_im (tw_im ), // i | |||
.m_re (mu_m_re), // o | |||
.m_im (mu_m_im) // o | |||
); | |||
always @(posedge clock) begin | |||
mu_do_re <= mu_en ? mu_m_re : bf2_do_re; | |||
mu_do_im <= mu_en ? mu_m_im : bf2_do_im; | |||
end | |||
always @(posedge clock or posedge reset) begin | |||
if (reset) begin | |||
mu_do_en <= 1'b0; | |||
end else begin | |||
mu_do_en <= bf2_do_en; | |||
end | |||
end | |||
// No multiplication required at final stage | |||
assign do_en = (LOG_M == 2) ? bf2_do_en : mu_do_en; | |||
assign do_re = (LOG_M == 2) ? bf2_do_re : mu_do_re; | |||
assign do_im = (LOG_M == 2) ? bf2_do_im : mu_do_im; | |||
endmodule |
@@ -0,0 +1,94 @@ | |||
//---------------------------------------------------------------------- | |||
// SdfUnit2: Radix-2 SDF Dedicated for Twiddle Resolution M = 2 | |||
//---------------------------------------------------------------------- | |||
module SdfUnit2 #( | |||
parameter WIDTH = 16, // Data Bit Length | |||
parameter BF_RH = 0 // Butterfly Round Half Up | |||
)( | |||
input clock, // Master Clock | |||
input reset, // Active High Asynchronous Reset | |||
input di_en, // Input Data Enable | |||
input [WIDTH-1:0] di_re, // Input Data (Real) | |||
input [WIDTH-1:0] di_im, // Input Data (Imag) | |||
output reg do_en, // Output Data Enable | |||
output reg [WIDTH-1:0] do_re, // Output Data (Real) | |||
output reg [WIDTH-1:0] do_im // Output Data (Imag) | |||
); | |||
//---------------------------------------------------------------------- | |||
// Internal Regs and Nets | |||
//---------------------------------------------------------------------- | |||
reg bf_en; // Butterfly Add/Sub Enable | |||
wire[WIDTH-1:0] x0_re; // Data #0 to Butterfly (Real) | |||
wire[WIDTH-1:0] x0_im; // Data #0 to Butterfly (Imag) | |||
wire[WIDTH-1:0] x1_re; // Data #1 to Butterfly (Real) | |||
wire[WIDTH-1:0] x1_im; // Data #1 to Butterfly (Imag) | |||
wire[WIDTH-1:0] y0_re; // Data #0 from Butterfly (Real) | |||
wire[WIDTH-1:0] y0_im; // Data #0 from Butterfly (Imag) | |||
wire[WIDTH-1:0] y1_re; // Data #1 from Butterfly (Real) | |||
wire[WIDTH-1:0] y1_im; // Data #1 from Butterfly (Imag) | |||
wire[WIDTH-1:0] db_di_re; // Data to DelayBuffer (Real) | |||
wire[WIDTH-1:0] db_di_im; // Data to DelayBuffer (Imag) | |||
wire[WIDTH-1:0] db_do_re; // Data from DelayBuffer (Real) | |||
wire[WIDTH-1:0] db_do_im; // Data from DelayBuffer (Imag) | |||
wire[WIDTH-1:0] bf_sp_re; // Single-Path Data Output (Real) | |||
wire[WIDTH-1:0] bf_sp_im; // Single-Path Data Output (Imag) | |||
reg bf_sp_en; // Single-Path Data Enable | |||
//---------------------------------------------------------------------- | |||
// Butterfly Add/Sub | |||
//---------------------------------------------------------------------- | |||
always @(posedge clock or posedge reset) begin | |||
if (reset) begin | |||
bf_en <= 1'b0; | |||
end else begin | |||
bf_en <= di_en ? ~bf_en : 1'b0; | |||
end | |||
end | |||
// Set unknown value x for verification | |||
assign x0_re = bf_en ? db_do_re : {WIDTH{1'bx}}; | |||
assign x0_im = bf_en ? db_do_im : {WIDTH{1'bx}}; | |||
assign x1_re = bf_en ? di_re : {WIDTH{1'bx}}; | |||
assign x1_im = bf_en ? di_im : {WIDTH{1'bx}}; | |||
Butterfly #(.WIDTH(WIDTH),.RH(BF_RH)) BF ( | |||
.x0_re (x0_re ), // i | |||
.x0_im (x0_im ), // i | |||
.x1_re (x1_re ), // i | |||
.x1_im (x1_im ), // i | |||
.y0_re (y0_re ), // o | |||
.y0_im (y0_im ), // o | |||
.y1_re (y1_re ), // o | |||
.y1_im (y1_im ) // o | |||
); | |||
DelayBuffer #(.DEPTH(1),.WIDTH(WIDTH)) DB ( | |||
.clock (clock ), // i | |||
.di_re (db_di_re ), // i | |||
.di_im (db_di_im ), // i | |||
.do_re (db_do_re ), // o | |||
.do_im (db_do_im ) // o | |||
); | |||
assign db_di_re = bf_en ? y1_re : di_re; | |||
assign db_di_im = bf_en ? y1_im : di_im; | |||
assign bf_sp_re = bf_en ? y0_re : db_do_re; | |||
assign bf_sp_im = bf_en ? y0_im : db_do_im; | |||
always @(posedge clock or posedge reset) begin | |||
if (reset) begin | |||
bf_sp_en <= 1'b0; | |||
do_en <= 1'b0; | |||
end else begin | |||
bf_sp_en <= di_en; | |||
do_en <= bf_sp_en; | |||
end | |||
end | |||
always @(posedge clock) begin | |||
do_re <= bf_sp_re; | |||
do_im <= bf_sp_im; | |||
end | |||
endmodule |
@@ -0,0 +1,24 @@ | |||
library ieee; | |||
use ieee.std_logic_1164.all; | |||
package avalon_slave is | |||
type State is ( | |||
SLAVE_IDLE, | |||
SLAVE_READ, | |||
SLAVE_READ_DATA, | |||
SLAVE_WRITE | |||
); | |||
type Request is record | |||
address : std_logic_vector( 3 downto 0 ); | |||
read : std_logic; | |||
write : std_logic; | |||
writedata : std_logic_vector( 31 downto 0 ); | |||
end record Request; | |||
type Response is record | |||
readdata : std_logic_vector( 31 downto 0 ); | |||
end record Response; | |||
end package avalon_slave; |
@@ -0,0 +1,89 @@ | |||
library ieee; | |||
use ieee.std_logic_1164.all; | |||
use ieee.numeric_std.all; | |||
library work; | |||
use work.reg32.all; | |||
use work.avalon_slave.all; | |||
entity avalon_slave_transitions is | |||
generic ( | |||
REG_COUNT : natural; | |||
REG_ACCESS_TYPES : work.reg32.AccessArray | |||
); | |||
port ( | |||
address : in std_logic_vector( 3 downto 0 ); | |||
read : in std_logic; | |||
write : in std_logic; | |||
current_state : in work.avalon_slave.State; | |||
next_state : out work.avalon_slave.State; | |||
reg_index : out integer range 0 to REG_COUNT - 1 | |||
); | |||
end entity avalon_slave_transitions; | |||
architecture rtl of avalon_slave_transitions is | |||
signal is_access : boolean; | |||
signal is_read : boolean; | |||
signal is_write : boolean; | |||
signal address_index : integer range 0 to 2 ** address'high - 1; | |||
signal is_valid_reg_index : boolean; | |||
signal access_type : work.reg32.AccessType; | |||
signal is_valid_access : boolean; | |||
signal is_valid_access_type : boolean; | |||
signal index : integer range 0 to REG_COUNT - 1; | |||
begin | |||
c_is_access: is_access <= ( read or write ) = '1'; | |||
c_is_read: is_read <= read = '1'; | |||
c_is_write: is_write <= write = '1' and not is_read; | |||
c_address_index: address_index <= to_integer( unsigned( address ) ); | |||
c_is_valid_reg_index: is_valid_reg_index <= address_index <= ( REG_COUNT - 1 ); | |||
c_index: index <= address_index when is_valid_reg_index else 0; | |||
c_reg_index: reg_index <= index; | |||
c_access_type: access_type <= REG_ACCESS_TYPES( index ); | |||
c_is_valid_access_type: is_valid_access_type <= true when | |||
( is_read and work.reg32.allows_read( access_type ) ) or | |||
( is_write and work.reg32.allows_write( access_type ) ) | |||
else false; | |||
c_is_valid_access: is_valid_access <= is_access and is_valid_reg_index and | |||
is_valid_access_type; | |||
transition : process( all ) is | |||
begin | |||
case current_state is | |||
when SLAVE_IDLE => | |||
if ( is_valid_access and is_read ) then | |||
next_state <= SLAVE_READ; | |||
elsif ( is_valid_access and is_write ) then | |||
next_state <= SLAVE_WRITE; | |||
else | |||
next_state <= SLAVE_IDLE; | |||
end if; | |||
when SLAVE_READ => | |||
next_state <= SLAVE_READ_DATA; | |||
when SLAVE_READ_DATA => | |||
if ( is_valid_access and is_read ) then | |||
next_state <= SLAVE_READ; | |||
elsif ( is_valid_access and is_write ) then | |||
next_state <= SLAVE_WRITE; | |||
else | |||
next_state <= SLAVE_IDLE; | |||
end if; | |||
when SLAVE_WRITE => | |||
next_state <= SLAVE_IDLE; | |||
end case; | |||
end process transition; | |||
end architecture rtl; |
@@ -0,0 +1,120 @@ | |||
library ieee; | |||
use ieee.std_logic_1164.all; | |||
use ieee.numeric_std.all; | |||
use ieee.math_real.all; | |||
library work; | |||
use work.cordic_pkg.all; | |||
entity cordic is | |||
generic ( | |||
SIZE : positive; | |||
ITERATIONS : positive; | |||
RESET_ACTIVE_LEVEL : std_ulogic := '1' | |||
); | |||
port ( | |||
Clock : in std_ulogic; | |||
Reset : in std_ulogic; | |||
Data_valid : in std_ulogic; --# Load new input data | |||
Busy : out std_ulogic; --# Generating new result | |||
Result_valid : out std_ulogic; --# Flag when result is valid | |||
Mode : in cordic_mode; --# Rotation or vector mode selection | |||
X : in signed(SIZE-1 downto 0); | |||
Y : in signed(SIZE-1 downto 0); | |||
Z : in signed(SIZE-1 downto 0); | |||
X_result : out signed(SIZE-1 downto 0); | |||
Y_result : out signed(SIZE-1 downto 0); | |||
Z_result : out signed(SIZE-1 downto 0) | |||
); | |||
end entity; | |||
architecture rtl of cordic is | |||
type signed_array is array (natural range <>) of signed(SIZE-1 downto 0); | |||
function gen_atan_table(s : positive) return signed_array is | |||
variable table : signed_array(0 to ITERATIONS-1); | |||
begin | |||
for i in table'range loop | |||
table(i) := to_signed(integer(arctan(2.0**(-i)) * 2.0**s / MATH_2_PI), s); | |||
end loop; | |||
return table; | |||
end function; | |||
constant ATAN_TABLE : signed_array(0 to ITERATIONS-1) := gen_atan_table(SIZE); | |||
signal xr : signed(X'range); | |||
signal yr : signed(Y'range); | |||
signal zr : signed(Z'range); | |||
signal x_shift : signed(X'range); | |||
signal y_shift : signed(Y'range); | |||
subtype iter_count is integer range 0 to ITERATIONS; | |||
signal cur_iter : iter_count; | |||
begin | |||
p_cordic: process(Clock, Reset) is | |||
variable negative : boolean; | |||
begin | |||
if Reset = RESET_ACTIVE_LEVEL then | |||
xr <= (others => '0'); | |||
yr <= (others => '0'); | |||
zr <= (others => '0'); | |||
cur_iter <= 0; | |||
Result_valid <= '0'; | |||
Busy <= '0'; | |||
elsif rising_edge(Clock) then | |||
if Data_valid = '1' then | |||
xr <= X; | |||
yr <= Y; | |||
zr <= Z; | |||
cur_iter <= 0; | |||
Result_valid <= '0'; | |||
Busy <= '1'; | |||
else | |||
if cur_iter /= ITERATIONS then | |||
--if cur_iter(ITERATIONS) /= '1' then | |||
if Mode = cordic_rotate then | |||
negative := zr(z'high) = '1'; | |||
else | |||
negative := yr(y'high) = '0'; | |||
end if; | |||
--if zr(z'high) = '1' then -- z or y is negative | |||
if negative then | |||
xr <= xr + y_shift; --(yr / 2**(cur_iter)); | |||
yr <= yr - x_shift; --(xr / 2**(cur_iter)); | |||
zr <= zr + ATAN_TABLE(cur_iter); | |||
else -- z or y is positive | |||
xr <= xr - y_shift; --(yr / 2**(cur_iter)); | |||
yr <= yr + x_shift; --(xr / 2**(cur_iter)); | |||
zr <= zr - ATAN_TABLE(cur_iter); | |||
end if; | |||
cur_iter <= cur_iter + 1; | |||
--cur_iter <= '0' & cur_iter(0 to ITERATIONS-1); | |||
end if; | |||
if cur_iter = ITERATIONS-1 then | |||
Result_valid <= '1'; | |||
Busy <= '0'; | |||
end if; | |||
end if; | |||
end if; | |||
end process; | |||
x_shift <= shift_right(xr, cur_iter); | |||
y_shift <= shift_right(yr, cur_iter); | |||
X_result <= xr; | |||
Y_result <= yr; | |||
Z_result <= zr; | |||
end architecture; |
@@ -0,0 +1,45 @@ | |||
library ieee; | |||
use ieee.std_logic_1164.all; | |||
use ieee.numeric_std.all; | |||
use ieee.math_real.all; | |||
package cordic_pkg is | |||
type cordic_mode is (cordic_rotate, cordic_vector); | |||
function cordic_gain(Iterations : positive) return real; | |||
procedure adjust_angle(x, y, z : in signed; signal xa, ya, za : out signed); | |||
end package cordic_pkg; | |||
package body cordic_pkg is | |||
function cordic_gain(iterations : positive) return real is | |||
variable g : real := 1.0; | |||
begin | |||
for i in 0 to iterations-1 loop | |||
g := g * sqrt(1.0 + 2.0**(-2*i)); | |||
end loop; | |||
return g; | |||
end function; | |||
procedure adjust_angle(x, y, z : in signed; signal xa, ya, za : out signed) is | |||
variable quad : unsigned(1 downto 0); | |||
variable zp : signed(z'length-1 downto 0) := z; | |||
variable yp : signed(y'length-1 downto 0) := y; | |||
variable xp : signed(x'length-1 downto 0) := x; | |||
begin | |||
-- 0-based quadrant number of angle | |||
quad := unsigned(zp(zp'high downto zp'high-1)); | |||
if quad = 1 or quad = 2 then -- Rotate into quadrant 0 and 3 (right half of plane) | |||
xp := -xp; | |||
yp := -yp; | |||
-- Add 180 degrees (flip the sign bit) | |||
zp := (not zp(zp'left)) & zp(zp'left-1 downto 0); | |||
end if; | |||
xa <= xp; | |||
ya <= yp; | |||
za <= zp; | |||
end procedure; | |||
end package body cordic_pkg; |
@@ -0,0 +1,25 @@ | |||