Browse Source

Initial commit

master
Johannes Kutning 6 months ago
commit
0d1b73e3e0
100 changed files with 10941 additions and 0 deletions
  1. 20
    0
      .gitignore
  2. 199
    0
      Makefile
  3. 195
    0
      data_channel_hw.tcl
  4. 32
    0
      hardware/signal_processing.sdc
  5. 77
    0
      hardware/signal_processing/add.vhd
  6. 76
    0
      hardware/signal_processing/crc.vhd
  7. 97
    0
      hardware/signal_processing/fft.vhd
  8. 73
    0
      hardware/signal_processing/rand.vhd
  9. 363
    0
      hardware/signal_processing/signal_processing.vhd
  10. 77
    0
      hardware/signal_processing/sine.vhd
  11. 32
    0
      hardware/system/Butterfly.v
  12. 32
    0
      hardware/system/DelayBuffer.v
  13. 89
    0
      hardware/system/FFT1024_32B.v
  14. 35
    0
      hardware/system/Multiply.v
  15. 277
    0
      hardware/system/SdfUnit.v
  16. 94
    0
      hardware/system/SdfUnit2.v
  17. 1064
    0
      hardware/system/Twiddle1024_32B.v
  18. 24
    0
      hardware/system/avalon_slave.vhd
  19. 89
    0
      hardware/system/avalon_slave_transitions.vhd
  20. 120
    0
      hardware/system/cordic.vhd
  21. 45
    0
      hardware/system/cordic_pkg.vhd
  22. 25
    0
      hardware/system/data_channel.cmp.vhd
  23. 122
    0
      hardware/system/data_channel.vhd
  24. 151
    0
      hardware/system/data_channel_control.vhd
  25. 194
    0
      hardware/system/data_channel_hw.tcl
  26. 26
    0
      hardware/system/data_sink_mux.vhd
  27. 26
    0
      hardware/system/data_source_mux.vhd
  28. 180
    0
      hardware/system/fft_magnitude_calc.vhd
  29. 118
    0
      hardware/system/fifo.vhd
  30. 83
    0
      hardware/system/fixed_sine.vhd
  31. 144
    0
      hardware/system/float.vhd
  32. 133
    0
      hardware/system/float_add.vhd
  33. 49
    0
      hardware/system/float_sine.vhd
  34. 22
    0
      hardware/system/hardware_task.cmp.vhd
  35. 31
    0
      hardware/system/hardware_task.vhd
  36. 137
    0
      hardware/system/hardware_task_control.vhd
  37. 13
    0
      hardware/system/hardware_timestamp.cmp.vhd
  38. 102
    0
      hardware/system/hardware_timestamp.vhd
  39. 82
    0
      hardware/system/pll/pll_main.bsf
  40. 9
    0
      hardware/system/pll/pll_main.cmp
  41. 13
    0
      hardware/system/pll/pll_main.ppf
  42. 337
    0
      hardware/system/pll/pll_main.qip
  43. 6
    0
      hardware/system/pll/pll_main.sip
  44. 6
    0
      hardware/system/pll/pll_main.spd
  45. 271
    0
      hardware/system/pll/pll_main.vhd
  46. 4
    0
      hardware/system/pll/pll_main/pll_main_0002.qip
  47. 87
    0
      hardware/system/pll/pll_main/pll_main_0002.v
  48. 1
    0
      hardware/system/pll/pll_main_sim.f
  49. 284
    0
      hardware/system/pll/pll_main_sim/aldec/rivierapro_setup.tcl
  50. 18
    0
      hardware/system/pll/pll_main_sim/cadence/cds.lib
  51. 2
    0
      hardware/system/pll/pll_main_sim/cadence/hdl.var
  52. 202
    0
      hardware/system/pll/pll_main_sim/cadence/ncsim_setup.sh
  53. 278
    0
      hardware/system/pll/pll_main_sim/mentor/msim_setup.tcl
  54. 307
    0
      hardware/system/pll/pll_main_sim/pll_main.vho
  55. 12
    0
      hardware/system/pll/pll_main_sim/synopsys/vcsmx/synopsys_sim.setup
  56. 202
    0
      hardware/system/pll/pll_main_sim/synopsys/vcsmx/vcsmx_setup.sh
  57. 42
    0
      hardware/system/reg32.vhd
  58. 119
    0
      hardware/system/squareRoot_pipe.vhd
  59. 50
    0
      hardware/system/sync_ff.vhd
  60. 43
    0
      hardware/system/sync_rst.vhd
  61. 41
    0
      hardware/system/task.vhd
  62. 73
    0
      hardware/system/task_add.vhd
  63. 67
    0
      hardware/system/task_crc.vhd
  64. 73
    0
      hardware/system/task_fft.vhd
  65. 62
    0
      hardware/system/task_rand.vhd
  66. 65
    0
      hardware/system/task_sine.vhd
  67. 154
    0
      hardware_task_hw.tcl
  68. 120
    0
      hardware_timestamp_hw.tcl
  69. 51
    0
      hdl_sources.qsf
  70. 19
    0
      init.sh
  71. 1307
    0
      niosII.qsys
  72. 15
    0
      signal_processing.cdf
  73. 31
    0
      signal_processing.qpf
  74. 90
    0
      signal_processing.qsf
  75. 90
    0
      software/signal_processing/.cproject
  76. 7
    0
      software/signal_processing/.gitignore
  77. 40
    0
      software/signal_processing/.project
  78. 1050
    0
      software/signal_processing/Makefile
  79. 11
    0
      software/signal_processing/add.c
  80. 11
    0
      software/signal_processing/crc.c
  81. 12
    0
      software/signal_processing/fft.c
  82. 27
    0
      software/signal_processing/main.c
  83. 12
    0
      software/signal_processing/rand.c
  84. 10
    0
      software/signal_processing/sine.c
  85. 83
    0
      software/signal_processing/system/Complex.c
  86. 27
    0
      software/signal_processing/system/Complex.h
  87. 6
    0
      software/signal_processing/system/add_config.h
  88. 42
    0
      software/signal_processing/system/binding.c
  89. 32
    0
      software/signal_processing/system/binding.h
  90. 8
    0
      software/signal_processing/system/crc_config.h
  91. 99
    0
      software/signal_processing/system/data_channel.c
  92. 35
    0
      software/signal_processing/system/data_channel.h
  93. 9
    0
      software/signal_processing/system/fft_config.h
  94. 9
    0
      software/signal_processing/system/float_word.h
  95. 32
    0
      software/signal_processing/system/hardware_task.c
  96. 27
    0
      software/signal_processing/system/hardware_task.h
  97. 30
    0
      software/signal_processing/system/hardware_timestamp.c
  98. 10
    0
      software/signal_processing/system/hardware_timestamp.h
  99. 13
    0
      software/signal_processing/system/rand_config.h
  100. 0
    0
      software/signal_processing/system/signal_processing.c

+ 20
- 0
.gitignore View File

@@ -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


+ 199
- 0
Makefile View File

@@ -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


+ 195
- 0
data_channel_hw.tcl View File

@@ -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


+ 32
- 0
hardware/signal_processing.sdc View File

@@ -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] \
}]


+ 77
- 0
hardware/signal_processing/add.vhd View File

@@ -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;

+ 76
- 0
hardware/signal_processing/crc.vhd View File

@@ -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;


+ 97
- 0
hardware/signal_processing/fft.vhd View File

@@ -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;

+ 73
- 0
hardware/signal_processing/rand.vhd View File

@@ -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;

+ 363
- 0
hardware/signal_processing/signal_processing.vhd View File

@@ -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;


+ 77
- 0
hardware/signal_processing/sine.vhd View File

@@ -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;

+ 32
- 0
hardware/system/Butterfly.v View File

@@ -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

+ 32
- 0
hardware/system/DelayBuffer.v View File

@@ -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

+ 89
- 0
hardware/system/FFT1024_32B.v View File

@@ -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

+ 35
- 0
hardware/system/Multiply.v View File

@@ -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

+ 277
- 0
hardware/system/SdfUnit.v View File

@@ -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

+ 94
- 0
hardware/system/SdfUnit2.v View File

@@ -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

+ 1064
- 0
hardware/system/Twiddle1024_32B.v
File diff suppressed because it is too large
View File


+ 24
- 0
hardware/system/avalon_slave.vhd View File

@@ -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;

+ 89
- 0
hardware/system/avalon_slave_transitions.vhd View File

@@ -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;

+ 120
- 0
hardware/system/cordic.vhd View File

@@ -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;

+ 45
- 0
hardware/system/cordic_pkg.vhd View File

@@ -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;

+ 25
- 0
hardware/system/data_channel.cmp.vhd View File

@@ -0,0 +1,25 @@