Compare commits
9 Commits
main
...
v_amp_scal
Author | SHA1 | Date |
---|---|---|
Eric Yu | 334aa10655 | |
Eric Yu | e41460c843 | |
Eric Yu | 26775a0d2b | |
Eric Yu | 5ecd4eaf5a | |
Eric Yu | a0c05457c9 | |
Eric Yu | cbd8ca6215 | |
Eric Yu | fd185eafdf | |
Eric Yu | 8b9767a941 | |
Eric Yu | 74d552a323 |
|
@ -2,6 +2,7 @@
|
||||||
*.jou
|
*.jou
|
||||||
*.ini
|
*.ini
|
||||||
*.wlf
|
*.wlf
|
||||||
|
*.vstf
|
||||||
wlft*
|
wlft*
|
||||||
work
|
work
|
||||||
transcript
|
transcript
|
||||||
|
|
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -18,6 +18,7 @@ port (
|
||||||
cnt_time : in std_logic_vector(23 downto 0); -- Time since trigger.
|
cnt_time : in std_logic_vector(23 downto 0); -- Time since trigger.
|
||||||
|
|
||||||
busy : out std_logic; -- Status signal
|
busy : out std_logic; -- Status signal
|
||||||
|
-- TODO: Add another status signal to indicate any errors?
|
||||||
|
|
||||||
-- CPU interface
|
-- CPU interface
|
||||||
cpu_addr : in std_logic_vector(11 downto 0); -- Address input
|
cpu_addr : in std_logic_vector(11 downto 0); -- Address input
|
||||||
|
@ -91,8 +92,8 @@ signal sm_state : t_sm_state;
|
||||||
signal sm_wavedata : std_logic_vector(15 downto 0); -- Waveform RAM data
|
signal sm_wavedata : std_logic_vector(15 downto 0); -- Waveform RAM data
|
||||||
signal sm_wavedata_dv : std_logic; -- Signal to indicate that waveform RAM data is valid
|
signal sm_wavedata_dv : std_logic; -- Signal to indicate that waveform RAM data is valid
|
||||||
signal sm_busy : std_logic; -- Signal to indicate that s.m. is not idle
|
signal sm_busy : std_logic; -- Signal to indicate that s.m. is not idle
|
||||||
signal cnt_wave_len : std_logic_vector(C_BITS_ADDR_LENGTH - 1 downto 0); -- Counter used for incremnet/decrement wave table addresses
|
signal cnt_wave_len : unsigned(C_BITS_ADDR_LENGTH - 1 downto 0); -- Counter used for incremnet/decrement wave table addresses
|
||||||
signal cnt_wave_top : std_logic_vector(C_BITS_ADDR_TOP - 1 downto 0); -- Counter for the flat top of the waveform
|
signal cnt_wave_top : unsigned(C_BITS_ADDR_TOP - 1 downto 0); -- Counter for the flat top of the waveform
|
||||||
|
|
||||||
-- Misc signals
|
-- Misc signals
|
||||||
signal cpu_rdata_dv_e1 : std_logic;
|
signal cpu_rdata_dv_e1 : std_logic;
|
||||||
|
@ -111,9 +112,11 @@ signal pc : std_logic_vector(C_BITS_ADDR_PULSE - 1 downto 0);
|
||||||
-- 4. Flat-top 17-bit. [16:0]
|
-- 4. Flat-top 17-bit. [16:0]
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
signal reg_pulse_time : std_logic_vector(31 downto 0); -- first register which stores the pulse's start time
|
signal reg_pulse_time : std_logic_vector(31 downto 0); -- first register which stores the pulse's start time
|
||||||
signal reg_pulse_sizes : std_logic_vector(31 downto 0); -- second register which stores the pulse's length, the bit width should increase with the amount of addresses the wavetable has, and its start address
|
signal reg_wave_start_addr : std_logic_vector(C_BITS_ADDR_START -1 downto 0); -- the start address of the wavetable
|
||||||
signal reg_pulse_factors : std_logic_vector(31 downto 0); -- third register which stores the pulse's amplitude and time scale factors
|
signal reg_wave_length : unsigned( 9 downto 0); -- the length of the wavetable
|
||||||
signal reg_pulse_flattop : std_logic_vector(31 downto 0); -- fourth register which stores the pulse's flat top value
|
signal reg_scale_gain : unsigned(15 downto 0); -- scale factor for the gain, amplitude
|
||||||
|
signal reg_scale_time : unsigned(15 downto 0); -- scale factor for the time, length
|
||||||
|
signal reg_pulse_flattop : unsigned(C_BITS_ADDR_TOP - 1 downto 0); -- fourth register which stores the pulse's flat top value
|
||||||
|
|
||||||
-- Pipeline delays
|
-- Pipeline delays
|
||||||
signal start_d1 : std_logic;
|
signal start_d1 : std_logic;
|
||||||
|
@ -298,7 +301,8 @@ begin
|
||||||
-- or until the maximum counter time has been reached.
|
-- or until the maximum counter time has been reached.
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
pr_sm : process (reset, clk)
|
pr_sm : process (reset, clk)
|
||||||
|
-- Temp variables for waveform output
|
||||||
|
variable v_ram_waveform_doutb_multiplied : std_logic_vector(C_BITS_GAIN_FACTOR + 15 downto 0);
|
||||||
begin
|
begin
|
||||||
if (reset = '1') then
|
if (reset = '1') then
|
||||||
|
|
||||||
|
@ -309,10 +313,11 @@ begin
|
||||||
sm_wavedata <= (others=>'0');
|
sm_wavedata <= (others=>'0');
|
||||||
sm_wavedata_dv <= '0';
|
sm_wavedata_dv <= '0';
|
||||||
sm_busy <= '0';
|
sm_busy <= '0';
|
||||||
|
reg_wave_start_addr <= (others=>'0');
|
||||||
|
reg_wave_length <= (others=>'0');
|
||||||
|
reg_scale_gain <= (others=>'0');
|
||||||
|
reg_scale_time <= (others=>'0');
|
||||||
reg_pulse_time <= (others=>'0');
|
reg_pulse_time <= (others=>'0');
|
||||||
reg_pulse_sizes <= (others=>'0');
|
|
||||||
reg_pulse_factors <= (others=>'0');
|
|
||||||
reg_pulse_flattop <= (others=>'0');
|
reg_pulse_flattop <= (others=>'0');
|
||||||
|
|
||||||
pc <= (others=>'0');
|
pc <= (others=>'0');
|
||||||
|
@ -348,7 +353,7 @@ begin
|
||||||
sm_wavedata_dv <= '1';
|
sm_wavedata_dv <= '1';
|
||||||
sm_state <= S_IDLE;
|
sm_state <= S_IDLE;
|
||||||
end if;
|
end if;
|
||||||
sm_busy <= '0';
|
sm_busy <= '0';
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
-- Wait for rising edge of 'start'.
|
-- Wait for rising edge of 'start'.
|
||||||
|
@ -369,21 +374,16 @@ begin
|
||||||
when S_LOAD =>
|
when S_LOAD =>
|
||||||
-- TODO: Eric: does is needed here? or should be inside the if-else loops
|
-- TODO: Eric: does is needed here? or should be inside the if-else loops
|
||||||
-- Load the pulse channel RAM addresses and start the waveform output
|
-- Load the pulse channel RAM addresses and start the waveform output
|
||||||
sm_busy <= '1';
|
sm_busy <= '1';
|
||||||
-- Pipline the pulse definition address
|
-- Pipline the pulse definition address
|
||||||
|
|
||||||
-- TODO: is it better to make a counter to count the quarter or just mod 4?
|
|
||||||
-- TODO: maybe C-slow around the pulse ram to get it down to 1 cycle??
|
|
||||||
if (unsigned(ram_pulse_addrb) mod 4 = 0) then
|
if (unsigned(ram_pulse_addrb) mod 4 = 0) then
|
||||||
ram_pulse_addrb <= std_logic_vector(unsigned(pc) + 1);
|
ram_pulse_addrb <= std_logic_vector(unsigned(pc) + 1);
|
||||||
sm_state <= S_LOAD;
|
sm_state <= S_LOAD;
|
||||||
-- first quarter of the pulse definition, no register is loaded
|
-- first quarter of the pulse definition, no register is loaded
|
||||||
-- reg_pulse_time <= ram_pulse_doutb;
|
|
||||||
|
|
||||||
elsif (unsigned(ram_pulse_addrb) mod 4 = 1) then
|
elsif (unsigned(ram_pulse_addrb) mod 4 = 1) then
|
||||||
ram_pulse_addrb <= std_logic_vector(unsigned(pc) + 2);
|
ram_pulse_addrb <= std_logic_vector(unsigned(pc) + 2);
|
||||||
sm_state <= S_LOAD;
|
sm_state <= S_LOAD;
|
||||||
-- reg_pulse_sizes <= ram_pulse_doutb;
|
|
||||||
-- second quarter of the pulse definition, the start time is loaded
|
-- second quarter of the pulse definition, the start time is loaded
|
||||||
reg_pulse_time <= ram_pulse_doutb;
|
reg_pulse_time <= ram_pulse_doutb;
|
||||||
|
|
||||||
|
@ -391,19 +391,17 @@ begin
|
||||||
elsif (unsigned(ram_pulse_addrb) mod 4 = 2) then
|
elsif (unsigned(ram_pulse_addrb) mod 4 = 2) then
|
||||||
ram_pulse_addrb <= std_logic_vector(unsigned(pc) + 3);
|
ram_pulse_addrb <= std_logic_vector(unsigned(pc) + 3);
|
||||||
sm_state <= S_LOAD;
|
sm_state <= S_LOAD;
|
||||||
-- reg_pulse_factors <= ram_pulse_doutb;
|
|
||||||
-- third quarter of the pulse definition, the length and start address of the wavetable are loaded
|
-- third quarter of the pulse definition, the length and start address of the wavetable are loaded
|
||||||
reg_pulse_sizes <= ram_pulse_doutb;
|
reg_wave_start_addr <= ram_pulse_doutb(C_BITS_ADDR_START - 1 downto 0);
|
||||||
|
reg_wave_length <= unsigned(ram_pulse_doutb(25 downto 16)); -- TODO: make this a constant
|
||||||
|
|
||||||
elsif (unsigned(ram_pulse_addrb) mod 4 = 3) then
|
elsif (unsigned(ram_pulse_addrb) mod 4 = 3) then
|
||||||
-- ram_pulse_addrb <= std_logic_vector(unsigned(pc) + 4);
|
|
||||||
sm_state <= S_WAIT; -- address is on the forth word of the entry, the loading process is complete. Moving onto the next state
|
sm_state <= S_WAIT; -- address is on the forth word of the entry, the loading process is complete. Moving onto the next state
|
||||||
-- hold the last pulse definition address as it will be used in the next state
|
-- hold the last pulse definition address as it will be used in the next state
|
||||||
-- reg_pulse_flattop <= ram_pulse_doutb;
|
|
||||||
pc <= std_logic_vector(unsigned(pc) + C_PC_INCR); -- incremnet the pulse counter and start waiting to output the wave
|
pc <= std_logic_vector(unsigned(pc) + C_PC_INCR); -- incremnet the pulse counter and start waiting to output the wave
|
||||||
-- forth quarter of the pulse definition, the scale factors are loaded
|
-- forth quarter of the pulse definition, the scale factors are loaded
|
||||||
reg_pulse_factors <= ram_pulse_doutb;
|
reg_scale_gain <= unsigned(ram_pulse_doutb(31 downto 16));
|
||||||
|
reg_scale_time <= unsigned(ram_pulse_doutb(15 downto 0));
|
||||||
|
|
||||||
|
|
||||||
end if;
|
end if;
|
||||||
|
@ -420,12 +418,12 @@ begin
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
when S_WAIT =>
|
when S_WAIT =>
|
||||||
-- read the last word of the pulse definition, the flat top value
|
-- read the last word of the pulse definition, the flat top value
|
||||||
reg_pulse_flattop <= ram_pulse_doutb;
|
reg_pulse_flattop <= unsigned(ram_pulse_doutb(C_BITS_ADDR_TOP - 1 downto 0));
|
||||||
-- Start to output wave and increment pulse position RAM address
|
-- Start to output wave and increment pulse position RAM address
|
||||||
if (reg_pulse_time(C_START_TIME - 1 downto 0) = cnt_time) then
|
if (reg_pulse_time(C_START_TIME - 1 downto 0) = cnt_time) then
|
||||||
sm_state <= S_WAVE_UP;
|
sm_state <= S_WAVE_UP;
|
||||||
-- set the wavetable's address to the starting address defined from the pulse ram
|
-- set the wavetable's address to the starting address defined from the pulse ram
|
||||||
ram_waveform_addrb <= reg_pulse_sizes(C_BITS_ADDR_START - 1 downto 0);
|
ram_waveform_addrb <= reg_wave_start_addr;
|
||||||
-- reset the wave lenth counter
|
-- reset the wave lenth counter
|
||||||
cnt_wave_len <= (others=>'0');
|
cnt_wave_len <= (others=>'0');
|
||||||
elsif (cnt_time = X"FFFFFF") then
|
elsif (cnt_time = X"FFFFFF") then
|
||||||
|
@ -440,18 +438,32 @@ begin
|
||||||
when S_WAVE_UP =>
|
when S_WAVE_UP =>
|
||||||
-- Check if is end of rise of the waveform, and hold the address
|
-- Check if is end of rise of the waveform, and hold the address
|
||||||
-- TODO: convert the numbers below to constaint. right now just make sure I'm not confused
|
-- TODO: convert the numbers below to constaint. right now just make sure I'm not confused
|
||||||
if (cnt_wave_len = reg_pulse_sizes(25 downto 16)) then
|
if (cnt_wave_len = reg_wave_length) then
|
||||||
sm_state <= S_WAVE_FLAT;
|
-- skip the flat top state if the flat top value is zero
|
||||||
-- reset counters for transitions
|
if (reg_pulse_flattop = 0) then
|
||||||
cnt_wave_len <= (others=>'0');
|
sm_state <= S_WAVE_DOWN;
|
||||||
cnt_wave_top <= (others=>'0');
|
-- reset the counter for the next transition
|
||||||
|
cnt_wave_len <= (others=>'0');
|
||||||
|
else
|
||||||
|
sm_state <= S_WAVE_FLAT;
|
||||||
|
-- reset the counter for the next transition
|
||||||
|
cnt_wave_len <= (others=>'0');
|
||||||
|
cnt_wave_top <= (others=>'0');
|
||||||
|
end if;
|
||||||
|
-- -- reset counters for transitions
|
||||||
|
-- cnt_wave_len <= (others=>'0');
|
||||||
|
-- cnt_wave_top <= (others=>'0');
|
||||||
else
|
else
|
||||||
cnt_wave_len <= std_logic_vector(unsigned(cnt_wave_len) + 1);
|
cnt_wave_len <= cnt_wave_len + 1;
|
||||||
ram_waveform_addrb <= std_logic_vector(unsigned(ram_waveform_addrb) + 1);
|
ram_waveform_addrb <= std_logic_vector(unsigned(ram_waveform_addrb) + 1);
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
sm_wavedata <= ram_waveform_doutb;
|
-- sm_wavedata <= std_logic_vector(unsigned(ram_waveform_doutb) * reg_scale_gain)(31 downto 16);
|
||||||
sm_wavedata_dv <= '1';
|
-- Modelsim Cannot synthesize this above line, so we *have to* seperate them into two lines
|
||||||
|
-- # ** Error: Prefix of slice name cannot be type conversion (STD_LOGIC_VECTOR) expression.
|
||||||
|
v_ram_waveform_doutb_multiplied := std_logic_vector(unsigned(ram_waveform_doutb) * reg_scale_gain);
|
||||||
|
sm_wavedata <= v_ram_waveform_doutb_multiplied(30 downto 15);
|
||||||
|
sm_wavedata_dv <= '1';
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
-- Hold the last address and output its data
|
-- Hold the last address and output its data
|
||||||
|
@ -459,15 +471,16 @@ begin
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
when S_WAVE_FLAT =>
|
when S_WAVE_FLAT =>
|
||||||
-- count the 17-bit flat top, if the counter reaches the flat top value, then go to the next state
|
-- count the 17-bit flat top, if the counter reaches the flat top value, then go to the next state
|
||||||
if (cnt_wave_top = reg_pulse_flattop(C_BITS_ADDR_TOP - 1 downto 0)) then
|
if (cnt_wave_top = reg_pulse_flattop) then
|
||||||
sm_state <= S_WAVE_DOWN;
|
sm_state <= S_WAVE_DOWN;
|
||||||
-- reset the counter for the next transition
|
-- reset the counter for the next transition
|
||||||
cnt_wave_top <= (others=>'0');
|
cnt_wave_top <= (others=>'0');
|
||||||
else
|
else
|
||||||
cnt_wave_top <= std_logic_vector(unsigned(cnt_wave_top) + 1);
|
cnt_wave_top <= cnt_wave_top + 1;
|
||||||
end if;
|
end if;
|
||||||
sm_wavedata <= ram_waveform_doutb;
|
v_ram_waveform_doutb_multiplied := std_logic_vector(unsigned(ram_waveform_doutb) * reg_scale_gain);
|
||||||
sm_wavedata_dv <= '1';
|
sm_wavedata <= v_ram_waveform_doutb_multiplied(30 downto 15);
|
||||||
|
sm_wavedata_dv <= '1';
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
-- Output the falling edge of a waveform
|
-- Output the falling edge of a waveform
|
||||||
|
@ -477,7 +490,7 @@ begin
|
||||||
|
|
||||||
-- End of waveform?
|
-- End of waveform?
|
||||||
-- TODO: convert the numbers below to constaint. right now just make sure I'm not confused
|
-- TODO: convert the numbers below to constaint. right now just make sure I'm not confused
|
||||||
if (cnt_wave_len = reg_pulse_sizes(25 downto 16)) then
|
if (cnt_wave_len = reg_wave_length) then
|
||||||
|
|
||||||
-- If the end of the pulse table is reached then go to idle, increment pulse address for the next waveform otherwise
|
-- If the end of the pulse table is reached then go to idle, increment pulse address for the next waveform otherwise
|
||||||
if (ram_pulse_addrb = std_logic_vector(to_unsigned(C_LEN_PULSE-1, C_BITS_ADDR_PULSE))) then
|
if (ram_pulse_addrb = std_logic_vector(to_unsigned(C_LEN_PULSE-1, C_BITS_ADDR_PULSE))) then
|
||||||
|
@ -494,20 +507,31 @@ begin
|
||||||
|
|
||||||
-- Output waveform from RAM with decremented address
|
-- Output waveform from RAM with decremented address
|
||||||
else
|
else
|
||||||
cnt_wave_len <= std_logic_vector(unsigned(cnt_wave_len) + 1);
|
cnt_wave_len <= cnt_wave_len + 1;
|
||||||
ram_waveform_addrb <= std_logic_vector(unsigned(ram_waveform_addrb) - 1);
|
ram_waveform_addrb <= std_logic_vector(unsigned(ram_waveform_addrb) - 1);
|
||||||
end if;
|
end if;
|
||||||
sm_wavedata <= ram_waveform_doutb;
|
v_ram_waveform_doutb_multiplied := std_logic_vector(unsigned(ram_waveform_doutb) * reg_scale_gain);
|
||||||
sm_wavedata_dv <= '1';
|
sm_wavedata <= v_ram_waveform_doutb_multiplied(30 downto 15);
|
||||||
|
sm_wavedata_dv <= '1';
|
||||||
|
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
-- Default
|
-- Default
|
||||||
------------------------------------------------------------------------
|
------------------------------------------------------------------------
|
||||||
when others =>
|
when others =>
|
||||||
sm_state <= S_IDLE;
|
sm_state <= S_IDLE;
|
||||||
|
|
||||||
end case;
|
end case;
|
||||||
end if;
|
end if;
|
||||||
end process;
|
end process;
|
||||||
|
|
||||||
|
-- AXI-Stream output.
|
||||||
|
-- TBD: This should come from a FIFO
|
||||||
|
-- TODO: the bits are not correct, should be top bits (C_BITS_GAIN_FACTOR + 16 downto C_BITS_GAIN_FACTOR), but for now just make it this way so modelsim can simulate
|
||||||
|
-- TODO: apply scaling factor to the output
|
||||||
|
-- TODO: data valid bit is not aligned with the data
|
||||||
|
axis_tdata <= sm_wavedata; -- axi stream output data, this output should be multiplied by the gain factor, then take the top 16 bits
|
||||||
|
axis_tvalid <= sm_wavedata_dv; -- axi_stream output data valid
|
||||||
|
|
||||||
|
-- TBD : Generate in state machine?
|
||||||
|
axis_tlast <= '0'; -- axi_stream output last
|
||||||
end channel;
|
end channel;
|
|
@ -0,0 +1,35 @@
|
||||||
|
----------------------------------------------------------------------------------------
|
||||||
|
-- Project : qlaser FPGA
|
||||||
|
-- File : qlaser_dacs_pulse_channel.vhd
|
||||||
|
-- Description : Pulse Channel package file specifying constants
|
||||||
|
-- Author : eyhc
|
||||||
|
----------------------------------------------------------------------------------------
|
||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
|
||||||
|
package qlaser_dacs_pulse_channel_pkg is
|
||||||
|
-- Constants declearations
|
||||||
|
constant C_RAM_SELECT : integer := 11; -- Select bit for which RAM for CPU read/write
|
||||||
|
-- constant C_NUM_PULSE : integer := 16; -- Number of output data values from pulse RAM (16x24-bit)
|
||||||
|
|
||||||
|
constant C_START_TIME : integer := 24; -- Start time for pulse generation
|
||||||
|
constant C_BITS_ADDR_START : integer := 12; -- Number of bits for starting address
|
||||||
|
constant C_BITS_ADDR_LENGTH : integer := 10; -- Number of bits for length address used by an edge of a pulse
|
||||||
|
constant C_BITS_GAIN_FACTOR : integer := 16; -- Number of bits in gain table
|
||||||
|
constant C_BITS_TIME_FACTOR : integer := 16; -- Number of bits in time table
|
||||||
|
constant C_BITS_TIME_INT : integer := 14; -- Starting bit for time integer part of the time factor, counting from MSB
|
||||||
|
constant C_BITS_TIME_FRAC : integer := 5; -- Starting bit for time fractional part of the time factor, counting from MSB
|
||||||
|
constant C_BITS_ADDR_TOP : integer := 17; -- Number of bits for the "flat top", the top of the pulse
|
||||||
|
|
||||||
|
constant C_LENGTH_WAVEFORM : integer := 4096; -- Number of output data values from waveform RAM (4kx16-bit)
|
||||||
|
constant C_BITS_ADDR_WAVE : integer := 16; -- Number of bits in address for waveform RAM
|
||||||
|
|
||||||
|
constant C_BITS_ADDR_PULSE : integer := 10; -- Number of bits in address for pulse definition RAM
|
||||||
|
constant C_LEN_PULSE : integer := 2**C_BITS_ADDR_PULSE; -- Numbers of address for pulse definition RAM
|
||||||
|
constant C_PC_INCR : integer := 4;
|
||||||
|
-- Width of pulse counter increment
|
||||||
|
|
||||||
|
|
||||||
|
constant BIT_FRAC : integer := 4; -- Define the number of fractional bits
|
||||||
|
constant BIT_FRAC_GAIN : integer := C_BITS_GAIN_FACTOR - 1; -- Define the number of fractional bits of the gain
|
||||||
|
end package qlaser_dacs_pulse_channel_pkg;
|
|
@ -14,6 +14,7 @@ use ieee.std_logic_1164.all;
|
||||||
use std.textio.all;
|
use std.textio.all;
|
||||||
|
|
||||||
use work.std_iopak.all;
|
use work.std_iopak.all;
|
||||||
|
use work.qlaser_dacs_pulse_channel_pkg.all;
|
||||||
|
|
||||||
|
|
||||||
entity tb_cpubus_dacs_pulse_channel is
|
entity tb_cpubus_dacs_pulse_channel is
|
||||||
|
@ -131,13 +132,12 @@ variable slv_wavetopwidth : std_logic_vector(16 downto 0); -- For 17-bit numb
|
||||||
|
|
||||||
-- constant ADR_PULSE_DEF : integer := to_integer(unsigned(X"?????")); -- Use address of pulse definition RAM from qlaser_pkg
|
-- constant ADR_PULSE_DEF : integer := to_integer(unsigned(X"?????")); -- Use address of pulse definition RAM from qlaser_pkg
|
||||||
-- Define the number of fractional bits
|
-- Define the number of fractional bits
|
||||||
constant BIT_FRAC : integer := 4; -- TODO: this should be defined in qlaser_pkg
|
|
||||||
begin
|
begin
|
||||||
|
|
||||||
-- Convert each field into its std_logic_vector equivalent
|
-- Convert each field into its std_logic_vector equivalent
|
||||||
slv_pulsetime := std_logic_vector(to_unsigned(pulsetime, 24));
|
slv_pulsetime := std_logic_vector(to_unsigned(pulsetime, 24));
|
||||||
slv_timefactor := std_logic_vector(to_unsigned(integer(timefactor * real(2**BIT_FRAC)), 16)); -- Convert real to std_logic_vector keeping the fractional part
|
slv_timefactor := std_logic_vector(to_unsigned(integer(timefactor * real(2**BIT_FRAC)), 16)); -- Convert real to std_logic_vector keeping the fractional part
|
||||||
slv_gainfactor := std_logic_vector(to_unsigned(integer(gainfactor * real(2**BIT_FRAC)), 16)); -- Convert real to std_logic_vector keeping the fractional part
|
slv_gainfactor := std_logic_vector(to_unsigned(integer(gainfactor * real(2**BIT_FRAC_GAIN)), 16)); -- Convert real to std_logic_vector keeping the fractional part
|
||||||
slv_wavestartaddr := std_logic_vector(to_unsigned(wavestartaddr, 12));
|
slv_wavestartaddr := std_logic_vector(to_unsigned(wavestartaddr, 12));
|
||||||
slv_wavesteps := std_logic_vector(to_unsigned(wavesteps, 10));
|
slv_wavesteps := std_logic_vector(to_unsigned(wavesteps, 10));
|
||||||
slv_wavetopwidth := std_logic_vector(to_unsigned(wavetopwidth, 17));
|
slv_wavetopwidth := std_logic_vector(to_unsigned(wavetopwidth, 17));
|
||||||
|
@ -146,8 +146,8 @@ begin
|
||||||
--etc, etc.
|
--etc, etc.
|
||||||
-- 4 writes. (Address is an integer)
|
-- 4 writes. (Address is an integer)
|
||||||
cpu_write(clk, ADR_RAM_PULSE+num_entry , x"00" & slv_pulsetime, cpu_sel, cpu_wr, cpu_addr, cpu_wdata);
|
cpu_write(clk, ADR_RAM_PULSE+num_entry , x"00" & slv_pulsetime, cpu_sel, cpu_wr, cpu_addr, cpu_wdata);
|
||||||
cpu_write(clk, ADR_RAM_PULSE+(num_entry+1) , "00" & x"00" & slv_wavesteps & slv_wavestartaddr, cpu_sel, cpu_wr, cpu_addr, cpu_wdata);
|
cpu_write(clk, ADR_RAM_PULSE+(num_entry+1) , "00" & x"0" & slv_wavesteps & x"0" & slv_wavestartaddr, cpu_sel, cpu_wr, cpu_addr, cpu_wdata);
|
||||||
cpu_write(clk, ADR_RAM_PULSE+(num_entry+2) , slv_timefactor & slv_gainfactor, cpu_sel, cpu_wr, cpu_addr, cpu_wdata);
|
cpu_write(clk, ADR_RAM_PULSE+(num_entry+2) , slv_gainfactor & slv_timefactor, cpu_sel, cpu_wr, cpu_addr, cpu_wdata);
|
||||||
cpu_write(clk, ADR_RAM_PULSE+(num_entry+3) , "0000000" & x"00" & slv_wavetopwidth, cpu_sel, cpu_wr, cpu_addr, cpu_wdata);
|
cpu_write(clk, ADR_RAM_PULSE+(num_entry+3) , "0000000" & x"00" & slv_wavetopwidth, cpu_sel, cpu_wr, cpu_addr, cpu_wdata);
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
@ -224,13 +224,12 @@ variable slv_wavetopwidth : std_logic_vector(16 downto 0); -- For 17-bit numb
|
||||||
|
|
||||||
-- constant ADR_PULSE_DEF : integer := to_integer(unsigned(X"?????")); -- Use address of pulse definition RAM from qlaser_pkg
|
-- constant ADR_PULSE_DEF : integer := to_integer(unsigned(X"?????")); -- Use address of pulse definition RAM from qlaser_pkg
|
||||||
-- Define the number of fractional bits
|
-- Define the number of fractional bits
|
||||||
constant BIT_FRAC : integer := 4; -- TODO: this should be defined in qlaser_pkg
|
|
||||||
begin
|
begin
|
||||||
|
|
||||||
-- Convert each field into its std_logic_vector equivalent
|
-- Convert each field into its std_logic_vector equivalent
|
||||||
slv_pulsetime := std_logic_vector(to_unsigned(pulsetime, 24));
|
slv_pulsetime := std_logic_vector(to_unsigned(pulsetime, 24));
|
||||||
slv_timefactor := std_logic_vector(to_unsigned(integer(timefactor * real(2**BIT_FRAC)), 16)); -- Convert real to std_logic_vector keeping the fractional part
|
slv_timefactor := std_logic_vector(to_unsigned(integer(timefactor * real(2**BIT_FRAC)), 16)); -- Convert real to std_logic_vector keeping the fractional part
|
||||||
slv_gainfactor := std_logic_vector(to_unsigned(integer(gainfactor * real(2**BIT_FRAC)), 16)); -- Convert real to std_logic_vector keeping the fractional part
|
slv_gainfactor := std_logic_vector(to_unsigned(integer(gainfactor * real(2**BIT_FRAC_GAIN)), 16)); -- Convert real to std_logic_vector keeping the fractional part
|
||||||
slv_wavestartaddr := std_logic_vector(to_unsigned(wavestartaddr, 12));
|
slv_wavestartaddr := std_logic_vector(to_unsigned(wavestartaddr, 12));
|
||||||
slv_wavesteps := std_logic_vector(to_unsigned(wavesteps, 10));
|
slv_wavesteps := std_logic_vector(to_unsigned(wavesteps, 10));
|
||||||
slv_wavetopwidth := std_logic_vector(to_unsigned(wavetopwidth, 17));
|
slv_wavetopwidth := std_logic_vector(to_unsigned(wavetopwidth, 17));
|
||||||
|
@ -240,7 +239,7 @@ begin
|
||||||
-- 4 writes. (Address is an integer)
|
-- 4 writes. (Address is an integer)
|
||||||
cpu_read(clk, ADR_RAM_PULSE+num_entry, x"00" & slv_pulsetime, cpu_sel, cpu_wr, cpu_addr, cpu_wdata, cpu_rdata, cpu_rdata_dv);
|
cpu_read(clk, ADR_RAM_PULSE+num_entry, x"00" & slv_pulsetime, cpu_sel, cpu_wr, cpu_addr, cpu_wdata, cpu_rdata, cpu_rdata_dv);
|
||||||
cpu_read(clk, ADR_RAM_PULSE+(num_entry+1), "00" & x"00" & slv_wavesteps & slv_wavestartaddr, cpu_sel, cpu_wr, cpu_addr, cpu_wdata, cpu_rdata, cpu_rdata_dv);
|
cpu_read(clk, ADR_RAM_PULSE+(num_entry+1), "00" & x"00" & slv_wavesteps & slv_wavestartaddr, cpu_sel, cpu_wr, cpu_addr, cpu_wdata, cpu_rdata, cpu_rdata_dv);
|
||||||
cpu_read(clk, ADR_RAM_PULSE+(num_entry+2), slv_timefactor & slv_gainfactor, cpu_sel, cpu_wr, cpu_addr, cpu_wdata, cpu_rdata, cpu_rdata_dv);
|
cpu_read(clk, ADR_RAM_PULSE+(num_entry+2), slv_gainfactor & slv_timefactor, cpu_sel, cpu_wr, cpu_addr, cpu_wdata, cpu_rdata, cpu_rdata_dv);
|
||||||
cpu_read(clk, ADR_RAM_PULSE+(num_entry+3), "0000000" & x"00" & slv_wavetopwidth, cpu_sel, cpu_wr, cpu_addr, cpu_wdata, cpu_rdata, cpu_rdata_dv);
|
cpu_read(clk, ADR_RAM_PULSE+(num_entry+3), "0000000" & x"00" & slv_wavetopwidth, cpu_sel, cpu_wr, cpu_addr, cpu_wdata, cpu_rdata, cpu_rdata_dv);
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
@ -325,8 +324,19 @@ begin
|
||||||
-- Reset and drive CPU bus
|
-- Reset and drive CPU bus
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
pr_main : process
|
pr_main : process
|
||||||
variable v_ndata32 : integer := 0;
|
variable v_ndata32 : integer := 0;
|
||||||
variable v_ndata16 : integer := 0;
|
variable v_ndata16 : integer := 0;
|
||||||
|
|
||||||
|
-- "global" variables for base definitions of each pulses, all pulses are based on these but scaled/offset a bit
|
||||||
|
variable v_pulseaddr : integer := 0; -- manually set the pulse address, 0 to 255
|
||||||
|
variable v_waveaddr : integer := 0; -- manually set the wave address, 0 to 2047
|
||||||
|
variable v_pulsetime : integer := 0; -- For 24-bit pulse time
|
||||||
|
variable v_timefactor : real := 0.0; -- For 16-bit fixed point timestep
|
||||||
|
variable v_gainfactor : real := 0.0; -- For 16-bit fixed point gain
|
||||||
|
variable v_wavestartaddr : integer := 0; -- For 12-bit address i.e. 1024 point waveform RAM
|
||||||
|
variable v_wavesteps : integer := 0; -- For 10-bit number of steps i.e. 0 = 1 step, X"3FF" = 1024 points
|
||||||
|
variable v_wavetopwidth : integer := 0; -- For 17-bit number of clock cycles in top of waveform
|
||||||
|
|
||||||
begin
|
begin
|
||||||
-- Reset
|
-- Reset
|
||||||
reset <= '1';
|
reset <= '1';
|
||||||
|
@ -355,9 +365,41 @@ begin
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
v_ndata32 := 128; -- Time for first pulse
|
v_ndata32 := 128; -- Time for first pulse
|
||||||
cpu_print_msg("Load pulse RAM");
|
cpu_print_msg("Load pulse RAM");
|
||||||
for NADDR in 0 to 255 loop
|
-- for NADDR in 0 to 255 loop
|
||||||
cpu_write_pulsedef(clk, NADDR*4, v_ndata32 + (NADDR*(1024+32)), 1.0, 1.0, 0, NADDR*32, 128, cpu_sel, cpu_wr, cpu_addr, cpu_wdata);
|
-- -- TODO: In the real setting should we have the python script to check those parameters to make sure they are valid and non-overlapping?
|
||||||
end loop;
|
-- v_pulsetime := v_ndata32 + (NADDR*(4096+32)); -- todo: what is this math doing?
|
||||||
|
-- v_timefactor := 1.0;
|
||||||
|
-- v_gainfactor := 1.0/real(NADDR + 1);
|
||||||
|
-- v_wavestartaddr := 0; -- TODO: EricToGeoff/Sara: I assume we want starting address of each wave to be different and non-overlapping, right?
|
||||||
|
-- v_wavesteps := NADDR*32;
|
||||||
|
-- v_wavetopwidth := NADDR;
|
||||||
|
-- -- cpu_write_pulsedef(clk, NADDR*4, v_ndata32 + (NADDR*(1024+32)), 1.0, 1.0, 0, NADDR*32, 128, cpu_sel, cpu_wr, cpu_addr, cpu_wdata);
|
||||||
|
-- cpu_write_pulsedef(clk, NADDR*4, v_pulsetime, v_timefactor, v_gainfactor, v_wavestartaddr, v_wavesteps, v_wavetopwidth, cpu_sel, cpu_wr, cpu_addr, cpu_wdata);
|
||||||
|
-- end loop;
|
||||||
|
|
||||||
|
----------------------------------------------------------------
|
||||||
|
-- Load pulse RAM with a series of pulse start times MANUALLY
|
||||||
|
---------------------------------------------------------------
|
||||||
|
v_pulseaddr := 0;
|
||||||
|
v_pulsetime := 7;
|
||||||
|
v_timefactor := 1.0;
|
||||||
|
v_gainfactor := 1.0;
|
||||||
|
v_wavestartaddr := 1; -- TODO: EricToGeoff/Sara: I assume we want starting address of each wave to be different and non-overlapping, right?
|
||||||
|
v_wavesteps := 4;
|
||||||
|
v_wavetopwidth := 1;
|
||||||
|
cpu_write_pulsedef(clk, v_pulseaddr*4, v_pulsetime, v_timefactor, v_gainfactor, v_wavestartaddr, v_wavesteps, v_wavetopwidth, cpu_sel, cpu_wr, cpu_addr, cpu_wdata);
|
||||||
|
|
||||||
|
|
||||||
|
v_pulseaddr := 1;
|
||||||
|
v_pulsetime := 69;
|
||||||
|
v_timefactor := 1.0;
|
||||||
|
v_gainfactor := 1.0;
|
||||||
|
v_wavestartaddr := 4; -- TODO: EricToGeoff/Sara: I assume we want starting address of each wave to be different and non-overlapping, right?
|
||||||
|
v_wavesteps := 6;
|
||||||
|
v_wavetopwidth := 9;
|
||||||
|
cpu_write_pulsedef(clk, v_pulseaddr*4, v_pulsetime, v_timefactor, v_gainfactor, v_wavestartaddr, v_wavesteps, v_wavetopwidth, cpu_sel, cpu_wr, cpu_addr, cpu_wdata);
|
||||||
|
|
||||||
|
|
||||||
cpu_print_msg("Pulse RAM loaded");
|
cpu_print_msg("Pulse RAM loaded");
|
||||||
clk_delay(20);
|
clk_delay(20);
|
||||||
|
|
||||||
|
@ -368,36 +410,41 @@ begin
|
||||||
cpu_print_msg("Load waveform RAM");
|
cpu_print_msg("Load waveform RAM");
|
||||||
v_ndata16 := 1; -- first waveform value
|
v_ndata16 := 1; -- first waveform value
|
||||||
for NADDR in 0 to 2047 loop
|
for NADDR in 0 to 2047 loop
|
||||||
v_ndata32 := (((v_ndata16+1) * 65536) + v_ndata16);
|
v_ndata32 := (((v_ndata16) * 2**C_BITS_ADDR_WAVE) + (v_ndata16 - 1)); -- Write two 16-bit values with each write
|
||||||
cpu_write(clk, (ADR_RAM_WAVE + NADDR) , v_ndata32, cpu_sel, cpu_wr, cpu_addr, cpu_wdata);
|
cpu_write(clk, (ADR_RAM_WAVE + NADDR) , v_ndata32, cpu_sel, cpu_wr, cpu_addr, cpu_wdata);
|
||||||
v_ndata16 := v_ndata16 + 2;
|
v_ndata16 := v_ndata16 + 2;
|
||||||
end loop;
|
end loop;
|
||||||
cpu_print_msg("Waveform RAM loaded");
|
|
||||||
clk_delay(20);
|
|
||||||
|
|
||||||
|
|
||||||
----------------------------------------------------------------
|
|
||||||
-- Read back Pulse RAM.
|
|
||||||
----------------------------------------------------------------
|
|
||||||
v_ndata32 := 128; -- Time for first pulse
|
|
||||||
for NADDR in 0 to 255 loop
|
|
||||||
cpu_read_pulsedef(clk, NADDR*4, v_ndata32 + (NADDR*(1024+32)), 1.0, 1.0, 0, NADDR*32, 128, cpu_sel, cpu_wr, cpu_addr, cpu_wdata);
|
|
||||||
end loop;
|
|
||||||
clk_delay(20);
|
|
||||||
|
|
||||||
----------------------------------------------------------------
|
|
||||||
-- Read back Waveform RAM
|
|
||||||
----------------------------------------------------------------
|
|
||||||
v_ndata16 := 1; -- first waveform value
|
|
||||||
for NADDR in 0 to 2047 loop
|
|
||||||
v_ndata32 := (((v_ndata16+1) * 65536) + v_ndata16);
|
|
||||||
cpu_read (clk, ADR_RAM_WAVE + NADDR , std_logic_vector(to_unsigned(v_ndata32, 32)) , cpu_sel, cpu_wr, cpu_addr, cpu_wdata, cpu_rdata, cpu_rdata_dv);
|
|
||||||
v_ndata16 := v_ndata16 + 2;
|
|
||||||
end loop;
|
|
||||||
|
|
||||||
-- Done reg write/read check
|
|
||||||
cpu_print_msg("RAM readback completed");
|
-- ----------------------------------------------------------------
|
||||||
clk_delay(20);
|
-- -- Read back Pulse RAM.
|
||||||
|
-- -- Comment out if not needed to check CPU R/W
|
||||||
|
-- ----------------------------------------------------------------
|
||||||
|
-- v_ndata32 := 128; -- Time for first pulse
|
||||||
|
-- for NADDR in 0 to 255 loop
|
||||||
|
-- v_pulsetime := v_ndata32 + (NADDR*(1024+32));
|
||||||
|
-- v_timefactor := 1.0;
|
||||||
|
-- v_gainfactor := 1.0;
|
||||||
|
-- v_wavestartaddr := 0;
|
||||||
|
-- v_wavesteps := NADDR*32;
|
||||||
|
-- v_wavetopwidth := 0;
|
||||||
|
-- cpu_read_pulsedef(clk, NADDR*4, v_pulsetime, v_timefactor, v_gainfactor, v_wavestartaddr, v_wavesteps, v_wavetopwidth, cpu_sel, cpu_wr, cpu_addr, cpu_wdata);
|
||||||
|
-- end loop;
|
||||||
|
-- clk_delay(20);
|
||||||
|
|
||||||
|
-- ----------------------------------------------------------------
|
||||||
|
-- -- Read back Waveform RAM
|
||||||
|
-- ----------------------------------------------------------------
|
||||||
|
-- v_ndata16 := 1; -- first waveform value
|
||||||
|
-- for NADDR in 0 to 2047 loop
|
||||||
|
-- v_ndata32 := (((v_ndata16) * 2**C_BITS_ADDR_WAVE) + (v_ndata16 - 1));
|
||||||
|
-- cpu_read (clk, ADR_RAM_WAVE + NADDR , std_logic_vector(to_unsigned(v_ndata32, 32)) , cpu_sel, cpu_wr, cpu_addr, cpu_wdata, cpu_rdata, cpu_rdata_dv);
|
||||||
|
-- v_ndata16 := v_ndata16 + 2;
|
||||||
|
-- end loop;
|
||||||
|
|
||||||
|
-- -- Done reg write/read check
|
||||||
|
-- cpu_print_msg("RAM readback completed");
|
||||||
|
-- clk_delay(20);
|
||||||
|
|
||||||
|
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
|
@ -408,8 +455,9 @@ begin
|
||||||
clk_delay(5);
|
clk_delay(5);
|
||||||
start <= '0';
|
start <= '0';
|
||||||
|
|
||||||
|
-- TODO: we may need to modify the for loop to make sure the simulation time is long enough to cover all the pulses
|
||||||
-- Wait for cnt_time to reach last pulse start time + waveform size
|
-- Wait for cnt_time to reach last pulse start time + waveform size
|
||||||
for NCNT in 1 to (128 + 16*(1024+32)+ 1024) loop
|
for NCNT in 1 to (128 + 256*(1024+32)+ 4096) loop -- TODO: EricToGeoff/Sara: in the real settings do we have a constant amount of time or the total time also vary? if so, how much?
|
||||||
cnt_time <= std_logic_vector(unsigned(cnt_time) + 1);
|
cnt_time <= std_logic_vector(unsigned(cnt_time) + 1);
|
||||||
clk_delay(0);
|
clk_delay(0);
|
||||||
end loop;
|
end loop;
|
||||||
|
|
|
@ -0,0 +1,530 @@
|
||||||
|
---------------------------------------------------------------
|
||||||
|
-- File : qlaser_dacs_pulse_channel.vhd
|
||||||
|
-- Description : Single channel of pulse output
|
||||||
|
----------------------------------------------------------------
|
||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
use work.qlaser_pkg.all;
|
||||||
|
use work.qlaser_dacs_pulse_channel_pkg.all;
|
||||||
|
|
||||||
|
entity qlaser_dacs_pulse_channel is
|
||||||
|
port (
|
||||||
|
reset : in std_logic;
|
||||||
|
clk : in std_logic;
|
||||||
|
|
||||||
|
enable : in std_logic; -- Set when DAC interface is running
|
||||||
|
start : in std_logic; -- Set when pulse generation sequence begins (trigger)
|
||||||
|
cnt_time : in std_logic_vector(23 downto 0); -- Time since trigger.
|
||||||
|
|
||||||
|
busy : out std_logic; -- Status signal
|
||||||
|
|
||||||
|
-- CPU interface
|
||||||
|
cpu_addr : in std_logic_vector(11 downto 0); -- Address input
|
||||||
|
cpu_wdata : in std_logic_vector(31 downto 0); -- Data input
|
||||||
|
cpu_wr : in std_logic; -- Write enable
|
||||||
|
cpu_sel : in std_logic; -- Block select
|
||||||
|
cpu_rdata : out std_logic_vector(31 downto 0); -- Data output
|
||||||
|
cpu_rdata_dv : out std_logic; -- Acknowledge output
|
||||||
|
|
||||||
|
-- AXI-stream output
|
||||||
|
axis_tready : in std_logic; -- axi_stream ready from downstream module
|
||||||
|
axis_tdata : out std_logic_vector(15 downto 0); -- axi stream output data
|
||||||
|
axis_tvalid : out std_logic; -- axi_stream output data valid
|
||||||
|
axis_tlast : out std_logic -- axi_stream output set on last data
|
||||||
|
);
|
||||||
|
end entity;
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
-- Single channel pulse generator with two RAMs
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
architecture channel of qlaser_dacs_pulse_channel is
|
||||||
|
-- Signal declarations for pulse RAM
|
||||||
|
signal ram_pulse_we : std_logic_vector( 0 downto 0); -- Write enable for pulse RAM
|
||||||
|
signal ram_pulse_addra : std_logic_vector( 9 downto 0); -- Address for pulse RAM
|
||||||
|
signal ram_pulse_dina : std_logic_vector(31 downto 0); -- Data for pulse RAM
|
||||||
|
signal ram_pulse_douta : std_logic_vector(31 downto 0); -- Data out from pulse RAM
|
||||||
|
signal ram_pulse_addrb : std_logic_vector( 9 downto 0); -- Address for pulse RAM
|
||||||
|
signal ram_pulse_doutb : std_logic_vector(31 downto 0); -- Data out from pulse RAM
|
||||||
|
|
||||||
|
-- Signal declarations for waveform RAM
|
||||||
|
signal ram_waveform_wea : std_logic_vector( 0 downto 0); -- Write enable for waveform RAM
|
||||||
|
signal ram_waveform_addra : std_logic_vector(10 downto 0); -- Address for waveform RAM
|
||||||
|
signal ram_waveform_dina : std_logic_vector(31 downto 0); -- Data for waveform RAM
|
||||||
|
signal ram_waveform_douta : std_logic_vector(31 downto 0); -- Data out from waveform RAM
|
||||||
|
signal ram_waveform_addrb : std_logic_vector(11 downto 0); -- Address for waveform RAM
|
||||||
|
signal ram_waveform_doutb : std_logic_vector(15 downto 0); -- Data out from waveform RAM
|
||||||
|
|
||||||
|
-- State variable type declaration for main state machine
|
||||||
|
-- TODO: add a fetch state to get four address from pd ram?
|
||||||
|
type t_sm_state is (
|
||||||
|
S_RESET, -- Wait for 'enable'. Stay here until JESD interface is up and running,
|
||||||
|
S_IDLE, -- Wait for 'start'
|
||||||
|
S_WAIT, -- Wait for cnt_time, external input, to match pulse position RAM output
|
||||||
|
S_LOAD, -- Load the pulse channel RAM addresses and start the waveform output
|
||||||
|
S_HOLD, -- Hold the last pulse definition address and output its data
|
||||||
|
S_WAVE_UP, -- Output the rising edge of a waveform
|
||||||
|
S_WAVE_FLAT,-- Output the flat top part of a waveform
|
||||||
|
S_WAVE_DOWN -- Output the falling edge of a waveform
|
||||||
|
);
|
||||||
|
signal sm_state : t_sm_state;
|
||||||
|
signal sm_wavedata : std_logic_vector(15 downto 0); -- Waveform RAM data
|
||||||
|
signal sm_wavedata_dv : std_logic; -- Signal to indicate that waveform RAM data is valid
|
||||||
|
signal sm_busy : std_logic; -- Signal to indicate that s.m. is not idle
|
||||||
|
signal cnt_wave_len : unsigned(C_BITS_ADDR_LENGTH - 1 downto 0); -- Counter used for incremnet/decrement wave table addresses
|
||||||
|
signal cnt_wave_top : unsigned(C_BITS_ADDR_TOP - 1 downto 0); -- Counter for the flat top of the waveform
|
||||||
|
|
||||||
|
-- Misc signals
|
||||||
|
signal cpu_rdata_dv_e1 : std_logic;
|
||||||
|
signal cpu_rdata_dv_e2 : std_logic;
|
||||||
|
signal cpu_rdata_ramsel_d1 : std_logic;
|
||||||
|
signal cpu_rdata_ramsel_d2 : std_logic;
|
||||||
|
|
||||||
|
signal pc : std_logic_vector(C_BITS_ADDR_PULSE - 1 downto 0); -- pulse counter, used to count the number of pulses generated
|
||||||
|
|
||||||
|
----------------------------------------------------------------
|
||||||
|
-- Assign values from the pulse definition ram to regfiles (?) with the following:
|
||||||
|
-- 1. Start time 24 bits. [23:0]
|
||||||
|
-- 2. Wave start addr 12 bit at [11:0]
|
||||||
|
-- Wave length 10-bit at [25:16]
|
||||||
|
-- 3. Scale factors 16, 16. [31:16] [15:0]
|
||||||
|
-- 4. Flat-top 17-bit. [16:0]
|
||||||
|
----------------------------------------------------------------
|
||||||
|
signal reg_start_time : std_logic_vector(23 downto 0); -- first register which stores the pulse's start time
|
||||||
|
signal reg_pulse_sizes : std_logic_vector(31 downto 0); -- second register which stores the pulse's length, the bit width should increase with the amount of addresses the wavetable has, and its start address
|
||||||
|
-- TODO: replace the above one w/ below two
|
||||||
|
signal reg_wave_start_addr : std_logic_vector(11 downto 0); -- the start address of the wavetable
|
||||||
|
signal reg_wave_length : unsigned(9 downto 0); -- the length of the wavetable
|
||||||
|
|
||||||
|
signal reg_pulse_factors : std_logic_vector(31 downto 0); -- third register which stores the pulse's amplitude and time scale factors
|
||||||
|
-- TODO: replace the above one w/ below two
|
||||||
|
signal reg_scale_gain : unsigned(15 downto 0); -- scale factor for the gain, amplitude
|
||||||
|
signal reg_scale_time : unsigned(15 downto 0); -- scale factor for the time, length
|
||||||
|
|
||||||
|
signal reg_flattop : std_logic_vector(16 downto 0); -- fourth register which stores the pulse's flat top value
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- Pipeline delays
|
||||||
|
signal start_d1 : std_logic;
|
||||||
|
signal enable_d1 : std_logic;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
----------------------------------------------------------------
|
||||||
|
-- Pulse Definition Block RAM.
|
||||||
|
-- Synch write, Synch read
|
||||||
|
-- Port A is for CPU read/write. 1024x32-bit
|
||||||
|
-- Port B is for pulse time data output. 1024x32-bit
|
||||||
|
----------------------------------------------------------------
|
||||||
|
u_ram_pulse : entity work.bram_pulse_definition
|
||||||
|
port map(
|
||||||
|
-- Port A CPU Bus
|
||||||
|
clka => clk, -- input std_logic
|
||||||
|
wea => ram_pulse_we, -- input slv( 0 to 0 )
|
||||||
|
addra => ram_pulse_addra, -- input slv( 9 downto 0 )
|
||||||
|
dina => ram_pulse_dina, -- input slv( 31 downto 0 )
|
||||||
|
douta => ram_pulse_douta, -- output slv( 31 downto 0 ),
|
||||||
|
-- Port B waveform input
|
||||||
|
clkb => clk,
|
||||||
|
web => (others=>'0'),
|
||||||
|
addrb => ram_pulse_addrb, -- input slv( 9 downto 0 )
|
||||||
|
dinb => (others=>'0'),
|
||||||
|
doutb => ram_pulse_doutb -- output slv( 31 downto 0 )
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
----------------------------------------------------------------
|
||||||
|
-- Waveform table Block RAM.
|
||||||
|
-- Synch write, Synch read
|
||||||
|
-- Port A is for CPU read/write. 2048x32-bit
|
||||||
|
-- Port B is for waveform data. 4096x16-bit
|
||||||
|
----------------------------------------------------------------
|
||||||
|
u_ram_waveform : entity work.bram_waveform
|
||||||
|
port map (
|
||||||
|
-- Port A CPU Bus
|
||||||
|
clka => clk , -- input std_logic
|
||||||
|
wea => ram_waveform_wea , -- input slv(0 downto 0)
|
||||||
|
addra => ram_waveform_addra , -- input slv(10 downto 0)
|
||||||
|
dina => ram_waveform_dina , -- input slv(31 downto 0)
|
||||||
|
douta => ram_waveform_douta , -- output slv(31 downto 0)
|
||||||
|
|
||||||
|
-- Port B waveform output
|
||||||
|
clkb => clk , -- input std_logic
|
||||||
|
web => (others=>'0') , -- input slv(0 downto 0)
|
||||||
|
addrb => ram_waveform_addrb , -- input slv(11 downto 0)
|
||||||
|
dinb => (others=>'0') , -- input slv(15 downto 0)
|
||||||
|
doutb => ram_waveform_doutb -- output slv(15 downto 0)
|
||||||
|
);
|
||||||
|
|
||||||
|
----------------------------------------------------------------
|
||||||
|
-- CPU Read/Write RAM
|
||||||
|
-- MSB of cpu_addr is used to select one of the two RAMs
|
||||||
|
-- to read/write, and the remainder are a 9-bit or 4-bit RAM address.
|
||||||
|
----------------------------------------------------------------
|
||||||
|
pr_ram_rw : process (reset, clk)
|
||||||
|
begin
|
||||||
|
if (reset = '1') then
|
||||||
|
|
||||||
|
ram_pulse_addra <= (others=>'0');
|
||||||
|
ram_pulse_dina <= (others=>'0');
|
||||||
|
ram_pulse_we <= (others=>'0');
|
||||||
|
|
||||||
|
ram_waveform_wea <= (others=>'0');
|
||||||
|
ram_waveform_addra <= (others=>'0');
|
||||||
|
ram_waveform_dina <= (others=>'0');
|
||||||
|
|
||||||
|
cpu_rdata <= (others=>'0');
|
||||||
|
cpu_rdata_dv <= '0';
|
||||||
|
cpu_rdata_dv_e1 <= '0';
|
||||||
|
cpu_rdata_dv_e2 <= '0';
|
||||||
|
cpu_rdata_ramsel_d1 <= '0';
|
||||||
|
cpu_rdata_ramsel_d2 <= '0';
|
||||||
|
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
-- CPU writing RAM
|
||||||
|
-------------------------------------------------
|
||||||
|
if (cpu_wr = '1') and (cpu_sel = '1') then
|
||||||
|
|
||||||
|
-- 0 for pulse definition, 1 for waveform table
|
||||||
|
if (cpu_addr(C_RAM_SELECT) = '1') then
|
||||||
|
|
||||||
|
ram_pulse_addra <= (others=>'0');
|
||||||
|
ram_pulse_dina <= (others=>'0');
|
||||||
|
ram_pulse_we <= (others=>'0');
|
||||||
|
|
||||||
|
ram_waveform_wea(0) <= '1';
|
||||||
|
ram_waveform_addra <= cpu_addr(10 downto 0);
|
||||||
|
ram_waveform_dina <= cpu_wdata;
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
ram_pulse_addra <= cpu_addr(9 downto 0);
|
||||||
|
ram_pulse_dina <= cpu_wdata;
|
||||||
|
ram_pulse_we(0) <= '1';
|
||||||
|
ram_waveform_wea <= (others=>'0');
|
||||||
|
ram_waveform_addra <= (others=>'0');
|
||||||
|
ram_waveform_dina <= (others=>'0');
|
||||||
|
|
||||||
|
end if;
|
||||||
|
|
||||||
|
cpu_rdata_dv_e1 <= '0';
|
||||||
|
cpu_rdata_dv_e2 <= '0';
|
||||||
|
cpu_rdata_ramsel_d1 <= '0';
|
||||||
|
cpu_rdata_ramsel_d2 <= '0';
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
-- CPU read
|
||||||
|
-------------------------------------------------
|
||||||
|
elsif (cpu_wr = '0') and (cpu_sel = '1') then
|
||||||
|
|
||||||
|
if (cpu_addr(C_RAM_SELECT) = '1') then -- Waveform
|
||||||
|
ram_pulse_addra <= (others=>'0');
|
||||||
|
ram_waveform_addra <= cpu_addr(10 downto 0);
|
||||||
|
else -- Pulse
|
||||||
|
ram_pulse_addra <= cpu_addr(9 downto 0);
|
||||||
|
ram_waveform_addra <= (others=>'0');
|
||||||
|
end if;
|
||||||
|
|
||||||
|
ram_pulse_we <= (others=>'0');
|
||||||
|
ram_waveform_wea(0) <= '0';
|
||||||
|
|
||||||
|
cpu_rdata_dv_e2 <= '1'; -- DV for cycle, when RAM output occurs
|
||||||
|
cpu_rdata_dv_e1 <= cpu_rdata_dv_e2; -- DV for next cycle
|
||||||
|
cpu_rdata_ramsel_d1 <= cpu_addr(C_RAM_SELECT); -- Save the select bit one cycle later
|
||||||
|
cpu_rdata_ramsel_d2 <= cpu_rdata_ramsel_d1;
|
||||||
|
|
||||||
|
else
|
||||||
|
ram_pulse_addra <= (others=>'0');
|
||||||
|
ram_pulse_we <= (others=>'0');
|
||||||
|
ram_waveform_addra <= (others=>'0');
|
||||||
|
ram_waveform_wea(0) <= '0';
|
||||||
|
|
||||||
|
cpu_rdata_dv_e2 <= '0';
|
||||||
|
cpu_rdata_dv_e1 <= cpu_rdata_dv_e2; -- DV for next cycle
|
||||||
|
cpu_rdata_ramsel_d1 <= '0';
|
||||||
|
cpu_rdata_ramsel_d2 <= cpu_rdata_ramsel_d1;
|
||||||
|
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
-- Output the delayed RAM data
|
||||||
|
-- This adds a pipeline delay to the cpu_rdata_dv to account for
|
||||||
|
-- the delay in reading data from the RAM
|
||||||
|
-------------------------------------------------
|
||||||
|
if (cpu_rdata_dv_e1 = '1') then
|
||||||
|
|
||||||
|
cpu_rdata_dv <= '1';
|
||||||
|
|
||||||
|
-- Select source of output data
|
||||||
|
if (cpu_rdata_ramsel_d2 = '1') then -- Output is from waveform table
|
||||||
|
cpu_rdata <= ram_waveform_douta;
|
||||||
|
|
||||||
|
elsif (cpu_rdata_ramsel_d2 = '0') then
|
||||||
|
cpu_rdata <= ram_pulse_douta;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
else
|
||||||
|
cpu_rdata <= (others=>'0');
|
||||||
|
cpu_rdata_dv <= '0';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
end if;
|
||||||
|
|
||||||
|
end process;
|
||||||
|
|
||||||
|
----------------------------------------------------------------
|
||||||
|
-- State machine:
|
||||||
|
-- Compares cnt_time input against current output from pulse position RAM.
|
||||||
|
-- When values match iti incremnts the pulse postion RAM address to
|
||||||
|
-- retrieve the next pulse position and also starts reading the
|
||||||
|
-- entire waveform table, one value every clock cycle, until it reaches the end.
|
||||||
|
-- Once the pulse is complete it waits for the next cnt_time match.
|
||||||
|
-- Repeat until all pulse position RAM times have triggered a pulse output
|
||||||
|
-- or until the maximum counter time has been reached.
|
||||||
|
----------------------------------------------------------------
|
||||||
|
pr_sm : process (reset, clk)
|
||||||
|
variable v_amp_factor : std_logic_vector(C_BITS_GAIN_FACTOR - 1 downto 0);
|
||||||
|
variable v_time_factor : std_logic_vector(C_BITS_TIME_FACTOR - 1 downto 0);
|
||||||
|
|
||||||
|
-- Temp variables for waveform output
|
||||||
|
variable v_ram_waveform_doutb_multiplied : std_logic_vector(C_BITS_GAIN_FACTOR + 15 downto 0);
|
||||||
|
begin
|
||||||
|
if (reset = '1') then
|
||||||
|
|
||||||
|
sm_state <= S_IDLE; -- TODO: Eric: Should this be S_RESET since we reset the JEDS interface as well?
|
||||||
|
ram_pulse_addrb <= (others=>'0');
|
||||||
|
ram_waveform_addrb <= (others=>'0');
|
||||||
|
|
||||||
|
sm_wavedata <= (others=>'0');
|
||||||
|
sm_wavedata_dv <= '0';
|
||||||
|
sm_busy <= '0';
|
||||||
|
|
||||||
|
reg_start_time <= (others=>'0');
|
||||||
|
reg_pulse_sizes <= (others=>'0');
|
||||||
|
reg_pulse_factors <= (others=>'0');
|
||||||
|
reg_flattop <= (others=>'0');
|
||||||
|
reg_scale_gain <= (others=>'0');
|
||||||
|
reg_scale_time <= (others=>'0');
|
||||||
|
|
||||||
|
pc <= (others=>'0');
|
||||||
|
cnt_wave_len <= (others=>'0');
|
||||||
|
cnt_wave_top <= (others=>'0');
|
||||||
|
elsif rising_edge(clk) then
|
||||||
|
|
||||||
|
|
||||||
|
-- Pipeline delays to use for rising edge detection
|
||||||
|
enable_d1 <= enable;
|
||||||
|
start_d1 <= start;
|
||||||
|
|
||||||
|
-- Default
|
||||||
|
sm_wavedata <= (others=>'0');
|
||||||
|
sm_wavedata_dv <= '0';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
-- Main state machine
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
case sm_state is
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
-- Wait for rising edge of enable
|
||||||
|
-- This is set when the JESD interface is aligned and functional.
|
||||||
|
-- Send a zero value to initialize the DAC then go to idle.
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
when S_RESET =>
|
||||||
|
|
||||||
|
if (enable = '1') and (enable_d1 = '0') then
|
||||||
|
sm_wavedata <= (others=>'0');
|
||||||
|
sm_wavedata_dv <= '1';
|
||||||
|
sm_state <= S_IDLE;
|
||||||
|
end if;
|
||||||
|
sm_busy <= '0';
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
-- Wait for rising edge of 'start'.
|
||||||
|
-- No data output.
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
when S_IDLE =>
|
||||||
|
|
||||||
|
if (start = '1') and (start_d1 = '0') then
|
||||||
|
sm_state <= S_LOAD;
|
||||||
|
sm_busy <= '1';
|
||||||
|
else
|
||||||
|
sm_busy <= '0';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
-- Load four addresses from pulse definition RAM into four 32 bits regesters
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
when S_LOAD =>
|
||||||
|
-- TODO: Eric: does is needed here? or should be inside the if-else loops
|
||||||
|
-- Load the pulse channel RAM addresses and start the waveform output
|
||||||
|
sm_busy <= '1';
|
||||||
|
-- Pipline the pulse definition address
|
||||||
|
|
||||||
|
-- TODO: is it better to make a counter to count the quarter or just mod 4?
|
||||||
|
-- TODO: maybe C-slow around the pulse ram to get it down to 1 cycle??
|
||||||
|
if (unsigned(ram_pulse_addrb) mod 4 = 0) then
|
||||||
|
ram_pulse_addrb <= std_logic_vector(unsigned(pc) + 1);
|
||||||
|
sm_state <= S_LOAD;
|
||||||
|
-- first quarter of the pulse definition, no register is loaded
|
||||||
|
-- reg_start_time <= ram_pulse_doutb;
|
||||||
|
|
||||||
|
elsif (unsigned(ram_pulse_addrb) mod 4 = 1) then
|
||||||
|
ram_pulse_addrb <= std_logic_vector(unsigned(pc) + 2);
|
||||||
|
sm_state <= S_LOAD;
|
||||||
|
-- reg_pulse_sizes <= ram_pulse_doutb;
|
||||||
|
-- second quarter of the pulse definition, the start time is loaded
|
||||||
|
reg_start_time <= ram_pulse_doutb;
|
||||||
|
|
||||||
|
|
||||||
|
elsif (unsigned(ram_pulse_addrb) mod 4 = 2) then
|
||||||
|
ram_pulse_addrb <= std_logic_vector(unsigned(pc) + 3);
|
||||||
|
sm_state <= S_LOAD;
|
||||||
|
-- reg_pulse_factors <= ram_pulse_doutb;
|
||||||
|
-- third quarter of the pulse definition, the length and start address of the wavetable are loaded
|
||||||
|
reg_pulse_sizes <= ram_pulse_doutb;
|
||||||
|
|
||||||
|
|
||||||
|
elsif (unsigned(ram_pulse_addrb) mod 4 = 3) then
|
||||||
|
-- ram_pulse_addrb <= std_logic_vector(unsigned(pc) + 4);
|
||||||
|
sm_state <= S_WAIT; -- address is on the forth word of the entry, the loading process is complete. Moving onto the next state
|
||||||
|
-- hold the last pulse definition address as it will be used in the next state
|
||||||
|
-- reg_flattop <= ram_pulse_doutb;
|
||||||
|
pc <= std_logic_vector(unsigned(pc) + C_PC_INCR); -- incremnet the pulse counter and start waiting to output the wave
|
||||||
|
-- forth quarter of the pulse definition, the scale factors are loaded
|
||||||
|
reg_pulse_factors <= ram_pulse_doutb;
|
||||||
|
|
||||||
|
reg_scale_gain <= unsigned(ram_pulse_doutb(31 downto 16));
|
||||||
|
reg_scale_time <= unsigned(ram_pulse_doutb(15 downto 0));
|
||||||
|
|
||||||
|
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- ------------------------------------------------------------------------
|
||||||
|
-- -- Hold the last pulse definition address and output its data for one more clock cycle
|
||||||
|
-- ------------------------------------------------------------------------
|
||||||
|
-- when S_HOLD =>
|
||||||
|
-- sm_state <= S_LOAD;
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
-- Wait for cnt_time, external input, to match pulse position RAM output
|
||||||
|
-- Return to idle state if max time is reached. Output waveform value zero.
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
when S_WAIT =>
|
||||||
|
-- read the last word of the pulse definition, the flat top value
|
||||||
|
reg_flattop <= ram_pulse_doutb;
|
||||||
|
-- Start to output wave and increment pulse position RAM address
|
||||||
|
if (reg_start_time(C_START_TIME - 1 downto 0) = cnt_time) then
|
||||||
|
sm_state <= S_WAVE_UP;
|
||||||
|
-- set the wavetable's address to the starting address defined from the pulse ram
|
||||||
|
ram_waveform_addrb <= reg_pulse_sizes(C_BITS_ADDR_START - 1 downto 0);
|
||||||
|
-- reset the wave lenth counter
|
||||||
|
cnt_wave_len <= (others=>'0');
|
||||||
|
-- parse the scale factors from reg_pulse_factors register
|
||||||
|
v_time_factor := reg_pulse_factors(C_BITS_TIME_FACTOR - 1 downto 0);
|
||||||
|
v_amp_factor := reg_pulse_factors(31 downto 16);
|
||||||
|
elsif (cnt_time = X"FFFFFF") then
|
||||||
|
sm_state <= S_IDLE;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
-- Output the raising edge of a waveform
|
||||||
|
-- Hold the last address when complete
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
when S_WAVE_UP =>
|
||||||
|
-- Check if is end of rise of the waveform, and hold the address
|
||||||
|
|
||||||
|
-- TODO: convert the numbers below to constaint. right now just make sure I'm not confused
|
||||||
|
if (cnt_wave_len = reg_wave_length) then
|
||||||
|
sm_state <= S_WAVE_FLAT;
|
||||||
|
-- reset counters for transitions
|
||||||
|
cnt_wave_len <= (others=>'0');
|
||||||
|
cnt_wave_top <= (others=>'0');
|
||||||
|
-- TODO: toSara: do we need to consider the even of no flat top?
|
||||||
|
else
|
||||||
|
cnt_wave_len <= cnt_wave_len + 1;
|
||||||
|
ram_waveform_addrb <= std_logic_vector(unsigned(ram_waveform_addrb) + 1);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
v_ram_waveform_doutb_multiplied := std_logic_vector(unsigned(ram_waveform_doutb) * reg_scale_gain);
|
||||||
|
sm_wavedata <= std_logic_vector(unsigned(ram_waveform_doutb) * reg_scale_gain)(31 downto 16);
|
||||||
|
sm_wavedata_dv <= '1';
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
-- Hold the last address and output its data
|
||||||
|
-- decrement from this address when finished waiting
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
when S_WAVE_FLAT =>
|
||||||
|
-- count the 17-bit flat top, if the counter reaches the flat top value, then go to the next state
|
||||||
|
if (cnt_wave_top = reg_flattop(C_BITS_ADDR_TOP - 1 downto 0)) then
|
||||||
|
sm_state <= S_WAVE_DOWN;
|
||||||
|
-- reset the counter for the next transition
|
||||||
|
cnt_wave_top <= (others=>'0');
|
||||||
|
else
|
||||||
|
cnt_wave_top <= std_logic_vector(unsigned(cnt_wave_top) + 1);
|
||||||
|
end if;
|
||||||
|
v_ram_waveform_doutb_multiplied := std_logic_vector(unsigned(ram_waveform_doutb) * unsigned(v_amp_factor));
|
||||||
|
sm_wavedata <= std_logic_vector(unsigned(ram_waveform_doutb) * reg_scale_gain)(31 downto 16); ;
|
||||||
|
sm_wavedata_dv <= '1';
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
-- Output the falling edge of a waveform
|
||||||
|
-- Hold the start address when complete
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
when S_WAVE_DOWN =>
|
||||||
|
|
||||||
|
-- End of waveform?
|
||||||
|
-- TODO: convert the numbers below to constaint. right now just make sure I'm not confused
|
||||||
|
if (cnt_wave_len = reg_wave_length) then
|
||||||
|
|
||||||
|
-- If the end of the pulse table is reached then go to idle, increment pulse address for the next waveform otherwise
|
||||||
|
if (ram_pulse_addrb = std_logic_vector(to_unsigned(C_LEN_PULSE-1, C_BITS_ADDR_PULSE))) then
|
||||||
|
ram_pulse_addrb <= (others=>'0');
|
||||||
|
pc <= (others=>'0');
|
||||||
|
sm_state <= S_IDLE;
|
||||||
|
|
||||||
|
else -- increment pulse address for the next waveform
|
||||||
|
ram_pulse_addrb <= pc;
|
||||||
|
-- the above line will now happen in the load state
|
||||||
|
-- pc <= std_logic_vector(unsigned(pc) + C_PC_INCR);
|
||||||
|
sm_state <= S_LOAD;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Output waveform from RAM with decremented address
|
||||||
|
else
|
||||||
|
cnt_wave_len <= cnt_wave_len + 1;
|
||||||
|
ram_waveform_addrb <= std_logic_vector(unsigned(ram_waveform_addrb) - 1);
|
||||||
|
end if;
|
||||||
|
sm_wavedata <= std_logic_vector(unsigned(ram_waveform_doutb) * reg_scale_gain)(31 downto 16);
|
||||||
|
sm_wavedata_dv <= '1';
|
||||||
|
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
-- Default
|
||||||
|
------------------------------------------------------------------------
|
||||||
|
when others =>
|
||||||
|
sm_state <= S_IDLE;
|
||||||
|
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- AXI-Stream output.
|
||||||
|
-- TBD: This should come from a FIFO
|
||||||
|
-- TODO: the bits are not correct, should be top bits (C_BITS_GAIN_FACTOR + 16 downto C_BITS_GAIN_FACTOR), but for now just make it this way so modelsim can simulate
|
||||||
|
-- TODO: apply scaling factor to the output
|
||||||
|
axis_tdata <= sm_wavedata; -- axi stream output data, this output should be multiplied by the gain factor, then take the top 16 bits
|
||||||
|
axis_tvalid <= sm_wavedata_dv; -- axi_stream output data valid
|
||||||
|
|
||||||
|
-- TBD : Generate in state machine?
|
||||||
|
axis_tlast <= '0'; -- axi_stream output last
|
||||||
|
|
||||||
|
end channel;
|
|
@ -2,7 +2,7 @@ do compile.do
|
||||||
|
|
||||||
vsim -voptargs="+acc" -lib work tb_cpubus_dacs_pulse_channel
|
vsim -voptargs="+acc" -lib work tb_cpubus_dacs_pulse_channel
|
||||||
|
|
||||||
do waves_do/pp_sm.do
|
do waves_do/pp_sm_wavetables.do
|
||||||
|
|
||||||
view wave
|
view wave
|
||||||
view structure
|
view structure
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
# Current time Mon Jan 15 15:15:21 2024
|
||||||
|
# ModelSim - Intel FPGA Edition Stack Trace
|
||||||
|
# Program = vsim
|
||||||
|
# Id = "10.5b"
|
||||||
|
# Version = "2016.10"
|
||||||
|
# Date = "Oct 5 2016"
|
||||||
|
# Platform = win32pe
|
||||||
|
# Signature = a4da31216fa3031746f0a74423efc007
|
||||||
|
# 0 0x004d3b4a: '<unknown (@0x4d3b4a)>'
|
||||||
|
# End of Stack Trace
|
||||||
|
|
||||||
|
|
||||||
|
# Current time Mon Jan 22 14:57:15 2024
|
||||||
|
# ModelSim - Intel FPGA Edition Stack Trace
|
||||||
|
# Program = vsim
|
||||||
|
# Id = "10.5b"
|
||||||
|
# Version = "2016.10"
|
||||||
|
# Date = "Oct 5 2016"
|
||||||
|
# Platform = win32pe
|
||||||
|
# Signature = a4da31216fa3031746f0a74423efc007
|
||||||
|
# 0 0x005d9fc7: '<unknown (@0x5d9fc7)>'
|
||||||
|
# End of Stack Trace
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
onerror {resume}
|
||||||
|
quietly virtual signal -install /tb_cpubus_dacs_pulse_channel/u_dac_pulse { /tb_cpubus_dacs_pulse_channel/u_dac_pulse/reg_pulse_time(31 downto 16)} reg_pulse_time_31_16
|
||||||
|
quietly virtual signal -install /tb_cpubus_dacs_pulse_channel/u_dac_pulse { /tb_cpubus_dacs_pulse_channel/u_dac_pulse/reg_pulse_time(15 downto 0)} reg_pulse_time_15_0
|
||||||
|
quietly WaveActivateNextPane {} 0
|
||||||
|
add wave -noupdate /tb_cpubus_dacs_pulse_channel/u_dac_pulse/clk
|
||||||
|
add wave -noupdate /tb_cpubus_dacs_pulse_channel/u_dac_pulse/start
|
||||||
|
add wave -noupdate /tb_cpubus_dacs_pulse_channel/u_dac_pulse/reset
|
||||||
|
add wave -noupdate /tb_cpubus_dacs_pulse_channel/u_dac_pulse/busy
|
||||||
|
add wave -noupdate -radix unsigned /tb_cpubus_dacs_pulse_channel/u_dac_pulse/cnt_time
|
||||||
|
add wave -noupdate -radix binary /tb_cpubus_dacs_pulse_channel/u_dac_pulse/cpu_addr
|
||||||
|
add wave -noupdate -radix hexadecimal /tb_cpubus_dacs_pulse_channel/u_dac_pulse/cpu_wdata
|
||||||
|
add wave -noupdate /tb_cpubus_dacs_pulse_channel/u_dac_pulse/cpu_wr
|
||||||
|
add wave -noupdate /tb_cpubus_dacs_pulse_channel/u_dac_pulse/cpu_sel
|
||||||
|
add wave -noupdate -radix hexadecimal /tb_cpubus_dacs_pulse_channel/u_dac_pulse/cpu_rdata
|
||||||
|
add wave -noupdate /tb_cpubus_dacs_pulse_channel/u_dac_pulse/cpu_rdata_dv
|
||||||
|
add wave -noupdate -radix unsigned /tb_cpubus_dacs_pulse_channel/u_dac_pulse/ram_pulse_addra
|
||||||
|
add wave -noupdate -radix hexadecimal /tb_cpubus_dacs_pulse_channel/u_dac_pulse/ram_pulse_dina
|
||||||
|
add wave -noupdate -radix hexadecimal /tb_cpubus_dacs_pulse_channel/u_dac_pulse/ram_pulse_douta
|
||||||
|
add wave -noupdate /tb_cpubus_dacs_pulse_channel/u_dac_pulse/ram_pulse_we
|
||||||
|
add wave -noupdate /tb_cpubus_dacs_pulse_channel/u_dac_pulse/sm_state
|
||||||
|
add wave -noupdate -radix unsigned /tb_cpubus_dacs_pulse_channel/u_dac_pulse/pc
|
||||||
|
add wave -noupdate -radix unsigned /tb_cpubus_dacs_pulse_channel/u_dac_pulse/ram_pulse_addrb
|
||||||
|
add wave -noupdate -radix hexadecimal /tb_cpubus_dacs_pulse_channel/u_dac_pulse/ram_pulse_doutb
|
||||||
|
add wave -noupdate -radix unsigned /tb_cpubus_dacs_pulse_channel/u_dac_pulse/reg_pulse_time
|
||||||
|
add wave -noupdate -radix hexadecimal /tb_cpubus_dacs_pulse_channel/u_dac_pulse/reg_scale_gain
|
||||||
|
add wave -noupdate -radix hexadecimal /tb_cpubus_dacs_pulse_channel/u_dac_pulse/reg_scale_time
|
||||||
|
add wave -noupdate -radix unsigned /tb_cpubus_dacs_pulse_channel/u_dac_pulse/reg_wave_start_addr
|
||||||
|
add wave -noupdate -radix unsigned /tb_cpubus_dacs_pulse_channel/u_dac_pulse/reg_wave_length
|
||||||
|
add wave -noupdate -radix unsigned /tb_cpubus_dacs_pulse_channel/u_dac_pulse/reg_pulse_flattop
|
||||||
|
add wave -noupdate /tb_cpubus_dacs_pulse_channel/u_dac_pulse/ram_waveform_wea
|
||||||
|
add wave -noupdate -radix unsigned /tb_cpubus_dacs_pulse_channel/u_dac_pulse/ram_waveform_addra
|
||||||
|
add wave -noupdate -radix unsigned /tb_cpubus_dacs_pulse_channel/u_dac_pulse/ram_waveform_dina
|
||||||
|
add wave -noupdate -radix unsigned /tb_cpubus_dacs_pulse_channel/u_dac_pulse/ram_waveform_douta
|
||||||
|
add wave -noupdate -radix unsigned /tb_cpubus_dacs_pulse_channel/u_dac_pulse/ram_waveform_addrb
|
||||||
|
add wave -noupdate -radix hexadecimal /tb_cpubus_dacs_pulse_channel/u_dac_pulse/ram_waveform_doutb
|
||||||
|
add wave -noupdate -radix hexadecimal /tb_cpubus_dacs_pulse_channel/u_dac_pulse/sm_wavedata
|
||||||
|
add wave -noupdate /tb_cpubus_dacs_pulse_channel/u_dac_pulse/sm_wavedata_dv
|
||||||
|
add wave -noupdate -format Analog-Step -height 74 -max 204.0 -radix unsigned /tb_cpubus_dacs_pulse_channel/u_dac_pulse/axis_tdata
|
||||||
|
add wave -noupdate /tb_cpubus_dacs_pulse_channel/u_dac_pulse/axis_tvalid
|
||||||
|
add wave -noupdate /tb_cpubus_dacs_pulse_channel/u_dac_pulse/axis_tlast
|
||||||
|
add wave -noupdate /tb_cpubus_dacs_pulse_channel/u_dac_pulse/axis_tready
|
||||||
|
TreeUpdate [SetDefaultTree]
|
||||||
|
WaveRestoreCursors {{Cursor 2} {62275000000 fs} 0}
|
||||||
|
quietly wave cursor active 1
|
||||||
|
configure wave -namecolwidth 163
|
||||||
|
configure wave -valuecolwidth 99
|
||||||
|
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 fs
|
||||||
|
update
|
||||||
|
WaveRestoreZoom {61852729312 fs} {62817270688 fs}
|
|
@ -257,7 +257,7 @@
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.OUTPUTDIR">../../../prj/zcu_pulse_channel.gen/sources_1/ip/bram_pulse_definition</spirit:configurableElementValue>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.OUTPUTDIR">../../../prj/zcu_pulse_channel.gen/sources_1/ip/bram_pulse_definition</spirit:configurableElementValue>
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SELECTEDSIMMODEL"/>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SELECTEDSIMMODEL"/>
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SHAREDDIR">.</spirit:configurableElementValue>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SHAREDDIR">.</spirit:configurableElementValue>
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SWVERSION">2022.1</spirit:configurableElementValue>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SWVERSION">2022.1.2</spirit:configurableElementValue>
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SYNTHESISFLOW">OUT_OF_CONTEXT</spirit:configurableElementValue>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SYNTHESISFLOW">OUT_OF_CONTEXT</spirit:configurableElementValue>
|
||||||
</spirit:configurableElementValues>
|
</spirit:configurableElementValues>
|
||||||
<spirit:vendorExtensions>
|
<spirit:vendorExtensions>
|
||||||
|
|
|
@ -86,7 +86,7 @@
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.OUTPUTDIR">../../../prj/zcu_pulse_channel.gen/sources_1/ip/bram_pulseposition</spirit:configurableElementValue>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.OUTPUTDIR">../../../prj/zcu_pulse_channel.gen/sources_1/ip/bram_pulseposition</spirit:configurableElementValue>
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SELECTEDSIMMODEL"/>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SELECTEDSIMMODEL"/>
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SHAREDDIR">.</spirit:configurableElementValue>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SHAREDDIR">.</spirit:configurableElementValue>
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SWVERSION">2022.1</spirit:configurableElementValue>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SWVERSION">2022.1.2</spirit:configurableElementValue>
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SYNTHESISFLOW">OUT_OF_CONTEXT</spirit:configurableElementValue>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SYNTHESISFLOW">OUT_OF_CONTEXT</spirit:configurableElementValue>
|
||||||
</spirit:configurableElementValues>
|
</spirit:configurableElementValues>
|
||||||
<spirit:vendorExtensions>
|
<spirit:vendorExtensions>
|
||||||
|
|
|
@ -257,7 +257,7 @@
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.OUTPUTDIR">../../../prj/zcu_pulse_channel.gen/sources_1/ip/bram_waveform</spirit:configurableElementValue>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.OUTPUTDIR">../../../prj/zcu_pulse_channel.gen/sources_1/ip/bram_waveform</spirit:configurableElementValue>
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SELECTEDSIMMODEL"/>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SELECTEDSIMMODEL"/>
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SHAREDDIR">.</spirit:configurableElementValue>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SHAREDDIR">.</spirit:configurableElementValue>
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SWVERSION">2022.1</spirit:configurableElementValue>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SWVERSION">2022.1.2</spirit:configurableElementValue>
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SYNTHESISFLOW">OUT_OF_CONTEXT</spirit:configurableElementValue>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SYNTHESISFLOW">OUT_OF_CONTEXT</spirit:configurableElementValue>
|
||||||
</spirit:configurableElementValues>
|
</spirit:configurableElementValues>
|
||||||
<spirit:vendorExtensions>
|
<spirit:vendorExtensions>
|
||||||
|
|
|
@ -524,7 +524,7 @@
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.OUTPUTDIR">../../../prj/zcu_pulse_channel.gen/sources_1/ip/fifo_data_to_stream</spirit:configurableElementValue>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.OUTPUTDIR">../../../prj/zcu_pulse_channel.gen/sources_1/ip/fifo_data_to_stream</spirit:configurableElementValue>
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SELECTEDSIMMODEL"/>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SELECTEDSIMMODEL"/>
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SHAREDDIR">.</spirit:configurableElementValue>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SHAREDDIR">.</spirit:configurableElementValue>
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SWVERSION">2022.1</spirit:configurableElementValue>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SWVERSION">2022.1.2</spirit:configurableElementValue>
|
||||||
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SYNTHESISFLOW">OUT_OF_CONTEXT</spirit:configurableElementValue>
|
<spirit:configurableElementValue spirit:referenceId="RUNTIME_PARAM.SYNTHESISFLOW">OUT_OF_CONTEXT</spirit:configurableElementValue>
|
||||||
</spirit:configurableElementValues>
|
</spirit:configurableElementValues>
|
||||||
<spirit:vendorExtensions>
|
<spirit:vendorExtensions>
|
||||||
|
|
Loading…
Reference in New Issue