Compare commits
9 Commits
labor-vers
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 365e95d3a0 | |||
|
|
71a6ddcf3b | ||
|
|
8658ac24db | ||
|
|
2f3e03827a | ||
|
|
e6b05276d8 | ||
|
|
9d6838aca3 | ||
| b1f3a5c0bc | |||
| 336a393655 | |||
| 19aadb159e |
58
Readme.md
58
Readme.md
@ -33,10 +33,11 @@ Zedboard Pin | Description
|
|||||||
--------------------------------|---------------
|
--------------------------------|---------------
|
||||||
JC1 PMOD Connector (Upper Row) | PMOD-AD1 Board
|
JC1 PMOD Connector (Upper Row) | PMOD-AD1 Board
|
||||||
JD1 PMOD Connector (Upper Row) | PMOD-DA3 Board
|
JD1 PMOD Connector (Upper Row) | PMOD-DA3 Board
|
||||||
JA1 PMOD JA1 Pin | Optional External Clock [NOTE: Clk has to be connected in VHDL and PLL has to be reconfigured accordingly]
|
JA1 PMOD JA4 Pin | (Optional) External Clock [NOTE: Clk has to be connected in VHDL and PLL has to be reconfigured accordingly]
|
||||||
JA1 PMOD JA4 Pin | External SYNC Pulse [NOTE: if pin is left unconnected (floating), it will register as a pulse]
|
JA1 PMOD JA1 Pin | External SYNC Pulse [NOTE: if pin is left unconnected (floating), it will register as a pulse]
|
||||||
SW7 | Standby / Write Mode (Allows xillinux to write configuration)
|
SW7 | Standby / Operation Mode (Allows xillinux to write configuration if in Standby Mode)
|
||||||
LED7 | Standby Status
|
LED7 | Standby Mode Status (ON if FPGA in Standby Mode)
|
||||||
|
LED6 | Sync Status (ON if Sync Pulse was registered)
|
||||||
BTNC | Global reset
|
BTNC | Global reset
|
||||||
BTNU | Debug value reset
|
BTNU | Debug value reset
|
||||||
|
|
||||||
@ -45,20 +46,36 @@ BTNU | Debug value reset
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
This project implements the above feedback loop in FPGA logic. The components of the feedback loop are analysed below:
|
This project implements the above feedback loop in FPGA logic. The components of the feedback loop are detailed below:
|
||||||
* **ADC** The ADC (PMOD-AD1) is capable of operating at a maximum frequency of 20 MHz, and converting an analog signal every 18 clock cycles (ca 1.1 MHz Sampling Frequency). All PMOD Connectors on the Zedboard are fixed to 3.3V, hence the ADC can convert analog signals in the range 0V-3.3V to 12-bits.
|
* **ADC** The ADC (PMOD-AD1) is capable of operating at a maximum frequency of 20 MHz, and converting an analog signal every 18 clock cycles (ca 1.1 MHz Sampling Frequency). All PMOD Connectors on the Zedboard are fixed to 3.3V, hence the ADC can convert analog signals in the range 0V-3.3V to 12-bits.
|
||||||
* **DAC** The DAC (PMOD-DA3) is capable of operating at a maximum frequency of 50 MHz, and converting a digital signal every 16 clock cycles (ca 1.25 MHz). The DAC uses an internal 2.5 V Voltage reference (uncorrelated to the used VCC Voltage), and can thus convert 16-bits to 0V-2.5V.
|
* **DAC** The DAC (PMOD-DA3) is capable of operating at a maximum frequency of 50 MHz, and converting a digital signal every 16 clock cycles (ca 1.25 MHz). The DAC uses an internal 2.5 V Voltage reference (uncorrelated to the used VCC Voltage), and can thus convert 16-bits to 0V-2.5V.
|
||||||
* **DELAY LINE** The delay line allows to delay the converted ADC values by a pre-specified amount of clock cycles.
|
* **DELAY LINE** The delay line allows to delay the converted ADC values by a pre-specified amount of clock cycles.
|
||||||
* **SCALER** The scaler allows the converted ADC values to be downscaled. It uses a 5-bit multiplication factor that is intepreted as a 1Q4 (1-Bit Integer, 4-Bit Fractional) fixed point number. Note that the factor should only take values between 0 and 16 (decimal), as due to the internal connection (truncat highest bit) using higher numbers can (and will) result to overflow conditions.
|
* **SCALER** The scaler allows the converted ADC values to be scaled. It uses a 5-bit multiplication factor that is intepreted as a Q1.4 (1-Bit Integer, 4-Bit Fractional) fixed point number. The signals are scaled with respect to the configured *Bias Offset*. Note that when scaling up the signal may be capped due to overflow conditions in the internal representation. See *Overflow Considerations*
|
||||||
e.g. A value of 16(decimal) is intepreted as scaling by 1, a value of 15 (decimal) is intepreted as scaling by 0.9375, and a value of 8 is is intepreted as scaling by 0.5.
|
e.g. A value of 16(decimal) is intepreted as scaling by 1, a value of 15(decimal) is intepreted as scaling by 0.9375, and a value of 24(decimal) is is intepreted as scaling by 1.5.
|
||||||
* **ADD/SUB** The ADD/SUB allows to either add or subtract the scaler output from the MUX output. (Allowing to either implement a positive, or negative feedback loop).
|
* **ADD/SUB** The ADD/SUB allows to either add or subtract the input signals (Sig0 +/- Sig1).
|
||||||
* **MUX** The MUX selects between the second ADC channel or zero (GND), allowing a "neutral" feedback.
|
* **INV** The INV inverts the input signal 0. The negated signal 0 is used if the loop is in *Single Input Mode* configured as *Negative Feedback*.
|
||||||
|
* **MUX** The MUX selects between the signals, allowing either input signal 0 passthrough, or feedback result to be outputted.
|
||||||
|
|
||||||
## Timing Considerations
|
## Timing Considerations
|
||||||
|
|
||||||
The whole system is clocked at 20 MHz (highest supported frequency of ADC).
|
The whole system is clocked at 20 MHz (highest supported frequency of ADC).
|
||||||
The *ADD/SUB* and *Scaler* have a 1-stage pipeline, meaning that if the *Delay Line* is configured with 0 delay, the feedback loop follows the 18 clock cycle cadence of the ADC without additional delay.
|
The logic between the ADC and DAC is implemented in a 2-stage pipeline format, so that the whole feedback loop follows the 18 clock cycle cadence of the ADC.
|
||||||
In order to re-align the inputs of the *ADD/SUB*, the second channel of the ADC is latched (delayed) for one clock cycle (not shown in diagram) to compensate for the Scaler pipeline.
|
|
||||||
|
## Bias Offset
|
||||||
|
|
||||||
|
Because both the used ADC and DAC are unipolar, signals have to be biased accordingly on input and output. In order to have correct processing of biased signals, the bias offset has to be configured in the *typedef_package*.
|
||||||
|
The default configured bias is 2048 (1.65V), and is in the middle of the ADC input range.
|
||||||
|
|
||||||
|
## Input/Output Voltage Range
|
||||||
|
|
||||||
|
Because the input range is 0-3.3V but the output range is 0-2.5V, the output signal amplitude is approx. 75% of the input signal amplitude when using a scaling of 1 (16 in config). In order to compensate for that you have to scale by a factor of 1.32 (21 in config). Note that when using the factor 1.32 to compensate this reduces the effective input range to 0.4-2.9V (with default bias).
|
||||||
|
|
||||||
|
## Overflow Considerations
|
||||||
|
|
||||||
|
Due to the internal representation signals may be capped to their maximum value in-between arithmetic operations, leading to unwanted signal distortion in the output. The user has to take into account that no signal is exceeding the output voltage range.
|
||||||
|
e.g. The below simulation shows a negative feedback loop, where Input 2 is scaled by 1 and subtracted by Input 1 scaled by 1.32. Because the scaling of Input 1 is capped before the subtraction of Input 2 we get an unwanted distortion.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
# USAGE
|
# USAGE
|
||||||
|
|
||||||
@ -74,27 +91,30 @@ In order to re-align the inputs of the *ADD/SUB*, the second channel of the ADC
|
|||||||
|
|
||||||
## Boot
|
## Boot
|
||||||
The UART should automatically connect to a root shell (after U-Boot did it's thing). The root user has no password set.
|
The UART should automatically connect to a root shell (after U-Boot did it's thing). The root user has no password set.
|
||||||
The system should be halted (using the `halt` or `shutdown now` command) before powering off the board.
|
The system should be halted (using the `halt` or `shutdown now` command) before powering off the board, to prevent SD Card corruption.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
The FPGA logic contains a configuration memory with a pre-defined (changable in `typedef_package.vhd`) number of configuration "slots". Each slot contains the configuration for the feedback loop (Delay Line clock count, scaler factor, add/sub selection, MUX selection), and a timestamp. The timestamp defines the number of clock cycles from the rising edge of the SYNC pulse signal after which the configuration described by the slot is applied. It makes sense for the first configuration slot to have a timestamp of 0. The slots are processed in write order, and not in timestamp order. (Thus slots should have increasing timestamp values).
|
The FPGA logic contains a configuration memory with a pre-defined (changable in `typedef_package.vhd`) number of configuration "slots". Each slot contains the configuration for the feedback loop (Delay Line clock count, scaler factor, add/sub selection, MUX selection), and a timestamp. The timestamp defines the number of clock cycles from the rising edge of the SYNC pulse signal after which the configuration described by the slot is applied. It makes sense for the first configuration slot to have a timestamp of 0. The slots are processed in write order, and not in timestamp order. (Thus slots should have increasing timestamp values).
|
||||||
NOTE: It is valid for a configuration slot to have a timestamp lower than the previous. The slot will be applied for at least 1 clock cycle before the next slot can be applied.
|
NOTE: It is valid for a configuration slot to have a timestamp lower than the previous. The slot will be applied for at least 1 clock cycle before the next slot can be applied.
|
||||||
|
|
||||||
The `xillybus_config` linux device file is used to write to the configuration memory of the FPGA. Note that the standby switch has to be enabled (Standby status led on). As long as the standby switch is enabled, the feedback loop is held in reset.
|
The `xillybus_config` linux device file is used to write to the configuration memory of the FPGA. Note that the standby switch has to be enabled (Standby status led on) in order to write the configuration to the FPGA. As long as the standby switch is enabled, the feedback loop is held in reset.
|
||||||
|
|
||||||
The `write_config.c` C program can be used to write the configuration memory of the FPGA.
|
The `write_config.c` C program can be used to write the configuration onto the FPGA.
|
||||||
e.g. `./write_config config /dev/xillybus_config`
|
e.g. `./write_config config /dev/xillybus_config`
|
||||||
|
|
||||||
### Config File
|
### Config File
|
||||||
Each line of this file defines a configuration slot and consists of integer numbers delimited by white spaces in the following order:
|
Each line of this file defines a configuration slot and consists of integer numbers delimited by white spaces in the following order:
|
||||||
ADDSUB_MODE ADD_INPUT_MUX DELAY FACTOR TIMESTAMP
|
ADDSUB_MODE ADD_INPUT_MUX DELAY FACTOR0 FACTOR1 TIMESTAMP
|
||||||
|
|
||||||
* ADDSUB_MODE: Select feedback mode (0=negative, 1=positive)
|
* ADDSUB_MODE: Select feedback mode (0=Negative, 1=Positive)
|
||||||
* ADD_INPUT_MUX: Select feedback input (0=GND[only ADC Input 1], 1=ADC Input 2[Both ADC inputs are used])
|
* ADD_INPUT_MUX: Select feedback input (0=Single Input Mode [ADC0], 1=Double Input Mode)
|
||||||
* DELAY: Clock cycle counts (50 ns period) to delay the feedback signal [0-255]
|
* DELAY: Clock cycles counts (50 ns period) to delay the feedback signal [0-65535]
|
||||||
* FACTOR: Multiplication factor to apply to the feedback signal [0-16] (NOTE: Integer is intepreted as a 1Q4 Fixed Point Number!)
|
* FACTOR0: Multiplication factor to apply to the ADC Signal0 [0-32] (NOTE: Integer is intepreted as a Q1.4 Fixed Point Number!)
|
||||||
|
* FACTOR1: Multiplication factor to apply to the ADC Signal1 [0-32] (NOTE: Integer is intepreted as a Q1.4 Fixed Point Number!)
|
||||||
* TIMESTAMP: Defines the clock count number from the sync pulse from which on the configurations settings will be applied. [32-bit unsigned integer]
|
* TIMESTAMP: Defines the clock count number from the sync pulse from which on the configurations settings will be applied. [32-bit unsigned integer]
|
||||||
|
|
||||||
|
NOTE: In *Single Input Mode* the feedback mode (Positive/Negative) selects if the input signal 0 is passed through as is, or negated.
|
||||||
|
|
||||||
## Debug
|
## Debug
|
||||||
The FPGA logic allows debug values to be sent to the Linux via the `xillybus_debug` device file.
|
The FPGA logic allows debug values to be sent to the Linux via the `xillybus_debug` device file.
|
||||||
|
|
||||||
|
|||||||
1
feedback.drawio
Normal file
1
feedback.drawio
Normal file
@ -0,0 +1 @@
|
|||||||
|
<mxfile host="embed.diagrams.net" modified="2021-03-28T11:07:23.450Z" agent="5.0 (Windows)" etag="lbqn4-AlfalGzMKEjJrE" version="14.5.3" type="embed"><diagram id="XXEXLVUDAfSVulWw4Scs" name="Page-1">7Vpdc5s4FP01fqxHfAjwo2M72c6mnU493aaPKiigXYy8Qo7t/fUrjDAgERvbEMfT5iXoSAJx7zm6lysPrMli88DQMvpEAxwPTBBsBtZ0YJomMD3xL0O2OQJHMAdCRoIcMkpgTv7DEgQSXZEAp7WBnNKYk2Ud9GmSYJ/XMMQYXdeHPdO4/tQlCrEGzH0U6+h3EvAoRz0ISvwPTMKoeLIBZM8CFYMlkEYooOsKZM0G1oRRyvOrxWaC48x4hV3yefev9O4XxnDCW02w5Tr4tng5HIh3lU3KeERDmqB4VqJ3jK6SAGd3AKJVjnmkdClAQ4B/Y8630nFoxamAIr6IZS/eEP5Uuf6R3WoIZWu6kXfeNbZFI+Fs+1RtVGZlzXLarlXM0y0ijZTSFfPlO5uSRIiFWI4yrRzLzFGZJ834gOkCi8eIAQzHiJOXOjWQZFi4H7ef+oUSsRITFGpwJRWkFgwL1m+RL0rOKl0pLirLKKGdg5udLd/yBcUrudrxdAI0AtTdu44Ix/Ml2plqLfRcd+UzieMJjSnbzbWePR/7vsBTzug/uNLz04M2POiQF8w43hy0tez1FJMValqXYrQlFFV0WGBNzqmZ9YANR7/1Mthro6oX2LVc2nrEamK1obnp5li9p+sbsNrU7fXuaT30XHgatXetL5gRYR/MJBigNNq9hNGW/HZDsAC9BIsxY2hbGbDMgkD6eixxDYVCQIn+R8ZbLlBYk6/g3IBja9Kcjic3qEzHVgKO93bSNPQA/e6l2UPEgbronGtFHKjTevY4/iGgx4+fZ5fxuwO2Gs7xQOL1xdYbDCQ9sNXR2epei62Oxtb5ZPw4+3p1nrZJeHrjqXlzPP0AhkAsu0bWSgp0Ss7TisOuzmGvlyxHS0sg9OrEKNrdfxK7mjgGphPzLC8kL+IyzC7HU9FxP/92V/SJVqX76kKywfWE5LUx4KdvT+/UdNA5r5Swj7EXbUK/iwl5Nt24rShfWL3sNGohqb/am6EL5Z7hf1c48beFNn6yQhcPOMEMcfEtoxJE8JrX/Vn/8klogpXPJAmhmISJaPrCF1kkuMtUQnwUj2XHggTBjmJNsqvTrgPlfTBV5UFNeU6D8qwuyh1Xjf5gaDh17R0Rn2ioEfxcQZ5e7SjcVBVj56Xx1o4Duopms+ndePKn7tE4Jss081waoWUG+jFdBW+T2iphxbL0sLIPNVV2e12wW6+IdpfxazZosFTrjL8p2vaVqDQUoxoylY+f/2qZqXBGUBK+ul9WDKdtvKkYSpLwq3xBE3RjXVup5hlGux0VdmFd+GukMlqOcmz3bDgpyZnY/VcTUJMZe6h+OOVL0/IZ7V4alXo8lHRujznD+sHDmzHH7YU4lnoCrW4IrVmjpnTqjV5hzanHHJYaRuzDxxzq+GPHIrZ9cPzFxyJF1eGWKH+tzdJ755SHClVug/KXU9i7OQpn9VNo13lc1lNPL5+ezO6Gc+N+2G2rZIHueeyGsJl1XbMbquerdsds/UUKbadS0tMZ2U9u6qj55Gg0hO6o/DszT3Ws5m3u8jxVNMtfYebDy9+yWrP/AQ==</diagram></mxfile>
|
||||||
BIN
feedback.png
BIN
feedback.png
Binary file not shown.
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 14 KiB |
@ -1 +0,0 @@
|
|||||||
<mxfile host="www.draw.io" modified="2020-04-29T16:58:52.772Z" agent="5.0 (Windows)" version="13.0.3" etag="cTyPEfKk6Dbk87byXYzn"><diagram id="XXEXLVUDAfSVulWw4Scs" name="Page-1">7ZnbcpswEIafxpfNADKYXBLbSTvjdDL1dJpcKqCAWhlRIR/o01eAsACRxHVsXGdyZfbXAaT9VivJAzBebG4YTKJbGiAysIxgMwCTgWVZhuWKn1zJSsW+tEshZDgoJVMJc/wHSdGQ6hIHKG1U5JQSjpOm6NM4Rj5vaJAxum5We6Kk+dYEhkgT5j4kuvoDBzwqVdc2lP4Z4TCq3mwasmQBq8pSSCMY0HVNAtMBGDNKefm02IwRySevmpey3fUzpdsPYyjmOzUYyu/gWTU4FIixSpMyHtGQxpBMlXrF6DIOUN6DISxVZ0ZpIkRTiD8R55l0HFxyKqSIL4gsRRvM72vPD3lXF7a0JhvZc2FklRFzlt3XjbLVyK5s1a6wqoblAPNRPTtHUkrpkvmyliWxgixEspa79Y8AG9EFEm8RVRgikONVs3coCQu39ZQTxIP0Q7dP5KtXkCxlp95krLmp6YR1hDmaJ7D4/LWIuuaEP2FCxpRQVrQFT66PfF/oKWf0F6qVPLr20FaztkKMo83L86bPiGzgSsZlkJuOtNcqZIZSimrRUmlvmcLLc6f6OFADHWq7J6jB+4R6S2sPUG89ekZUX7hqfd6N7MK6QwyL+UFMigFMo2IQ5t7sD3X2axl3P/iLph5jMKtVSCiOeVrr+S4XFEF2GyGnlaJfqQ9GRoua8gsUQ9uh7ITVUIvMiXeOkWlbpwvNamN6TqHZR8Kx9aBzeko4to71dOY9CGn25ev0bXwfgNbtbugFWt1j0XqGiaQPWh2d1lFPtDoarfOxN5t+Ozmnu2x4jsap9cFpF6cjndNhT5yONE4HlkN4vkXDK/EY5o/eRBRcz79fVWXCqhWfnOmhcUKmwSmZVhw/1Epe3cQ3t/BHYdo93drr7sL07ff7/5Xm1r7XtHbb97qHoHl07iu0dZwl2uzY+fZ1f2jqW1/9eCJ4481ZbR7OYhqj1klOSpDgMBamL8afH9CvcnqxD4knCxY4CApHd7HfdP4B8AeghT/Q8bc68LcOgf/HPWM3/W9FvfsmpH2h3F7BymCTjVpe/Lc7EVPPCdcM/V6i2M+qNPDIqhRwg2LEIBdB8m6j7FM7yTi2FmVOR5SBA0SZddJjgHFhOs1AeyXShNG+vtw3+g5w7Vn5rZ6IQE+JqHp3Y2fV9iQhOElzj6URTHLRJ3QZ9HO2bd3BgI7UYXbljj22TsJU/+qWK5L6bxxM/wI=</diagram></mxfile>
|
|
||||||
55
modelsim/feedback.do
Normal file
55
modelsim/feedback.do
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
onerror {resume}
|
||||||
|
quietly WaveActivateNextPane {} 0
|
||||||
|
add wave -noupdate -divider SYSTEM
|
||||||
|
add wave -noupdate /feedback_loop_tb/clk
|
||||||
|
add wave -noupdate /feedback_loop_tb/reset
|
||||||
|
add wave -noupdate -divider ADC
|
||||||
|
add wave -noupdate /feedback_loop_tb/adc_data_in1
|
||||||
|
add wave -noupdate /feedback_loop_tb/adc_data_in2
|
||||||
|
add wave -noupdate /feedback_loop_tb/adc_cs_n
|
||||||
|
add wave -noupdate -divider CONFIG
|
||||||
|
add wave -noupdate /feedback_loop_tb/addsub_mode
|
||||||
|
add wave -noupdate /feedback_loop_tb/add_input_mux
|
||||||
|
add wave -noupdate -radix unsigned /feedback_loop_tb/delay
|
||||||
|
add wave -noupdate -radix binary /feedback_loop_tb/uut/factor1
|
||||||
|
add wave -noupdate -radix binary /feedback_loop_tb/uut/factor2
|
||||||
|
add wave -noupdate -divider INPUT
|
||||||
|
add wave -noupdate -radix hexadecimal /feedback_loop_tb/uut/adc_data1
|
||||||
|
add wave -noupdate -radix hexadecimal /feedback_loop_tb/uut/adc_data2
|
||||||
|
add wave -noupdate /feedback_loop_tb/uut/adc_done
|
||||||
|
add wave -noupdate -divider TESTBENCH
|
||||||
|
add wave -noupdate /feedback_loop_tb/adc_stage
|
||||||
|
add wave -noupdate /feedback_loop_tb/cnt1
|
||||||
|
add wave -noupdate /feedback_loop_tb/cnt2
|
||||||
|
add wave -noupdate -divider SIGNAL
|
||||||
|
add wave -noupdate -expand -group ANALOG -format Analog-Step -height 200 -max 4096.0 -radix unsigned /feedback_loop_tb/input1
|
||||||
|
add wave -noupdate -expand -group ANALOG -format Analog-Step -height 200 -max 4094.9999999999995 -radix unsigned /feedback_loop_tb/input2
|
||||||
|
add wave -noupdate -expand -group ANALOG -format Analog-Step -height 200 -max 65536.0 -radix unsigned /feedback_loop_tb/output
|
||||||
|
add wave -noupdate -divider MISC
|
||||||
|
add wave -noupdate -radix hexadecimal /feedback_loop_tb/uut/data1_B
|
||||||
|
add wave -noupdate -radix hexadecimal /feedback_loop_tb/uut/data2_B
|
||||||
|
add wave -noupdate -radix hexadecimal /feedback_loop_tb/uut/scaler_offset_1
|
||||||
|
add wave -noupdate -radix hexadecimal /feedback_loop_tb/uut/scaler_offset_2
|
||||||
|
add wave -noupdate -radix hexadecimal /feedback_loop_tb/uut/data1_C
|
||||||
|
add wave -noupdate -radix hexadecimal /feedback_loop_tb/uut/data2_C
|
||||||
|
add wave -noupdate /feedback_loop_tb/uut/done_II
|
||||||
|
add wave -noupdate -radix hexadecimal /feedback_loop_tb/uut/data_out
|
||||||
|
add wave -noupdate /feedback_loop_tb/uut/done_IV
|
||||||
|
TreeUpdate [SetDefaultTree]
|
||||||
|
WaveRestoreCursors {{Cursor 4} {101850000000 fs} 0}
|
||||||
|
quietly wave cursor active 1
|
||||||
|
configure wave -namecolwidth 150
|
||||||
|
configure wave -valuecolwidth 100
|
||||||
|
configure wave -justifyvalue left
|
||||||
|
configure wave -signalnamewidth 1
|
||||||
|
configure wave -snapdistance 10
|
||||||
|
configure wave -datasetprefix 0
|
||||||
|
configure wave -rowmargin 4
|
||||||
|
configure wave -childrowmargin 2
|
||||||
|
configure wave -gridoffset 0
|
||||||
|
configure wave -gridperiod 1
|
||||||
|
configure wave -griddelta 40
|
||||||
|
configure wave -timeline 0
|
||||||
|
configure wave -timelineunits ns
|
||||||
|
update
|
||||||
|
WaveRestoreZoom {0 fs} {535391147585 fs}
|
||||||
BIN
overflow_issue.png
Normal file
BIN
overflow_issue.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 62 KiB |
@ -1,76 +0,0 @@
|
|||||||
library ieee;
|
|
||||||
use ieee.std_logic_1164.all;
|
|
||||||
use ieee.numeric_std.all;
|
|
||||||
|
|
||||||
Library UNISIM;
|
|
||||||
use UNISIM.vcomponents.all;
|
|
||||||
|
|
||||||
Library UNIMACRO;
|
|
||||||
use UNIMACRO.vcomponents.all;
|
|
||||||
|
|
||||||
-- Add/Sub
|
|
||||||
-- This entity adds or subtracts inputs 'A' and 'B', depending on 'mode' (1 = add, 0 = sub).
|
|
||||||
-- If 'cap' is high, on Overfolw/Underflow conditions the result is capped at max/min value.
|
|
||||||
|
|
||||||
entity addsub is
|
|
||||||
generic (
|
|
||||||
PIPELINE_STAGES : integer := 1;
|
|
||||||
DATA_WIDTH : integer := 16
|
|
||||||
);
|
|
||||||
port (
|
|
||||||
clk : in std_logic;
|
|
||||||
reset : in std_logic;
|
|
||||||
mode : in std_logic;
|
|
||||||
cap : in std_logic;
|
|
||||||
A : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
|
||||||
B : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
|
||||||
RES : out std_logic_vector(DATA_WIDTH-1 downto 0)
|
|
||||||
);
|
|
||||||
end entity;
|
|
||||||
|
|
||||||
architecture arch of addsub is
|
|
||||||
|
|
||||||
--*****SIGNAl DECLARATION
|
|
||||||
signal result : std_logic_vector(DATA_WIDTH-1 downto 0) := (others => '0');
|
|
||||||
signal carry : std_logic := '0';
|
|
||||||
|
|
||||||
begin
|
|
||||||
|
|
||||||
ADDSUB_MACRO_inst : ADDSUB_MACRO
|
|
||||||
generic map (
|
|
||||||
DEVICE => "7SERIES", -- Target Device: "VIRTEX5", "7SERIES", "SPARTAN6"
|
|
||||||
LATENCY => PIPELINE_STAGES, -- Desired clock cycle latency, 0-2
|
|
||||||
WIDTH => DATA_WIDTH -- Input / Output bus width, 1-48
|
|
||||||
)
|
|
||||||
port map (
|
|
||||||
CARRYOUT => open, -- 1-bit carry-out output signal
|
|
||||||
RESULT => result, -- Add/sub result output, width defined by WIDTH generic
|
|
||||||
A => A, -- Input A bus, width defined by WIDTH generic
|
|
||||||
ADD_SUB => mode, -- 1-bit add/sub input, high selects add, low selects subtract
|
|
||||||
B => B, -- Input B bus, width defined by WIDTH generic
|
|
||||||
CARRYIN => '0', -- 1-bit carry-in input
|
|
||||||
CE => '1', -- 1-bit clock enable input
|
|
||||||
CLK => clk, -- 1-bit clock input
|
|
||||||
RST => reset -- 1-bit active high synchronous reset
|
|
||||||
);
|
|
||||||
|
|
||||||
clamp : process(all)
|
|
||||||
begin
|
|
||||||
--DEFAULT VALUE
|
|
||||||
RES <= result;
|
|
||||||
|
|
||||||
--Overflow/Underflow
|
|
||||||
if(carry = '1' and cap = '1') then
|
|
||||||
--ADD
|
|
||||||
if(mode = '1') then
|
|
||||||
--CAP AT MAX VALUE
|
|
||||||
RES <= (others => '1');
|
|
||||||
--SUB
|
|
||||||
else
|
|
||||||
--CAP AT ZERO
|
|
||||||
RES <= (others => '0');
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
end architecture;
|
|
||||||
@ -45,7 +45,7 @@ architecture arch of delay_line is
|
|||||||
end component;
|
end component;
|
||||||
|
|
||||||
--*****SIGNAl DECLARATION*****
|
--*****SIGNAl DECLARATION*****
|
||||||
signal cnt, cnt_next, cnt_max, cnt_max_next : integer range 0 to MAX_DELAY := 0;
|
signal cnt, cnt_next : integer range 0 to MAX_DELAY := 0;
|
||||||
signal memory_out : std_logic_vector(DATA_WIDTH-1 downto 0) := (others => '0');
|
signal memory_out : std_logic_vector(DATA_WIDTH-1 downto 0) := (others => '0');
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@ -69,15 +69,13 @@ begin
|
|||||||
begin
|
begin
|
||||||
-- DEFAULT VALUES
|
-- DEFAULT VALUES
|
||||||
cnt_next <= cnt;
|
cnt_next <= cnt;
|
||||||
cnt_max_next <= cnt_max;
|
|
||||||
|
|
||||||
if(to_integer(unsigned(delay)) = 0) then
|
if(to_integer(unsigned(delay)) = 0) then
|
||||||
data_out <= data_in;
|
data_out <= data_in;
|
||||||
else
|
else
|
||||||
data_out <= memory_out;
|
data_out <= memory_out;
|
||||||
-- COUNT GENERATION
|
-- COUNT GENERATION
|
||||||
cnt_max_next <= to_integer(unsigned(delay)) - 1;
|
if (cnt >= (to_integer(unsigned(delay)) - 1)) then
|
||||||
if (cnt >= cnt_max) then
|
|
||||||
cnt_next <= 0;
|
cnt_next <= 0;
|
||||||
else
|
else
|
||||||
cnt_next <= cnt + 1;
|
cnt_next <= cnt + 1;
|
||||||
@ -90,10 +88,8 @@ begin
|
|||||||
if rising_edge(clk) then
|
if rising_edge(clk) then
|
||||||
if (reset = '1') then
|
if (reset = '1') then
|
||||||
cnt <= 0;
|
cnt <= 0;
|
||||||
cnt_max <= 0;
|
|
||||||
else
|
else
|
||||||
cnt <= cnt_next;
|
cnt <= cnt_next;
|
||||||
cnt_max <= cnt_max_next;
|
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|||||||
@ -14,8 +14,9 @@ use work.typedef_package.all;
|
|||||||
-- mem_data(63) : Slot Enable
|
-- mem_data(63) : Slot Enable
|
||||||
-- mem_data(62) : Addsub_mode
|
-- mem_data(62) : Addsub_mode
|
||||||
-- mem_data(61) : Add_input_mux
|
-- mem_data(61) : Add_input_mux
|
||||||
-- mem_data(47-40) : delay
|
-- mem_data(57-42) : delay
|
||||||
-- mem_data(36-32) : factor
|
-- mem_data(41-37) : factor1
|
||||||
|
-- mem_data(36-32) : factor2
|
||||||
-- mem_data(31-0) : timestamp
|
-- mem_data(31-0) : timestamp
|
||||||
|
|
||||||
|
|
||||||
@ -33,7 +34,8 @@ entity feedback_controller is
|
|||||||
addsub_mode : out std_logic;
|
addsub_mode : out std_logic;
|
||||||
add_input_mux : out std_logic;
|
add_input_mux : out std_logic;
|
||||||
delay : out std_logic_vector(DELAY_WIDTH-1 downto 0);
|
delay : out std_logic_vector(DELAY_WIDTH-1 downto 0);
|
||||||
factor : out std_logic_vector(FACTOR_WIDTH-1 downto 0)
|
factor1 : out std_logic_vector(FACTOR_WIDTH-1 downto 0);
|
||||||
|
factor2 : out std_logic_vector(FACTOR_WIDTH-1 downto 0)
|
||||||
);
|
);
|
||||||
end entity;
|
end entity;
|
||||||
|
|
||||||
@ -47,7 +49,7 @@ architecture arch of feedback_controller is
|
|||||||
signal sync_pulse_arrived : std_logic;
|
signal sync_pulse_arrived : std_logic;
|
||||||
signal addsub_mode_next, addsub_mode_sig, add_input_mux_next, add_input_mux_sig : std_logic := '0';
|
signal addsub_mode_next, addsub_mode_sig, add_input_mux_next, add_input_mux_sig : std_logic := '0';
|
||||||
signal delay_next, delay_sig : std_logic_vector(DELAY_WIDTH-1 downto 0) := (others => '0');
|
signal delay_next, delay_sig : std_logic_vector(DELAY_WIDTH-1 downto 0) := (others => '0');
|
||||||
signal factor_next, factor_sig : std_logic_vector(FACTOR_WIDTH-1 downto 0) := (others => '0');
|
signal factor1_next, factor1_sig, factor2_next, factor2_sig : std_logic_vector(FACTOR_WIDTH-1 downto 0) := (others => '0');
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|
||||||
@ -58,7 +60,8 @@ begin
|
|||||||
addsub_mode <= addsub_mode_sig;
|
addsub_mode <= addsub_mode_sig;
|
||||||
add_input_mux <= add_input_mux_sig;
|
add_input_mux <= add_input_mux_sig;
|
||||||
delay <= delay_sig;
|
delay <= delay_sig;
|
||||||
factor <= factor_sig;
|
factor1 <= factor1_sig;
|
||||||
|
factor2 <= factor2_sig;
|
||||||
|
|
||||||
ctrl : process(all)
|
ctrl : process(all)
|
||||||
begin
|
begin
|
||||||
@ -67,7 +70,8 @@ begin
|
|||||||
addsub_mode_next <= addsub_mode_sig;
|
addsub_mode_next <= addsub_mode_sig;
|
||||||
add_input_mux_next <= add_input_mux_sig;
|
add_input_mux_next <= add_input_mux_sig;
|
||||||
delay_next <= delay_sig;
|
delay_next <= delay_sig;
|
||||||
factor_next <= factor_sig;
|
factor1_next <= factor1_sig;
|
||||||
|
factor2_next <= factor2_sig;
|
||||||
|
|
||||||
if(mem_data(CONFIG_DATA_WIDTH-1) = '1') then
|
if(mem_data(CONFIG_DATA_WIDTH-1) = '1') then
|
||||||
-- If timestamp is reached (or exceeded), apply configuration and fetch next configuration
|
-- If timestamp is reached (or exceeded), apply configuration and fetch next configuration
|
||||||
@ -75,8 +79,9 @@ begin
|
|||||||
if (unsigned(timer) >= unsigned(mem_data(TIMESTAMP_WIDTH-1 downto 0))) then
|
if (unsigned(timer) >= unsigned(mem_data(TIMESTAMP_WIDTH-1 downto 0))) then
|
||||||
addsub_mode_next <= mem_data(CONFIG_DATA_WIDTH-2);
|
addsub_mode_next <= mem_data(CONFIG_DATA_WIDTH-2);
|
||||||
add_input_mux_next <= mem_data(CONFIG_DATA_WIDTH-3);
|
add_input_mux_next <= mem_data(CONFIG_DATA_WIDTH-3);
|
||||||
delay_next <= mem_data(CONFIG_DATA_WIDTH-17 downto CONFIG_DATA_WIDTH-16-DELAY_WIDTH);
|
factor2_next <= mem_data(TIMESTAMP_WIDTH+FACTOR_WIDTH-1 downto TIMESTAMP_WIDTH);
|
||||||
factor_next <= mem_data(TIMESTAMP_WIDTH+FACTOR_WIDTH-1 downto TIMESTAMP_WIDTH);
|
factor1_next <= mem_data(TIMESTAMP_WIDTH+FACTOR_WIDTH+FACTOR_WIDTH-1 downto TIMESTAMP_WIDTH+FACTOR_WIDTH);
|
||||||
|
delay_next <= mem_data(TIMESTAMP_WIDTH+FACTOR_WIDTH+FACTOR_WIDTH+DELAY_WIDTH-1 downto TIMESTAMP_WIDTH+FACTOR_WIDTH+FACTOR_WIDTH);
|
||||||
|
|
||||||
slot_nr_next <= std_logic_vector(unsigned(slot_nr) + inc);
|
slot_nr_next <= std_logic_vector(unsigned(slot_nr) + inc);
|
||||||
end if;
|
end if;
|
||||||
@ -91,13 +96,15 @@ begin
|
|||||||
addsub_mode_sig <= '0';
|
addsub_mode_sig <= '0';
|
||||||
add_input_mux_sig <= '0';
|
add_input_mux_sig <= '0';
|
||||||
delay_sig <= (others => '0');
|
delay_sig <= (others => '0');
|
||||||
factor_sig <= (others => '0');
|
factor1_sig <= (others => '0');
|
||||||
|
factor2_sig <= (others => '0');
|
||||||
else
|
else
|
||||||
slot_nr <= slot_nr_next;
|
slot_nr <= slot_nr_next;
|
||||||
addsub_mode_sig <= addsub_mode_next;
|
addsub_mode_sig <= addsub_mode_next;
|
||||||
add_input_mux_sig <= add_input_mux_next;
|
add_input_mux_sig <= add_input_mux_next;
|
||||||
delay_sig <= delay_next;
|
delay_sig <= delay_next;
|
||||||
factor_sig <= factor_next;
|
factor1_sig <= factor1_next;
|
||||||
|
factor2_sig <= factor2_next;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|||||||
@ -5,15 +5,16 @@ use ieee.numeric_std.all;
|
|||||||
use work.typedef_package.all;
|
use work.typedef_package.all;
|
||||||
|
|
||||||
-- Architecture
|
-- Architecture
|
||||||
-- --- ---------- ------ ------- ---
|
-- ---- ---------- ------ ------- ---
|
||||||
--->|ADC|--->|Delay Line|--->|Scaler|--->|ADD/SUB|--->|DAC|--->
|
--->|ADC2|--->|Delay Line|--->|Scaler|--->|ADD/SUB|--->| |
|
||||||
-- --- ---------- ------ ------- ---
|
-- ---- ---------- ------ ------- | |
|
||||||
-- ^
|
-- ^ | | ---
|
||||||
-- --- ----- --- |
|
-- | |MUX|-->|DAC|-->
|
||||||
--->|ADC|-------------------->|Latch|->| | |
|
-- +------+------->| | ---
|
||||||
-- --- ----- |MUX|--
|
-- ---- ------ | --- | |
|
||||||
-- GND--->| |
|
--->|ADC1|------------------->|Scaler|-+->|INV|------->| |
|
||||||
-- ---
|
-- ---- ------ --- ---
|
||||||
|
|
||||||
|
|
||||||
-- Feedback Loop
|
-- Feedback Loop
|
||||||
-- This entity implements the feedback loop as defined above.
|
-- This entity implements the feedback loop as defined above.
|
||||||
@ -34,9 +35,10 @@ entity feedback_loop is
|
|||||||
dac_sclk : out std_logic; -- PMOD-DA3
|
dac_sclk : out std_logic; -- PMOD-DA3
|
||||||
-- DYNAMIC CONFIGURATION
|
-- DYNAMIC CONFIGURATION
|
||||||
addsub_mode : in std_logic; -- (1=ADD, 0=SUB)
|
addsub_mode : in std_logic; -- (1=ADD, 0=SUB)
|
||||||
add_input_mux : in std_logic; -- (1=ADC Input 2, 0=GND)
|
add_input_mux : in std_logic; -- (1=Double Input 2, 0=Single Input)
|
||||||
delay : in std_logic_vector(DELAY_WIDTH-1 downto 0); -- unsigned delay clock count
|
delay : in std_logic_vector(DELAY_WIDTH-1 downto 0); -- Unsigned delay clock count
|
||||||
factor : in std_logic_vector(FACTOR_WIDTH-1 downto 0); -- 1Q3 Fixed Point
|
factor1 : in std_logic_vector(FACTOR_WIDTH-1 downto 0); -- Q1.x Fixed Point
|
||||||
|
factor2 : in std_logic_vector(FACTOR_WIDTH-1 downto 0); -- Q1.x Fixed Point
|
||||||
-- DEBUG
|
-- DEBUG
|
||||||
reset_debug : in std_logic;
|
reset_debug : in std_logic;
|
||||||
adc_data1_max : out std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
|
adc_data1_max : out std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
|
||||||
@ -48,10 +50,6 @@ end entity;
|
|||||||
|
|
||||||
architecture arch of feedback_loop is
|
architecture arch of feedback_loop is
|
||||||
|
|
||||||
--*****SIGNAL DECLARATION*****
|
|
||||||
signal adc_data1, adc_data2 : std_logic_vector(ADC_DATA_WIDTH-1 downto 0) := (others => '0');
|
|
||||||
signal adc_done : std_logic := '0';
|
|
||||||
|
|
||||||
--*****COMPONENT DECLARATION*****
|
--*****COMPONENT DECLARATION*****
|
||||||
component pmod_ad1_ctrl is
|
component pmod_ad1_ctrl is
|
||||||
generic(
|
generic(
|
||||||
@ -105,22 +103,6 @@ architecture arch of feedback_loop is
|
|||||||
);
|
);
|
||||||
end component;
|
end component;
|
||||||
|
|
||||||
component addsub is
|
|
||||||
generic (
|
|
||||||
PIPELINE_STAGES : integer := 1;
|
|
||||||
DATA_WIDTH : integer := 16
|
|
||||||
);
|
|
||||||
port (
|
|
||||||
clk : in std_logic;
|
|
||||||
reset : in std_logic;
|
|
||||||
mode : in std_logic;
|
|
||||||
cap : in std_logic;
|
|
||||||
A : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
|
||||||
B : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
|
||||||
RES : out std_logic_vector(DATA_WIDTH-1 downto 0)
|
|
||||||
);
|
|
||||||
end component;
|
|
||||||
|
|
||||||
component delay_line is
|
component delay_line is
|
||||||
generic (
|
generic (
|
||||||
DATA_WIDTH : integer := 12;
|
DATA_WIDTH : integer := 12;
|
||||||
@ -137,17 +119,20 @@ architecture arch of feedback_loop is
|
|||||||
end component;
|
end component;
|
||||||
|
|
||||||
--*****CONSTANT DECLARATION*****
|
--*****CONSTANT DECLARATION*****
|
||||||
constant CONST_MAX : unsigned(DAC_DATA_WIDTH-1 downto 0) := (others => '1');
|
constant CONST_BIAS : unsigned(DAC_DATA_WIDTH-1 downto 0) := unsigned(BIAS_OFFSET & "0000");
|
||||||
constant CONST_HALF : unsigned(DAC_DATA_WIDTH-1 downto 0) := (DAC_DATA_WIDTH-1 => '1', others => '0');
|
constant FACTOR_ONE : unsigned(FACTOR_WIDTH-1 downto 0) := (FACTOR_WIDTH-1 => '1', others => '0');
|
||||||
|
|
||||||
--*****SIGNAL DECLARATION*****
|
--*****SIGNAL DECLARATION*****
|
||||||
signal delay_out : std_logic_vector(ADC_DATA_WIDTH downto 0) := (others => '0');
|
signal adc_data1, adc_data2, adc_data1_latch : std_logic_vector(ADC_DATA_WIDTH-1 downto 0) := (others => '0');
|
||||||
signal latch_out : std_logic_vector(ADC_DATA_WIDTH-1 downto 0) := (others => '0');
|
signal adc_done : std_logic := '0';
|
||||||
signal inputA_wide, inputB_wide : std_logic_vector(DAC_DATA_WIDTH downto 0) := (others => '0');
|
signal data1_A : std_logic_vector(ADC_DATA_WIDTH-1 downto 0) := (others => '0');
|
||||||
signal addsub_out, inputA, inputB : std_logic_vector(DAC_DATA_WIDTH-1 downto 0) := (others => '0');
|
signal data2_A : std_logic_vector(ADC_DATA_WIDTH downto 0) := (others => '0');
|
||||||
signal scaler_1_out, scaler_2_out, scaler_offset_1, scaler_offset_2 : std_logic_vector(DAC_DATA_WIDTH downto 0) := (others => '0');
|
signal data2_C, data1_C : std_logic_vector(DAC_DATA_WIDTH downto 0) := (others => '0');
|
||||||
signal scaler_done, addsub_done : std_logic := '0';
|
signal data_out, data2_D, data1_D : std_logic_vector(DAC_DATA_WIDTH-1 downto 0) := (others => '0');
|
||||||
signal offset_factor, tmp : std_logic_vector(FACTOR_WIDTH-1 downto 0) := (others => '0');
|
signal data1_B, data2_B, scaler_offset_1, scaler_offset_2 : std_logic_vector(DAC_DATA_WIDTH downto 0) := (others => '0');
|
||||||
|
signal done_II, done_IV : std_logic := '0';
|
||||||
|
signal offset_factor1, offset_factor2, factor1_latch, factor2_latch : std_logic_vector(FACTOR_WIDTH-1 downto 0) := (others => '0');
|
||||||
|
signal add_input_mux_latch, addsub_mode_latch : std_logic := '0';
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
|
||||||
@ -172,7 +157,29 @@ begin
|
|||||||
);
|
);
|
||||||
|
|
||||||
--*****STAGE II*****
|
--*****STAGE II*****
|
||||||
delay_line_inst : delay_line
|
|
||||||
|
-- NOTE: The Input1 Signal has to be latched if the delay line is used, so that
|
||||||
|
-- there is a valid Signal to do operations with after the delay line.
|
||||||
|
latch_1_prc : process (clk)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if (adc_done = '1') then
|
||||||
|
adc_data1_latch <= adc_data1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
data1_prc : process (all)
|
||||||
|
begin
|
||||||
|
-- If delay_line disabled or Signle Input Mode
|
||||||
|
if (delay = (delay'range => '0') or add_input_mux = '0') then
|
||||||
|
data1_A <= adc_data1;
|
||||||
|
else
|
||||||
|
data1_A <= adc_data1_latch;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
delay_line_2_inst : delay_line
|
||||||
generic map(
|
generic map(
|
||||||
DATA_WIDTH => ADC_DATA_WIDTH+1,
|
DATA_WIDTH => ADC_DATA_WIDTH+1,
|
||||||
DELAY_WIDTH => DELAY_WIDTH,
|
DELAY_WIDTH => DELAY_WIDTH,
|
||||||
@ -182,29 +189,46 @@ begin
|
|||||||
clk => clk,
|
clk => clk,
|
||||||
reset => reset,
|
reset => reset,
|
||||||
delay => delay,
|
delay => delay,
|
||||||
data_in => (adc_done & adc_data1),
|
data_in => (adc_done & adc_data2),
|
||||||
data_out => delay_out
|
data_out => data2_A
|
||||||
);
|
);
|
||||||
|
|
||||||
addsub_offset_inst : addsub
|
offset_factor_1_prc : process (all)
|
||||||
generic map(
|
variable tmp_res : unsigned(FACTOR_WIDTH-1 downto 0) := (others => '0');
|
||||||
PIPELINE_STAGES => 0,
|
begin
|
||||||
DATA_WIDTH => FACTOR_WIDTH
|
if (factor1(FACTOR_WIDTH-1) = '1') then
|
||||||
)
|
offset_factor1 <= "0" & std_logic_vector(factor1(FACTOR_WIDTH-2 downto 0));
|
||||||
port map(
|
else
|
||||||
clk => clk,
|
tmp_res := FACTOR_ONE - unsigned(factor1);
|
||||||
reset => reset,
|
offset_factor1 <= "0" & std_logic_vector(tmp_res(FACTOR_WIDTH-2 downto 0));
|
||||||
mode => '0',
|
end if;
|
||||||
cap => '0',
|
end process;
|
||||||
A => (FACTOR_WIDTH-1 => '1', others => '0'),
|
|
||||||
B => factor,
|
|
||||||
RES => tmp
|
|
||||||
);
|
|
||||||
|
|
||||||
--TODO: Fix me
|
offset_factor_2_prc : process (all)
|
||||||
offset_factor <= tmp when (factor(FACTOR_WIDTH-1) = '0') else ("0" & factor(FACTOR_WIDTH-2 downto 0));
|
variable tmp_res : unsigned(FACTOR_WIDTH-1 downto 0) := (others => '0');
|
||||||
|
begin
|
||||||
|
if (factor2(FACTOR_WIDTH-1) = '1') then
|
||||||
|
offset_factor2 <= "0" & std_logic_vector(factor2(FACTOR_WIDTH-2 downto 0));
|
||||||
|
else
|
||||||
|
tmp_res := FACTOR_ONE - unsigned(factor2);
|
||||||
|
offset_factor2 <= "0" & std_logic_vector(tmp_res(FACTOR_WIDTH-2 downto 0));
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- NOTE: We delay the config signals to synchronize them with the data flow and
|
||||||
|
-- prevent glitches in the case that the config is changed between the stages.
|
||||||
|
config_latch : process (clk)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
factor1_latch <= factor1;
|
||||||
|
factor2_latch <= factor2;
|
||||||
|
add_input_mux_latch <= add_input_mux;
|
||||||
|
addsub_mode_latch <= addsub_mode;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
--*****STAGE III*****
|
--*****STAGE III*****
|
||||||
|
|
||||||
scaler_1_inst : scaler
|
scaler_1_inst : scaler
|
||||||
generic map(
|
generic map(
|
||||||
DATA_WIDTH => ADC_DATA_WIDTH,
|
DATA_WIDTH => ADC_DATA_WIDTH,
|
||||||
@ -213,22 +237,9 @@ begin
|
|||||||
)
|
)
|
||||||
port map(
|
port map(
|
||||||
clk => clk,
|
clk => clk,
|
||||||
data_in => delay_out(ADC_DATA_WIDTH-1 downto 0),
|
data_in => data1_A,
|
||||||
factor => factor,
|
factor => factor1,
|
||||||
data_out => scaler_1_out
|
data_out => data1_B
|
||||||
);
|
|
||||||
|
|
||||||
scaler_2_inst : scaler
|
|
||||||
generic map(
|
|
||||||
DATA_WIDTH => ADC_DATA_WIDTH,
|
|
||||||
FACTOR_WIDTH => FACTOR_WIDTH,
|
|
||||||
PIPELINE_STAGES => 1
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
data_in => adc_data2,
|
|
||||||
factor => "10101", --1.32
|
|
||||||
data_out => scaler_2_out
|
|
||||||
);
|
);
|
||||||
|
|
||||||
scaler_offset_1_inst : scaler
|
scaler_offset_1_inst : scaler
|
||||||
@ -239,11 +250,46 @@ begin
|
|||||||
)
|
)
|
||||||
port map(
|
port map(
|
||||||
clk => clk,
|
clk => clk,
|
||||||
data_in => (ADC_DATA_WIDTH-1 => '0', others => '1'),
|
data_in => BIAS_OFFSET,
|
||||||
factor => offset_factor,
|
factor => offset_factor1,
|
||||||
data_out => scaler_offset_1
|
data_out => scaler_offset_1
|
||||||
);
|
);
|
||||||
|
|
||||||
|
addsub_1_prc : process (all)
|
||||||
|
begin
|
||||||
|
if (factor1_latch(FACTOR_WIDTH-1) = '1') then
|
||||||
|
data1_C <= std_logic_vector(unsigned(data1_B) - unsigned(scaler_offset_1));
|
||||||
|
else
|
||||||
|
data1_C <= std_logic_vector(unsigned(data1_B) + unsigned(scaler_offset_1));
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
cap_1_prc : process(all)
|
||||||
|
begin
|
||||||
|
if (data1_C(DAC_DATA_WIDTH) = '1') then
|
||||||
|
if (factor1_latch(FACTOR_WIDTH-1) = '1' and data1_B(DAC_DATA_WIDTH) = '0') then
|
||||||
|
data1_D <= (others => '0');
|
||||||
|
else
|
||||||
|
data1_D <= (others => '1');
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
data1_D <= data1_C(DAC_DATA_WIDTH-1 downto 0);
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
scaler_2_inst : scaler
|
||||||
|
generic map(
|
||||||
|
DATA_WIDTH => ADC_DATA_WIDTH,
|
||||||
|
FACTOR_WIDTH => FACTOR_WIDTH,
|
||||||
|
PIPELINE_STAGES => 1
|
||||||
|
)
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
data_in => data2_A(ADC_DATA_WIDTH-1 downto 0),
|
||||||
|
factor => factor2,
|
||||||
|
data_out => data2_B
|
||||||
|
);
|
||||||
|
|
||||||
scaler_offset_2_inst : scaler
|
scaler_offset_2_inst : scaler
|
||||||
generic map(
|
generic map(
|
||||||
DATA_WIDTH => ADC_DATA_WIDTH,
|
DATA_WIDTH => ADC_DATA_WIDTH,
|
||||||
@ -252,154 +298,116 @@ begin
|
|||||||
)
|
)
|
||||||
port map(
|
port map(
|
||||||
clk => clk,
|
clk => clk,
|
||||||
data_in => (ADC_DATA_WIDTH-1 => '0', others => '1'),
|
data_in => BIAS_OFFSET,
|
||||||
factor => "00101", --0.32
|
factor => offset_factor2,
|
||||||
data_out => scaler_offset_2
|
data_out => scaler_offset_2
|
||||||
);
|
);
|
||||||
|
|
||||||
process(clk)
|
addsub_2_prc : process (all)
|
||||||
begin
|
begin
|
||||||
if (rising_edge(clk)) then
|
if (factor2_latch(FACTOR_WIDTH-1) = '1') then
|
||||||
if (reset = '1') then
|
data2_C <= std_logic_vector(unsigned(data2_B) - unsigned(scaler_offset_2));
|
||||||
scaler_done <= '0';
|
else
|
||||||
else
|
data2_C <= std_logic_vector(unsigned(data2_B) + unsigned(scaler_offset_2));
|
||||||
scaler_done <= delay_out(ADC_DATA_WIDTH);
|
|
||||||
end if;
|
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
latch : process(clk)
|
cap_2_prc : process(all)
|
||||||
begin
|
begin
|
||||||
if (rising_edge(clk)) then
|
if (data2_C(DAC_DATA_WIDTH) = '1') then
|
||||||
if (reset = '1') then
|
if (factor2_latch(FACTOR_WIDTH-1) = '1' and data2_B(DAC_DATA_WIDTH) = '0') then
|
||||||
latch_out <= (others => '0');
|
data2_D <= (others => '0');
|
||||||
elsif (adc_done) then
|
|
||||||
latch_out <= adc_data2;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
addsub_1_inst : addsub
|
|
||||||
generic map(
|
|
||||||
PIPELINE_STAGES => 0,
|
|
||||||
DATA_WIDTH => DAC_DATA_WIDTH+1
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
reset => reset,
|
|
||||||
mode => not factor(FACTOR_WIDTH-1),
|
|
||||||
cap => '0',
|
|
||||||
A => scaler_1_out,
|
|
||||||
B => scaler_offset_1,
|
|
||||||
RES => inputB_wide
|
|
||||||
);
|
|
||||||
|
|
||||||
addsub_2_inst : addsub
|
|
||||||
generic map(
|
|
||||||
PIPELINE_STAGES => 0,
|
|
||||||
DATA_WIDTH => DAC_DATA_WIDTH+1
|
|
||||||
)
|
|
||||||
port map(
|
|
||||||
clk => clk,
|
|
||||||
reset => reset,
|
|
||||||
mode => '0',
|
|
||||||
cap => '0',
|
|
||||||
A => scaler_2_out,
|
|
||||||
B => scaler_offset_2,
|
|
||||||
RES => inputA_wide
|
|
||||||
);
|
|
||||||
|
|
||||||
cap_B_prc : process(all)
|
|
||||||
begin
|
|
||||||
if (inputB_wide(DAC_DATA_WIDTH) = '1') then
|
|
||||||
if (factor(FACTOR_WIDTH-1) = '1') then
|
|
||||||
inputB <= (others => '0');
|
|
||||||
else
|
else
|
||||||
inputB <= (others => '1');
|
data2_D <= (others => '1');
|
||||||
end if;
|
end if;
|
||||||
else
|
else
|
||||||
inputB <= inputB_wide(DAC_DATA_WIDTH-1 downto 0);
|
data2_D <= data2_C(DAC_DATA_WIDTH-1 downto 0);
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
done_II_prc : process(clk)
|
||||||
|
begin
|
||||||
|
if (rising_edge(clk)) then
|
||||||
|
if (reset = '1') then
|
||||||
|
done_II <= '0';
|
||||||
|
else
|
||||||
|
-- Signle Input Mode
|
||||||
|
if (add_input_mux_latch = '0') then
|
||||||
|
-- Synchronize on ADC Output
|
||||||
|
done_II <= adc_done;
|
||||||
|
else
|
||||||
|
-- Synchronize on Delay Line Output
|
||||||
|
done_II <= data2_A(ADC_DATA_WIDTH);
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
--*****STAGE IV*****
|
--*****STAGE IV*****
|
||||||
|
|
||||||
mux: process(all)
|
add_sub_prc : process (clk)
|
||||||
begin
|
variable tmp_res : unsigned(DAC_DATA_WIDTH+1 downto 0) := (others => '0');
|
||||||
if (add_input_mux = '1') then
|
|
||||||
if (inputA_wide(DAC_DATA_WIDTH) = '1') then
|
|
||||||
--TODO: CAP Needed?
|
|
||||||
inputA <= (others => '0');
|
|
||||||
else
|
|
||||||
inputA <= inputA_wide(DAC_DATA_WIDTH-1 downto 0);
|
|
||||||
end if;
|
|
||||||
else
|
|
||||||
if (addsub_mode = '1') then
|
|
||||||
inputA <= (others => '0');
|
|
||||||
else
|
|
||||||
inputA <= (others => '1');
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end process;
|
|
||||||
|
|
||||||
add_sub_prc : process (all)
|
|
||||||
variable tmp_res : unsigned(inputB'length-1 downto 0) := (others => '0');
|
|
||||||
begin
|
begin
|
||||||
if rising_edge(clk) then
|
if rising_edge(clk) then
|
||||||
if (reset = '1') then
|
if (reset = '1') then
|
||||||
addsub_out <= (others => '0');
|
data_out <= (others => '0');
|
||||||
else
|
else
|
||||||
-- Both Inputs
|
-- Double Input Mode
|
||||||
if (add_input_mux = '1') then
|
if (add_input_mux_latch = '1') then
|
||||||
-- ADD
|
-- ADD
|
||||||
if (addsub_mode = '1') then
|
if (addsub_mode_latch = '1') then
|
||||||
tmp_res := unsigned(inputB) + unsigned(inputA);
|
tmp_res := unsigned("00" & data1_D) + unsigned("00" & data2_D);
|
||||||
|
tmp_res := tmp_res + ("00" & CONST_BIAS);
|
||||||
|
-- Overflow
|
||||||
|
if (tmp_res(DAC_DATA_WIDTH+1) = '1') then
|
||||||
|
data_out <= (others => '1');
|
||||||
|
-- Underflow
|
||||||
|
elsif (tmp_res(DAC_DATA_WIDTH+1 downto DAC_DATA_WIDTH) = "00") then
|
||||||
|
data_out <= (others => '0');
|
||||||
|
else
|
||||||
|
data_out <= std_logic_vector(tmp_res(DAC_DATA_WIDTH-1 downto 0));
|
||||||
|
end if;
|
||||||
-- SUB
|
-- SUB
|
||||||
else
|
else
|
||||||
tmp_res := unsigned(inputB) - unsigned(inputA);
|
tmp_res := unsigned("00" & data1_D) - unsigned("00" & data2_D);
|
||||||
|
tmp_res := tmp_res + ("00" & CONST_BIAS);
|
||||||
|
-- Underflow
|
||||||
|
if (tmp_res(DAC_DATA_WIDTH+1 downto DAC_DATA_WIDTH) = "11") then
|
||||||
|
data_out <= (others => '0');
|
||||||
|
-- Overflow
|
||||||
|
elsif (tmp_res(DAC_DATA_WIDTH) = '1') then
|
||||||
|
data_out <= (others => '1');
|
||||||
|
else
|
||||||
|
data_out <= std_logic_vector(tmp_res(DAC_DATA_WIDTH-1 downto 0));
|
||||||
|
end if;
|
||||||
end if;
|
end if;
|
||||||
addsub_out <= std_logic_vector(tmp_res + CONST_HALF);
|
-- Single Input Mode
|
||||||
-- Single Input
|
|
||||||
else
|
else
|
||||||
-- ADD
|
-- ADD
|
||||||
if (addsub_mode = '1') then
|
if (addsub_mode_latch = '1') then
|
||||||
addsub_out <= inputB;
|
data_out <= data1_D;
|
||||||
-- SUB
|
-- SUB
|
||||||
else
|
else
|
||||||
addsub_out <= std_logic_vector(CONST_MAX - unsigned(inputB));
|
data_out <= not data1_D;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
-- addsub_instA : addsub
|
done_IV_prc : process(clk)
|
||||||
-- generic map(
|
|
||||||
-- PIPELINE_STAGES => 1,
|
|
||||||
-- DATA_WIDTH => DAC_DATA_WIDTH
|
|
||||||
-- )
|
|
||||||
-- port map(
|
|
||||||
-- clk => clk,
|
|
||||||
-- reset => reset,
|
|
||||||
-- mode => addsub_mode,
|
|
||||||
-- cap => add_input_mux,
|
|
||||||
-- A => inputA,
|
|
||||||
-- B => inputB,
|
|
||||||
-- RES => addsub_out
|
|
||||||
-- );
|
|
||||||
|
|
||||||
process(clk)
|
|
||||||
begin
|
begin
|
||||||
if (rising_edge(clk)) then
|
if (rising_edge(clk)) then
|
||||||
if (reset = '1') then
|
if (reset = '1') then
|
||||||
addsub_done <= '0';
|
done_IV <= '0';
|
||||||
else
|
else
|
||||||
addsub_done <= scaler_done;
|
done_IV <= done_II;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
--*****STAGE V*****
|
--*****STAGE V*****
|
||||||
|
|
||||||
dac_inst : pmod_da3_ctrl
|
dac_inst : pmod_da3_ctrl
|
||||||
generic map(
|
generic map(
|
||||||
TRANSFER_CLK_COUNT => DAC_TRANSFER_CLK_COUNT,
|
TRANSFER_CLK_COUNT => DAC_TRANSFER_CLK_COUNT,
|
||||||
@ -408,8 +416,8 @@ begin
|
|||||||
port map(
|
port map(
|
||||||
clk => clk,
|
clk => clk,
|
||||||
reset => reset,
|
reset => reset,
|
||||||
start => addsub_done,
|
start => done_IV,
|
||||||
data => addsub_out,
|
data => data_out,
|
||||||
cs_n => dac_cs_n,
|
cs_n => dac_cs_n,
|
||||||
sdata => dac_data_out,
|
sdata => dac_data_out,
|
||||||
ldac => dac_ldac,
|
ldac => dac_ldac,
|
||||||
@ -433,15 +441,15 @@ begin
|
|||||||
elsif (to_integer(unsigned(adc_data2)) >= to_integer(unsigned(adc_data2_max))) then
|
elsif (to_integer(unsigned(adc_data2)) >= to_integer(unsigned(adc_data2_max))) then
|
||||||
adc_data2_max <= adc_data2;
|
adc_data2_max <= adc_data2;
|
||||||
end if;
|
end if;
|
||||||
-- DAC MAX VALUES
|
|
||||||
elsif (addsub_done = '1') then
|
|
||||||
if (to_integer(unsigned(addsub_out)) >= to_integer(unsigned(dac_max))) then
|
|
||||||
dac_max <= addsub_out;
|
|
||||||
end if;
|
|
||||||
-- SCALER MAX VALUES
|
-- SCALER MAX VALUES
|
||||||
elsif (scaler_done = '1') then
|
elsif (done_II = '1') then
|
||||||
if (to_integer(unsigned(scaler_1_out)) >= to_integer(unsigned(scaler_max))) then
|
if (to_integer(unsigned(data1_B)) >= to_integer(unsigned(scaler_max))) then
|
||||||
scaler_max <= scaler_1_out(DAC_DATA_WIDTH-1 downto 0);
|
scaler_max <= data1_B(DAC_DATA_WIDTH-1 downto 0);
|
||||||
|
end if;
|
||||||
|
-- DAC MAX VALUES
|
||||||
|
elsif (done_IV = '1') then
|
||||||
|
if (to_integer(unsigned(data_out)) >= to_integer(unsigned(dac_max))) then
|
||||||
|
dac_max <= data_out;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
end if;
|
end if;
|
||||||
|
|||||||
@ -76,9 +76,10 @@ architecture arch of feedback_top is
|
|||||||
dac_sclk : out std_logic; -- PMOD-DA3
|
dac_sclk : out std_logic; -- PMOD-DA3
|
||||||
-- DYNAMIC CONFIGURATION
|
-- DYNAMIC CONFIGURATION
|
||||||
addsub_mode : in std_logic; -- (1=ADD, 0=SUB)
|
addsub_mode : in std_logic; -- (1=ADD, 0=SUB)
|
||||||
add_input_mux : in std_logic; -- (1=ADC Input 2, 0=GND)
|
add_input_mux : in std_logic; -- (1=Double Input 2, 0=Single Input)
|
||||||
delay : in std_logic_vector(DELAY_WIDTH-1 downto 0); -- unsigned delay clock count
|
delay : in std_logic_vector(DELAY_WIDTH-1 downto 0); -- Unsigned delay clock count
|
||||||
factor : in std_logic_vector(FACTOR_WIDTH-1 downto 0); -- 1Q3 Fixed Point
|
factor1 : in std_logic_vector(FACTOR_WIDTH-1 downto 0); -- Q1.x Fixed Point
|
||||||
|
factor2 : in std_logic_vector(FACTOR_WIDTH-1 downto 0); -- Q1.x Fixed Point
|
||||||
-- DEBUG
|
-- DEBUG
|
||||||
reset_debug : in std_logic;
|
reset_debug : in std_logic;
|
||||||
adc_data1_max : out std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
|
adc_data1_max : out std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
|
||||||
@ -102,7 +103,8 @@ architecture arch of feedback_top is
|
|||||||
addsub_mode : out std_logic;
|
addsub_mode : out std_logic;
|
||||||
add_input_mux : out std_logic;
|
add_input_mux : out std_logic;
|
||||||
delay : out std_logic_vector(DELAY_WIDTH-1 downto 0);
|
delay : out std_logic_vector(DELAY_WIDTH-1 downto 0);
|
||||||
factor : out std_logic_vector(FACTOR_WIDTH-1 downto 0)
|
factor1 : out std_logic_vector(FACTOR_WIDTH-1 downto 0);
|
||||||
|
factor2 : out std_logic_vector(FACTOR_WIDTH-1 downto 0)
|
||||||
);
|
);
|
||||||
end component;
|
end component;
|
||||||
|
|
||||||
@ -142,7 +144,7 @@ architecture arch of feedback_top is
|
|||||||
signal clk_20, reset, sync_pulse, standby, reset_debug : std_logic := '0';
|
signal clk_20, reset, sync_pulse, standby, reset_debug : std_logic := '0';
|
||||||
signal addsub_mode, add_input_mux : std_logic := '0';
|
signal addsub_mode, add_input_mux : std_logic := '0';
|
||||||
signal delay : std_logic_vector(DELAY_WIDTH-1 downto 0) := (others => '0');
|
signal delay : std_logic_vector(DELAY_WIDTH-1 downto 0) := (others => '0');
|
||||||
signal factor : std_logic_vector(FACTOR_WIDTH-1 downto 0) := (others => '0');
|
signal factor1, factor2 : std_logic_vector(FACTOR_WIDTH-1 downto 0) := (others => '0');
|
||||||
signal adc_data1_max, adc_data2_max : std_logic_vector(ADC_DATA_WIDTH-1 downto 0) := (others => '0');
|
signal adc_data1_max, adc_data2_max : std_logic_vector(ADC_DATA_WIDTH-1 downto 0) := (others => '0');
|
||||||
signal scaler_max, dac_max : std_logic_vector(DAC_DATA_WIDTH-1 downto 0) := (others => '0');
|
signal scaler_max, dac_max : std_logic_vector(DAC_DATA_WIDTH-1 downto 0) := (others => '0');
|
||||||
signal config_addr : std_logic_vector(CONFIG_MEM_ADDR_WIDTH-1 downto 0) := (others => '0');
|
signal config_addr : std_logic_vector(CONFIG_MEM_ADDR_WIDTH-1 downto 0) := (others => '0');
|
||||||
@ -219,7 +221,8 @@ begin
|
|||||||
addsub_mode => addsub_mode,
|
addsub_mode => addsub_mode,
|
||||||
add_input_mux => add_input_mux,
|
add_input_mux => add_input_mux,
|
||||||
delay => delay,
|
delay => delay,
|
||||||
factor => factor,
|
factor1 => factor1,
|
||||||
|
factor2 => factor2,
|
||||||
reset_debug => reset_debug,
|
reset_debug => reset_debug,
|
||||||
adc_data1_max => adc_data1_max,
|
adc_data1_max => adc_data1_max,
|
||||||
adc_data2_max => adc_data2_max,
|
adc_data2_max => adc_data2_max,
|
||||||
@ -238,7 +241,8 @@ begin
|
|||||||
addsub_mode => addsub_mode,
|
addsub_mode => addsub_mode,
|
||||||
add_input_mux => add_input_mux,
|
add_input_mux => add_input_mux,
|
||||||
delay => delay,
|
delay => delay,
|
||||||
factor => factor
|
factor1 => factor1,
|
||||||
|
factor2 => factor2
|
||||||
);
|
);
|
||||||
|
|
||||||
xillybus_link_inst : xillybus_link
|
xillybus_link_inst : xillybus_link
|
||||||
|
|||||||
@ -25,7 +25,7 @@ end entity;
|
|||||||
|
|
||||||
architecture arch of mult is
|
architecture arch of mult is
|
||||||
|
|
||||||
|
signal P_wide : std_logic_vector(A_WIDTH+B_WIDTH+1 downto 0) := (others => '0');
|
||||||
begin
|
begin
|
||||||
|
|
||||||
mult_gen : if (UNSIGNED = true) generate
|
mult_gen : if (UNSIGNED = true) generate
|
||||||
@ -36,14 +36,14 @@ begin
|
|||||||
WIDTH_A => A_WIDTH+1, -- Multiplier A-input bus width, 1-25
|
WIDTH_A => A_WIDTH+1, -- Multiplier A-input bus width, 1-25
|
||||||
WIDTH_B => B_WIDTH+1) -- Multiplier B-input bus width, 1-18
|
WIDTH_B => B_WIDTH+1) -- Multiplier B-input bus width, 1-18
|
||||||
port map (
|
port map (
|
||||||
P(A_WIDTH+B_WIDTH+1 downto A_WIDTH+B_WIDTH) => open,
|
P => P_wide,
|
||||||
P(A_WIDTH+B_WIDTH-1 downto 0) => P,
|
|
||||||
A => "0" & A,
|
A => "0" & A,
|
||||||
B => "0" & B,
|
B => "0" & B,
|
||||||
CE => '1',
|
CE => '1',
|
||||||
CLK => clk,
|
CLK => clk,
|
||||||
RST => '0'
|
RST => '0'
|
||||||
);
|
);
|
||||||
|
P <= P_wide(A_WIDTH+B_WIDTH-1 downto 0);
|
||||||
else generate
|
else generate
|
||||||
MULT_MACRO_inst : MULT_MACRO
|
MULT_MACRO_inst : MULT_MACRO
|
||||||
generic map (
|
generic map (
|
||||||
|
|||||||
322
src/sim/feedback_loop_tb.vhd
Normal file
322
src/sim/feedback_loop_tb.vhd
Normal file
@ -0,0 +1,322 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
use work.typedef_package.all;
|
||||||
|
use work.sine_package.all;
|
||||||
|
|
||||||
|
entity feedback_loop_tb is
|
||||||
|
end entity;
|
||||||
|
|
||||||
|
architecture beh of feedback_loop_tb is
|
||||||
|
|
||||||
|
--*****COMPONENT DECLARATION*****
|
||||||
|
component feedback_loop is
|
||||||
|
port (
|
||||||
|
clk : in std_logic;
|
||||||
|
reset : in std_logic;
|
||||||
|
adc_data_in1 : in std_logic; -- PMOD-AD1
|
||||||
|
adc_data_in2 : in std_logic; -- PMOD-AD1
|
||||||
|
adc_cs_n : out std_logic; -- PMOD-AD1
|
||||||
|
adc_sclk : out std_logic; -- PMOD-AD1
|
||||||
|
dac_data_out : out std_logic; -- PMOD-DA3
|
||||||
|
dac_cs_n : out std_logic; -- PMOD-DA3
|
||||||
|
dac_ldac : out std_logic; -- PMOD-DA3
|
||||||
|
dac_sclk : out std_logic; -- PMOD-DA3
|
||||||
|
-- DYNAMIC CONFIGURATION
|
||||||
|
addsub_mode : in std_logic; -- (1=ADD, 0=SUB)
|
||||||
|
add_input_mux : in std_logic; -- (1=Double Input 2, 0=Single Input)
|
||||||
|
delay : in std_logic_vector(DELAY_WIDTH-1 downto 0); -- Unsigned delay clock count
|
||||||
|
factor1 : in std_logic_vector(FACTOR_WIDTH-1 downto 0); -- Q1.x Fixed Point
|
||||||
|
factor2 : in std_logic_vector(FACTOR_WIDTH-1 downto 0); -- Q1.x Fixed Point
|
||||||
|
-- DEBUG
|
||||||
|
reset_debug : in std_logic;
|
||||||
|
adc_data1_max : out std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
|
||||||
|
adc_data2_max : out std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
|
||||||
|
scaler_max : out std_logic_vector(DAC_DATA_WIDTH-1 downto 0);
|
||||||
|
dac_max : out std_logic_vector(DAC_DATA_WIDTH-1 downto 0)
|
||||||
|
);
|
||||||
|
end component;
|
||||||
|
|
||||||
|
type ADC_STAGE_TYPE is (ZERO, DATA);
|
||||||
|
|
||||||
|
constant ZERO_SIGNAL : SIGNAL_RECORD_TYPE := (
|
||||||
|
sine => (others => (others => '0')),
|
||||||
|
len => 1
|
||||||
|
);
|
||||||
|
constant HALF_SIGNAL : SIGNAL_RECORD_TYPE := (
|
||||||
|
sine => (others => x"800"),
|
||||||
|
len => 1
|
||||||
|
);
|
||||||
|
|
||||||
|
--*****SIGNAL DECLARATION*****
|
||||||
|
signal clk, reset : std_logic := '0';
|
||||||
|
signal adc_data_in1, adc_data_in2, adc_cs_n : std_logic := '0';
|
||||||
|
signal factor1, factor2 : std_logic_vector(FACTOR_WIDTH-1 downto 0) := (others => '0');
|
||||||
|
signal addsub_mode, add_input_mux : std_logic := '0';
|
||||||
|
signal delay : std_logic_vector(DELAY_WIDTH-1 downto 0) := (others => '0');
|
||||||
|
signal adc_stage : ADC_STAGE_TYPE := ZERO;
|
||||||
|
signal cnt1, cnt2, cnt3 : integer := 0;
|
||||||
|
signal input1, input2 : std_logic_vector(ADC_DATA_WIDTH-1 downto 0) := (others => '0');
|
||||||
|
signal output : std_logic_vector(DAC_DATA_WIDTH-1 downto 0) := (others => '0');
|
||||||
|
signal sig1, sig2 : SIGNAL_RECORD_TYPE := ZERO_SIGNAL;
|
||||||
|
|
||||||
|
procedure wait_samples( num : in natural) is
|
||||||
|
begin
|
||||||
|
-- Num * Sampling Cadence * Clock Period
|
||||||
|
wait for num*18*50 ns;
|
||||||
|
wait until rising_edge(clk);
|
||||||
|
end procedure;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
--*****COMPONENT INSTANTIATION*****
|
||||||
|
uut : feedback_loop
|
||||||
|
port map(
|
||||||
|
clk => clk,
|
||||||
|
reset => reset,
|
||||||
|
adc_data_in1 => adc_data_in1,
|
||||||
|
adc_data_in2 => adc_data_in2,
|
||||||
|
adc_cs_n => adc_cs_n,
|
||||||
|
adc_sclk => open,
|
||||||
|
dac_data_out => open,
|
||||||
|
dac_cs_n => open,
|
||||||
|
dac_ldac => open,
|
||||||
|
dac_sclk => open,
|
||||||
|
addsub_mode => addsub_mode,
|
||||||
|
add_input_mux => add_input_mux,
|
||||||
|
delay => delay,
|
||||||
|
factor1 => factor1,
|
||||||
|
factor2 => factor2,
|
||||||
|
reset_debug => '0',
|
||||||
|
adc_data1_max => open,
|
||||||
|
adc_data2_max => open,
|
||||||
|
scaler_max => open,
|
||||||
|
dac_max => open
|
||||||
|
);
|
||||||
|
|
||||||
|
clk_prc : process
|
||||||
|
begin
|
||||||
|
clk <= '1';
|
||||||
|
wait for 25 ns;
|
||||||
|
clk <= '0';
|
||||||
|
wait for 25 ns;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
process
|
||||||
|
begin
|
||||||
|
--INITIALISE SIGNALS
|
||||||
|
reset <= '1';
|
||||||
|
wait until rising_edge(clk);
|
||||||
|
wait until rising_edge(clk);
|
||||||
|
reset <= '0';
|
||||||
|
report "Single Input, Signal 1 [MAX Amplitude, 10kHz], Positive Feedback, Scale 1";
|
||||||
|
sig1 <= sine1;
|
||||||
|
sig2 <= ZERO_SIGNAL;
|
||||||
|
add_input_mux <= '0';
|
||||||
|
addsub_mode <= '1';
|
||||||
|
factor1 <= "10000"; --1.0
|
||||||
|
factor2 <= "10000"; --1.0
|
||||||
|
delay <= std_logic_vector(to_unsigned(0,DELAY_WIDTH));
|
||||||
|
wait_samples(sine1.len);
|
||||||
|
report "Single Input, Signal 1 [MAX Amplitude, 10kHz], Negative Feedback, Scale 1";
|
||||||
|
sig1 <= sine1;
|
||||||
|
sig2 <= ZERO_SIGNAL;
|
||||||
|
add_input_mux <= '0';
|
||||||
|
addsub_mode <= '0';
|
||||||
|
factor1 <= "10000"; --1.0
|
||||||
|
factor2 <= "10000"; --1.0
|
||||||
|
delay <= std_logic_vector(to_unsigned(0,DELAY_WIDTH));
|
||||||
|
wait_samples(sine1.len);
|
||||||
|
report "Single Input, Signal 1 [DAC Adjusted MAX Amplitude, 10kHz], Positive Feedback, Scale 1.32";
|
||||||
|
sig1 <= sine3;
|
||||||
|
sig2 <= ZERO_SIGNAL;
|
||||||
|
add_input_mux <= '0';
|
||||||
|
addsub_mode <= '1';
|
||||||
|
factor1 <= "10101"; --1.32
|
||||||
|
factor2 <= "10000"; --1.0
|
||||||
|
delay <= std_logic_vector(to_unsigned(0,DELAY_WIDTH));
|
||||||
|
wait_samples(sine3.len);
|
||||||
|
report "Single Input, Signal 1 [MAX Amplitude, 10kHz], Positive Feedback, Scale 1.32";
|
||||||
|
sig1 <= sine1;
|
||||||
|
sig2 <= ZERO_SIGNAL;
|
||||||
|
add_input_mux <= '0';
|
||||||
|
addsub_mode <= '1';
|
||||||
|
factor1 <= "10101"; --1.32
|
||||||
|
factor2 <= "10000"; --1.0
|
||||||
|
delay <= std_logic_vector(to_unsigned(0,DELAY_WIDTH));
|
||||||
|
wait_samples(sine1.len);
|
||||||
|
report "Single Input, Signal 1 [MAX Amplitude, 10kHz], Positive Feedback, Scale 0.5";
|
||||||
|
sig1 <= sine1;
|
||||||
|
sig2 <= ZERO_SIGNAL;
|
||||||
|
add_input_mux <= '0';
|
||||||
|
addsub_mode <= '1';
|
||||||
|
factor1 <= "01000"; --0.5
|
||||||
|
factor2 <= "10000"; --1.0
|
||||||
|
delay <= std_logic_vector(to_unsigned(0,DELAY_WIDTH));
|
||||||
|
wait_samples(sine1.len);
|
||||||
|
report "Double Input, Signal 1 [HALF Amplitude, 10kHz], Signal 2 [Static HALF], Positive Feedback, Scale1 1, Scale2 1, Delay 0";
|
||||||
|
sig1 <= sine2;
|
||||||
|
sig2 <= HALF_SIGNAL;
|
||||||
|
add_input_mux <= '1';
|
||||||
|
addsub_mode <= '1';
|
||||||
|
factor1 <= "10000"; --1.0
|
||||||
|
factor2 <= "10000"; --1.0
|
||||||
|
delay <= std_logic_vector(to_unsigned(0,DELAY_WIDTH));
|
||||||
|
wait_samples(sine2.len);
|
||||||
|
report "Double Input, Signal 1 [HALF Amplitude, 10kHz], Signal 2 [HALF Amplitude, 10kHz], Positive Feedback, Scale1 1, Scale2 1, Delay 0";
|
||||||
|
sig1 <= sine2;
|
||||||
|
sig2 <= sine2;
|
||||||
|
add_input_mux <= '1';
|
||||||
|
addsub_mode <= '1';
|
||||||
|
factor1 <= "10000"; --1.0
|
||||||
|
factor2 <= "10000"; --1.0
|
||||||
|
delay <= std_logic_vector(to_unsigned(0,DELAY_WIDTH));
|
||||||
|
wait_samples(sine2.len);
|
||||||
|
report "Double Input, Signal 1 [MAX Amplitude, 10kHz], Signal 2 [HALF Amplitude, 10kHz], Positive Feedback, Scale1 1, Scale2 1, Delay 0";
|
||||||
|
sig1 <= sine1;
|
||||||
|
sig2 <= sine2;
|
||||||
|
add_input_mux <= '1';
|
||||||
|
addsub_mode <= '1';
|
||||||
|
factor1 <= "10000"; --1.0
|
||||||
|
factor2 <= "10000"; --1.0
|
||||||
|
delay <= std_logic_vector(to_unsigned(0,DELAY_WIDTH));
|
||||||
|
wait_samples(sine1.len);
|
||||||
|
report "Double Input, Signal 1 [MAX Amplitude, 10kHz], Signal 2 [MAX Amplitude, 10kHz], Positive Feedback, Scale1 0.75, Scale2 0.25, Delay 0";
|
||||||
|
sig1 <= sine1;
|
||||||
|
sig2 <= sine1;
|
||||||
|
add_input_mux <= '1';
|
||||||
|
addsub_mode <= '1';
|
||||||
|
factor1 <= "01100"; --0.75
|
||||||
|
factor2 <= "00100"; --0.25
|
||||||
|
delay <= std_logic_vector(to_unsigned(0,DELAY_WIDTH));
|
||||||
|
wait_samples(sine1.len);
|
||||||
|
report "Double Input, Signal 1 [HALF Amplitude, 10kHz], Signal 2 [HALF Amplitude, 10kHz], Negative Feedback, Scale1 1, Scale2 1, Delay 0";
|
||||||
|
sig1 <= sine2;
|
||||||
|
sig2 <= sine2;
|
||||||
|
add_input_mux <= '1';
|
||||||
|
addsub_mode <= '0';
|
||||||
|
factor1 <= "10000"; --1.0
|
||||||
|
factor2 <= "10000"; --1.0
|
||||||
|
delay <= std_logic_vector(to_unsigned(0,DELAY_WIDTH));
|
||||||
|
wait_samples(sine2.len);
|
||||||
|
report "Double Input, Signal 1 [MAX Amplitude, 10kHz], Signal 2 [HALF Amplitude, 10kHz], Negative Feedback, Scale1 1, Scale2 1, Delay 0";
|
||||||
|
sig1 <= sine1;
|
||||||
|
sig2 <= sine2;
|
||||||
|
add_input_mux <= '1';
|
||||||
|
addsub_mode <= '0';
|
||||||
|
factor1 <= "10000"; --1.0
|
||||||
|
factor2 <= "10000"; --1.0
|
||||||
|
delay <= std_logic_vector(to_unsigned(0,DELAY_WIDTH));
|
||||||
|
wait_samples(sine1.len);
|
||||||
|
report "Double Input, Signal 1 [Static HALF], Signal 2 [MAX Amplitude, 10kHz], Negative Feedback, Scale1 1, Scale2 1, Delay 0";
|
||||||
|
sig1 <= HALF_SIGNAL;
|
||||||
|
sig2 <= sine1;
|
||||||
|
add_input_mux <= '1';
|
||||||
|
addsub_mode <= '0';
|
||||||
|
factor1 <= "10000"; --1.0
|
||||||
|
factor2 <= "10000"; --1.0
|
||||||
|
delay <= std_logic_vector(to_unsigned(0,DELAY_WIDTH));
|
||||||
|
wait_samples(sine1.len);
|
||||||
|
report "Double Input, Signal 1 [MAX Amplitude, 10kHz], Signal 2 [HALF Amplitude, 10kHz], Negative Feedback, Scale1 1.32, Scale2 1, Delay 0";
|
||||||
|
sig1 <= sine1;
|
||||||
|
sig2 <= sine2;
|
||||||
|
add_input_mux <= '1';
|
||||||
|
addsub_mode <= '0';
|
||||||
|
factor1 <= "10101"; --1.32
|
||||||
|
factor2 <= "10000"; --1.0
|
||||||
|
delay <= std_logic_vector(to_unsigned(0,DELAY_WIDTH));
|
||||||
|
wait_samples(sine1.len);
|
||||||
|
report "Double Input, Signal 1 [MAX Amplitude, 10kHz], Signal 2 [MAX Amplitude, 10kHz], Positive Feedback, Scale1 1, Scale2 1, Delay 1008";
|
||||||
|
sig1 <= sine1;
|
||||||
|
sig2 <= sine1;
|
||||||
|
add_input_mux <= '1';
|
||||||
|
addsub_mode <= '1';
|
||||||
|
factor1 <= "10000"; --1.0
|
||||||
|
factor2 <= "10000"; --1.0
|
||||||
|
delay <= std_logic_vector(to_unsigned(1008,DELAY_WIDTH));
|
||||||
|
wait_samples(sine1.len+56);
|
||||||
|
report "Double Input, Signal 1 [HALF Amplitude, 10kHz], Signal 2 [MAX Amplitude, 10kHz], Negative Feedback, Scale1 1, Scale2 1, Delay 504";
|
||||||
|
sig1 <= sine2;
|
||||||
|
sig2 <= sine1;
|
||||||
|
add_input_mux <= '1';
|
||||||
|
addsub_mode <= '0';
|
||||||
|
factor1 <= "10000"; --1.0
|
||||||
|
factor2 <= "10000"; --1.0
|
||||||
|
delay <= std_logic_vector(to_unsigned(504,DELAY_WIDTH));
|
||||||
|
wait_samples(sine1.len+28);
|
||||||
|
wait;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
adc_prc : process (all)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
case (adc_stage) is
|
||||||
|
when ZERO =>
|
||||||
|
if (adc_cs_n = '0') then
|
||||||
|
cnt1 <= cnt1 + 1;
|
||||||
|
if (cnt1 = 3) then
|
||||||
|
cnt1 <= 11;
|
||||||
|
adc_stage <= DATA;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
when DATA =>
|
||||||
|
if (adc_cs_n = '0') then
|
||||||
|
cnt1 <= cnt1 - 1;
|
||||||
|
if (cnt1 = 0) then
|
||||||
|
-- Signal 1
|
||||||
|
if (cnt2 = sig1.len-1) then
|
||||||
|
cnt2 <= 0;
|
||||||
|
else
|
||||||
|
cnt2 <= cnt2 + 1;
|
||||||
|
end if;
|
||||||
|
-- Signal 2
|
||||||
|
if (cnt3 = sig2.len-1) then
|
||||||
|
cnt3 <= 0;
|
||||||
|
else
|
||||||
|
cnt3 <= cnt3 + 1;
|
||||||
|
end if;
|
||||||
|
cnt1 <= 0;
|
||||||
|
adc_stage <= ZERO;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
case (adc_stage) is
|
||||||
|
when ZERO =>
|
||||||
|
adc_data_in1 <= '0';
|
||||||
|
adc_data_in2 <= '0';
|
||||||
|
when DATA =>
|
||||||
|
adc_data_in1 <= sig1.sine(cnt2)(cnt1);
|
||||||
|
adc_data_in2 <= sig2.sine(cnt3)(cnt1);
|
||||||
|
end case;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
io_prc : process (all)
|
||||||
|
alias in_done is <<signal uut.adc_done : std_logic>>;
|
||||||
|
alias in1 is <<signal uut.data1_A : std_logic_vector(ADC_DATA_WIDTH-1 downto 0)>>;
|
||||||
|
alias in2 is <<signal uut.data2_A : std_logic_vector(ADC_DATA_WIDTH downto 0)>>;
|
||||||
|
alias out1 is <<signal uut.data_out : std_logic_vector(DAC_DATA_WIDTH-1 downto 0)>>;
|
||||||
|
alias out_done is <<signal uut.done_IV : std_logic>>;
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
-- Signle Input Mode
|
||||||
|
if (add_input_mux = '0') then
|
||||||
|
if (in_done = '1') then
|
||||||
|
input1 <= in1;
|
||||||
|
input2 <= in2(ADC_DATA_WIDTH-1 downto 0);
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
if (in2(ADC_DATA_WIDTH) = '1') then
|
||||||
|
input1 <= in1;
|
||||||
|
input2 <= in2(ADC_DATA_WIDTH-1 downto 0);
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
if (out_done = '1') then
|
||||||
|
output <= out1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
end architecture;
|
||||||
125
src/sim/gen_sine.sh
Executable file
125
src/sim/gen_sine.sh
Executable file
@ -0,0 +1,125 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "USAGE: $0 -h|--help"
|
||||||
|
echo "USAGE: $0 [-z NUMBER] [-a NUMBER] [-n NUMBER] [-f FILE]"
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " -z Sine Zero value in decimal (sin(0))"
|
||||||
|
echo " -a Sine Amplitude value in decimal (sin(pi))"
|
||||||
|
echo " -n Number of Period Samples"
|
||||||
|
echo " -f Output VHDL File"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#**********MAIN**********
|
||||||
|
|
||||||
|
FILE="test_sine.vhd"
|
||||||
|
amp=1024
|
||||||
|
zero=512
|
||||||
|
num=1024
|
||||||
|
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
-a)
|
||||||
|
shift
|
||||||
|
amp=$1
|
||||||
|
shift
|
||||||
|
case $amp in
|
||||||
|
''|*[!0-9]*)
|
||||||
|
echo "ERROR: -a Option needs a Decimal Number."
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*);;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
-z)
|
||||||
|
shift
|
||||||
|
zero=$1
|
||||||
|
shift
|
||||||
|
case $zero in
|
||||||
|
''|*[!0-9]*)
|
||||||
|
echo "ERROR: -z Option needs a Decimal Number."
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*);;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
-n)
|
||||||
|
shift
|
||||||
|
num=$1
|
||||||
|
shift
|
||||||
|
case $num in
|
||||||
|
''|*[!0-9]*)
|
||||||
|
echo "ERROR: -n Option needs a Decimal Number."
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
*);;
|
||||||
|
esac
|
||||||
|
;;
|
||||||
|
-f)
|
||||||
|
shift
|
||||||
|
FILE=$1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "ERROR: Unknown Option"
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
#SANITY CHECK
|
||||||
|
if [ $amp -gt $zero ]
|
||||||
|
then
|
||||||
|
echo "ERROR: The Sine Amplitude has to be smaller than the Zero point."
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ $(echo "$amp+$zero" | bc -l) -gt 4095 ]
|
||||||
|
then
|
||||||
|
echo "ERROR: The requested Sine exceeds the 12 Bits representation (2^12=4096)"
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#Calculate Stepping
|
||||||
|
step=$(echo "(2*(4*a(1)))/$num" | bc -l)
|
||||||
|
num=$(echo "$num-1" | bc -l)
|
||||||
|
|
||||||
|
cat <<EOF >$FILE
|
||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
package sine_package is
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo " type SINE_ARRAY_TYPE is array (0 to $num) of std_logic_vector(11 downto 0);" >>$FILE
|
||||||
|
array=" constant sine : SINE_ARRAY_TYPE := ("
|
||||||
|
|
||||||
|
for i in $(seq 0 $num)
|
||||||
|
do
|
||||||
|
#Calculate Value
|
||||||
|
val=$(echo "($amp * s($i*$step))+$zero" | bc -l)
|
||||||
|
#Round
|
||||||
|
val=$(printf '%.0f' $val)
|
||||||
|
array=$array$(printf 'x"%03X"' $val)
|
||||||
|
|
||||||
|
if [ $i -eq $num ]
|
||||||
|
then
|
||||||
|
array=$array$(printf ');\n')
|
||||||
|
else
|
||||||
|
array=$array", "
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo $array >>$FILE
|
||||||
|
echo "end package;" >>$FILE
|
||||||
42
src/sim/sine_package.vhd
Normal file
42
src/sim/sine_package.vhd
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
package sine_package is
|
||||||
|
type SIGNAL_ARRAY_TYPE is array (0 to 1024) of std_logic_vector(11 downto 0);
|
||||||
|
type SIGNAL_RECORD_TYPE is record
|
||||||
|
sine : SIGNAL_ARRAY_TYPE;
|
||||||
|
len : natural;
|
||||||
|
end record;
|
||||||
|
|
||||||
|
-- ZERO: 2048, AMPLITUDE: 2047, FREQUENCY: 10kHz
|
||||||
|
constant sine1 : SIGNAL_RECORD_TYPE := (
|
||||||
|
sine => (x"800", x"873", x"8E5", x"957", x"9C8", x"A37", x"AA4", x"B0F", x"B78", x"BDE", x"C41", x"CA1", x"CFC", x"D54", x"DA7", x"DF6", x"E40", x"E85", x"EC5", x"F00", x"F34", x"F63", x"F8C", x"FAF", x"FCC", x"FE2", x"FF2", x"FFC", x"FFF", x"FFC", x"FF2", x"FE2", x"FCC", x"FAF", x"F8C", x"F63", x"F34", x"F00", x"EC5", x"E85", x"E40", x"DF6", x"DA7", x"D54", x"CFC", x"CA1", x"C41", x"BDE", x"B78", x"B0F", x"AA4", x"A37", x"9C8", x"957", x"8E5", x"873", x"800", x"78D", x"71B", x"6A9", x"638", x"5C9", x"55C", x"4F1", x"488", x"422", x"3BF", x"35F", x"304", x"2AC", x"259", x"20A", x"1C0", x"17B", x"13B", x"100", x"0CC", x"09D", x"074", x"051", x"034", x"01E", x"00E", x"004", x"001", x"004", x"00E", x"01E", x"034", x"051", x"074", x"09D", x"0CC", x"100", x"13B", x"17B", x"1C0", x"20A", x"259", x"2AC", x"304", x"35F", x"3BF", x"422", x"488", x"4F1", x"55C", x"5C9", x"638", x"6A9", x"71B", x"78D", others => x"000"),
|
||||||
|
len => 112
|
||||||
|
);
|
||||||
|
-- ZERO: 2048, AMPLITUDE: 1024, FREQUENCY: 10kHz
|
||||||
|
constant sine2 : SIGNAL_RECORD_TYPE := (
|
||||||
|
sine => (x"800", x"839", x"873", x"8AC", x"8E4", x"91B", x"952", x"988", x"9BC", x"9EF", x"A21", x"A51", x"A7E", x"AAA", x"AD4", x"AFC", x"B21", x"B43", x"B63", x"B80", x"B9B", x"BB2", x"BC7", x"BD8", x"BE6", x"BF2", x"BFA", x"BFE", x"C00", x"BFE", x"BFA", x"BF2", x"BE6", x"BD8", x"BC7", x"BB2", x"B9B", x"B80", x"B63", x"B43", x"B21", x"AFC", x"AD4", x"AAA", x"A7E", x"A51", x"A21", x"9EF", x"9BC", x"988", x"952", x"91B", x"8E4", x"8AC", x"873", x"839", x"800", x"7C7", x"78D", x"754", x"71C", x"6E5", x"6AE", x"678", x"644", x"611", x"5DF", x"5AF", x"582", x"556", x"52C", x"504", x"4DF", x"4BD", x"49D", x"480", x"465", x"44E", x"439", x"428", x"41A", x"40E", x"406", x"402", x"400", x"402", x"406", x"40E", x"41A", x"428", x"439", x"44E", x"465", x"480", x"49D", x"4BD", x"4DF", x"504", x"52C", x"556", x"582", x"5AF", x"5DF", x"611", x"644", x"678", x"6AE", x"6E5", x"71C", x"754", x"78D", x"7C7", others => x"000"),
|
||||||
|
len => 112
|
||||||
|
);
|
||||||
|
-- ZERO: 2048, AMPLITUDE: 1551, FREQUENCY: 10kHz
|
||||||
|
constant sine3 : SIGNAL_RECORD_TYPE := (
|
||||||
|
sine => (x"800", x"857", x"8AE", x"904", x"959", x"9AD", x"A00", x"A52", x"AA1", x"AEE", x"B39", x"B82", x"BC7", x"C0A", x"C49", x"C84", x"CBD", x"CF1", x"D21", x"D4D", x"D75", x"D99", x"DB8", x"DD2", x"DE8", x"DF9", x"E05", x"E0D", x"E0F", x"E0D", x"E05", x"DF9", x"DE8", x"DD2", x"DB8", x"D99", x"D75", x"D4D", x"D21", x"CF1", x"CBD", x"C84", x"C49", x"C0A", x"BC7", x"B82", x"B39", x"AEE", x"AA1", x"A52", x"A00", x"9AD", x"959", x"904", x"8AE", x"857", x"800", x"7A9", x"752", x"6FC", x"6A7", x"653", x"600", x"5AE", x"55F", x"512", x"4C7", x"47E", x"439", x"3F6", x"3B7", x"37C", x"343", x"30F", x"2DF", x"2B3", x"28B", x"267", x"248", x"22E", x"218", x"207", x"1FB", x"1F3", x"1F1", x"1F3", x"1FB", x"207", x"218", x"22E", x"248", x"267", x"28B", x"2B3", x"2DF", x"30F", x"343", x"37C", x"3B7", x"3F6", x"439", x"47E", x"4C7", x"512", x"55F", x"5AE", x"600", x"653", x"6A7", x"6FC", x"752", x"7A9", others => x"000"),
|
||||||
|
len => 112
|
||||||
|
);
|
||||||
|
-- ZERO: 2048, AMPLITUDE: 2047, FREQUENCY: 20kHz
|
||||||
|
constant sine4 : SIGNAL_RECORD_TYPE := (
|
||||||
|
sine => (x"800", x"8E5", x"9C8", x"AA4", x"B78", x"C41", x"CFC", x"DA7", x"E40", x"EC5", x"F34", x"F8C", x"FCC", x"FF2", x"FFF", x"FF2", x"FCC", x"F8C", x"F34", x"EC5", x"E40", x"DA7", x"CFC", x"C41", x"B78", x"AA4", x"9C8", x"8E5", x"800", x"71B", x"638", x"55C", x"488", x"3BF", x"304", x"259", x"1C0", x"13B", x"0CC", x"074", x"034", x"00E", x"001", x"00E", x"034", x"074", x"0CC", x"13B", x"1C0", x"259", x"304", x"3BF", x"488", x"55C", x"638", x"71B", others => x"000"),
|
||||||
|
len => 56
|
||||||
|
);
|
||||||
|
-- ZERO: 2048, AMPLITUDE: 1024, FREQUENCY: 20kHz
|
||||||
|
constant sine5 : SIGNAL_RECORD_TYPE := (
|
||||||
|
sine => (x"800", x"873", x"8E4", x"952", x"9BC", x"A21", x"A7E", x"AD4", x"B21", x"B63", x"B9B", x"BC7", x"BE6", x"BFA", x"C00", x"BFA", x"BE6", x"BC7", x"B9B", x"B63", x"B21", x"AD4", x"A7E", x"A21", x"9BC", x"952", x"8E4", x"873", x"800", x"78D", x"71C", x"6AE", x"644", x"5DF", x"582", x"52C", x"4DF", x"49D", x"465", x"439", x"41A", x"406", x"400", x"406", x"41A", x"439", x"465", x"49D", x"4DF", x"52C", x"582", x"5DF", x"644", x"6AE", x"71C", x"78D", others => x"000"),
|
||||||
|
len => 56
|
||||||
|
);
|
||||||
|
-- ZERO: 2048, AMPLITUDE: 1551, FREQUENCY: 20kHz
|
||||||
|
constant sine6 : SIGNAL_RECORD_TYPE := (
|
||||||
|
sine => (x"800", x"8AE", x"959", x"A00", x"AA1", x"B39", x"BC7", x"C49", x"CBD", x"D21", x"D75", x"DB8", x"DE8", x"E05", x"E0F", x"E05", x"DE8", x"DB8", x"D75", x"D21", x"CBD", x"C49", x"BC7", x"B39", x"AA1", x"A00", x"959", x"8AE", x"800", x"752", x"6A7", x"600", x"55F", x"4C7", x"439", x"3B7", x"343", x"2DF", x"28B", x"248", x"218", x"1FB", x"1F1", x"1FB", x"218", x"248", x"28B", x"2DF", x"343", x"3B7", x"439", x"4C7", x"55F", x"600", x"6A7", x"752", others => x"000"),
|
||||||
|
len => 56
|
||||||
|
);
|
||||||
|
end package;
|
||||||
@ -15,12 +15,14 @@ package typedef_package is
|
|||||||
constant ADC_DELAY_CLK_CNT : integer := 2;
|
constant ADC_DELAY_CLK_CNT : integer := 2;
|
||||||
constant DAC_TRANSFER_CLK_COUNT : integer := 16;
|
constant DAC_TRANSFER_CLK_COUNT : integer := 16;
|
||||||
|
|
||||||
constant MAX_DELAY : integer := 200;
|
constant MAX_DELAY : integer := 65536;
|
||||||
constant DELAY_WIDTH : integer := 8; --at least log2(MAX_DELAY)
|
constant DELAY_WIDTH : integer := 16; --at least log2(MAX_DELAY)
|
||||||
constant FACTOR_WIDTH : integer := 5;
|
constant FACTOR_WIDTH : integer := 5;
|
||||||
|
|
||||||
constant TIMESTAMP_WIDTH : integer := 32;
|
constant TIMESTAMP_WIDTH : integer := 32;
|
||||||
|
|
||||||
|
constant BIAS_OFFSET : std_logic_vector(ADC_DATA_WIDTH-1 downto 0) := (ADC_DATA_WIDTH-1 => '1', others => '0');
|
||||||
|
|
||||||
--XILLYBUS
|
--XILLYBUS
|
||||||
constant DEBUG_FIFO_DATA_WIDTH : integer := 32;
|
constant DEBUG_FIFO_DATA_WIDTH : integer := 32;
|
||||||
constant DEBUG_FIFO_DEPTH : integer := 16;
|
constant DEBUG_FIFO_DEPTH : integer := 16;
|
||||||
|
|||||||
@ -14,7 +14,7 @@ use work.typedef_package.all;
|
|||||||
-- memory for configuration. The 32-bit wide 16-bit address interface is converted into 2 32-bit wide
|
-- memory for configuration. The 32-bit wide 16-bit address interface is converted into 2 32-bit wide
|
||||||
-- 15-bit address RAMs, effectively increasing the internal config to 64-bits.
|
-- 15-bit address RAMs, effectively increasing the internal config to 64-bits.
|
||||||
|
|
||||||
-- NOTE: It has to be made sure that the read and write port to not access the smae address at the same
|
-- NOTE: It has to be made sure that the read and write port do not access the same address at the same
|
||||||
-- time
|
-- time
|
||||||
|
|
||||||
entity xillybus_link is
|
entity xillybus_link is
|
||||||
|
|||||||
15
sw/config
15
sw/config
@ -2,13 +2,14 @@
|
|||||||
#
|
#
|
||||||
#Each line of this file defines a configuration slot and consists of integer numbers delimited by white
|
#Each line of this file defines a configuration slot and consists of integer numbers delimited by white
|
||||||
#spaces in the following order:
|
#spaces in the following order:
|
||||||
#ADDSUB_MODE ADD_INPUT_MUX DELAY FACTOR TIMESTAMP
|
#ADDSUB_MODE ADD_INPUT_MUX DELAY FACTOR0 FACTOR1 TIMESTAMP
|
||||||
#
|
#
|
||||||
#ADDSUB_MODE: Select feedback mode (0=negative, 1=positive)
|
#ADDSUB_MODE: Select feedback mode (0=Negative, 1=Positive)
|
||||||
#ADD_INPUT_MUX: Select feedback input (0=GND[only ADC Input 1], 1=ADC Input 2[Both ADC inputs are used])
|
#ADD_INPUT_MUX: Select feedback input (0=Single Input Mode [ADC0], 1=Double Input Mode)
|
||||||
#DELAY: Clock cycles counts (50 ns period) to delay the feedback signal [0-255]
|
#DELAY: Clock cycles counts (50 ns period) to delay the feedback signal [0-65535]
|
||||||
#FACTOR: Multiplication factor to apply to the feedback signal [0-16] (NOTE: Integer is intepreted as a 1Q4 Fixed Point Number!)
|
#FACTOR0: Multiplication factor to apply to the ADC Signal0 [0-32] (NOTE: Integer is intepreted as a Q1.4 Fixed Point Number!)
|
||||||
|
#FACTOR1: Multiplication factor to apply to the ADC Signal1 [0-32] (NOTE: Integer is intepreted as a Q1.4 Fixed Point Number!)
|
||||||
#TIMESTAMP: Defines the clock count number from the sync pulse from which on the configurations settings will be applied. [32-bit unsigned integer]
|
#TIMESTAMP: Defines the clock count number from the sync pulse from which on the configurations settings will be applied. [32-bit unsigned integer]
|
||||||
# First Config slot should have a timestamp equal to zero.
|
# First Config slot should have a timestamp equal to zero.
|
||||||
1 0 0 8 0
|
1 0 0 8 8 0
|
||||||
0 0 0 8 1200000000
|
0 0 0 8 8 1200000000
|
||||||
|
|||||||
BIN
sw/read_debug
BIN
sw/read_debug
Binary file not shown.
BIN
sw/write_config
BIN
sw/write_config
Binary file not shown.
@ -37,7 +37,7 @@ int main(int argc, char *argv[]){
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t data, addsub_mode, add_input_mode, delay, factor, timestamp;
|
uint64_t data, addsub_mode, add_input_mode, delay, factor1, factor2, timestamp;
|
||||||
|
|
||||||
/*File Parsing Loop*/
|
/*File Parsing Loop*/
|
||||||
while(getline(&line, &len, src) != -1){
|
while(getline(&line, &len, src) != -1){
|
||||||
@ -46,7 +46,7 @@ int main(int argc, char *argv[]){
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sscanf(line, "%u %u %u %u %u", &addsub_mode, &add_input_mode, &delay, &factor, ×tamp) < 5){
|
if(sscanf(line, "%u %u %u %u %u %u", &addsub_mode, &add_input_mode, &delay, &factor1, &factor2, ×tamp) < 5){
|
||||||
perror("Parsing of configuration file failed");
|
perror("Parsing of configuration file failed");
|
||||||
fprintf(stderr, "Failing line: %s", line);
|
fprintf(stderr, "Failing line: %s", line);
|
||||||
bail();
|
bail();
|
||||||
@ -54,8 +54,8 @@ int main(int argc, char *argv[]){
|
|||||||
}
|
}
|
||||||
|
|
||||||
data = 0x0;
|
data = 0x0;
|
||||||
data |= ((uint64_t)0x1 << 63) | ((addsub_mode & 0x1) << 62) | ((add_input_mode & 0x1) << 61) | ((delay & 0xFF) << 40) |
|
data |= ((uint64_t)0x1 << 63) | ((addsub_mode & 0x1) << 62) | ((add_input_mode & 0x1) << 61) | ((delay & 0xFF) << 42) |
|
||||||
((factor & 0x1F) << 32) | (timestamp & 0xFFFFFFFF);
|
((factor1 & 0x1F) << 37) | ((factor2 & 0x1F) << 32) | (timestamp & 0xFFFFFFFF);
|
||||||
if(write(dest, &data, sizeof(uint64_t)) != sizeof(uint64_t)){
|
if(write(dest, &data, sizeof(uint64_t)) != sizeof(uint64_t)){
|
||||||
perror("Failed to write data");
|
perror("Failed to write data");
|
||||||
bail();
|
bail();
|
||||||
@ -66,10 +66,10 @@ int main(int argc, char *argv[]){
|
|||||||
//Write A non enabled slot
|
//Write A non enabled slot
|
||||||
data = 0x0;
|
data = 0x0;
|
||||||
if(write(dest, &data, sizeof(uint64_t)) != sizeof(uint64_t)){
|
if(write(dest, &data, sizeof(uint64_t)) != sizeof(uint64_t)){
|
||||||
perror("Failed to write data");
|
perror("Failed to write data");
|
||||||
bail();
|
bail();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Exit safely
|
//Exit safely
|
||||||
bail();
|
bail();
|
||||||
|
|||||||
@ -146,12 +146,6 @@
|
|||||||
<Attr Name="UsedIn" Val="simulation"/>
|
<Attr Name="UsedIn" Val="simulation"/>
|
||||||
</FileInfo>
|
</FileInfo>
|
||||||
</File>
|
</File>
|
||||||
<File Path="$PPRDIR/../../src/addsub.vhd">
|
|
||||||
<FileInfo SFType="VHDL2008">
|
|
||||||
<Attr Name="UsedIn" Val="synthesis"/>
|
|
||||||
<Attr Name="UsedIn" Val="simulation"/>
|
|
||||||
</FileInfo>
|
|
||||||
</File>
|
|
||||||
<File Path="$PPRDIR/../../src/typedef_package.vhd">
|
<File Path="$PPRDIR/../../src/typedef_package.vhd">
|
||||||
<FileInfo SFType="VHDL2008">
|
<FileInfo SFType="VHDL2008">
|
||||||
<Attr Name="UsedIn" Val="synthesis"/>
|
<Attr Name="UsedIn" Val="synthesis"/>
|
||||||
@ -258,6 +252,7 @@
|
|||||||
<Option Name="TopModule" Val="unknown"/>
|
<Option Name="TopModule" Val="unknown"/>
|
||||||
<Option Name="TransportPathDelay" Val="0"/>
|
<Option Name="TransportPathDelay" Val="0"/>
|
||||||
<Option Name="TransportIntDelay" Val="0"/>
|
<Option Name="TransportIntDelay" Val="0"/>
|
||||||
|
<Option Name="SimMode" Val="post-implementation"/>
|
||||||
<Option Name="SrcSet" Val="sources_1"/>
|
<Option Name="SrcSet" Val="sources_1"/>
|
||||||
<Option Name="xsim.simulate.runtime" Val="1000 ns"/>
|
<Option Name="xsim.simulate.runtime" Val="1000 ns"/>
|
||||||
<Option Name="xsim.simulate.uut" Val="UUT"/>
|
<Option Name="xsim.simulate.uut" Val="UUT"/>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user