diff --git a/.gitignore b/.gitignore index eba538a..756ae22 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ #Ignore List /syn/** /modelsim/** +/ip/** #Unignore Directories (Needed to unignore files in Subdirectories) diff --git a/doc/ug573-ultrascale-memory-resources.pdf b/doc/ug573-ultrascale-memory-resources.pdf new file mode 100644 index 0000000..bc241c5 --- /dev/null +++ b/doc/ug573-ultrascale-memory-resources.pdf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:703916371dafe6dddfd0c4b75c15e13a1f6b998c85ee38c1af2e05213807a70b +size 3838985 diff --git a/doc/ug974-vivado-ultrascale-libraries.pdf b/doc/ug974-vivado-ultrascale-libraries.pdf new file mode 100644 index 0000000..fd58dd1 --- /dev/null +++ b/doc/ug974-vivado-ultrascale-libraries.pdf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67bc73fa17fc19acb51a5bd9ce50237703f1aad7c1b64227015de9b402f456ab +size 5980850 diff --git a/src/addsub.vhd b/src/addsub.vhd new file mode 100644 index 0000000..ab608c9 --- /dev/null +++ b/src/addsub.vhd @@ -0,0 +1,75 @@ +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). +-- NOTE: In 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 : std_logic; + reset : std_logic; + mode : std_logic; + A : std_logic_vector(DATA_WIDTH-1 downto 0); + B : std_logic_vector(DATA_WIDTH-1 downto 0); + RES : 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') 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; \ No newline at end of file diff --git a/src/delay_line.vhd b/src/delay_line.vhd new file mode 100644 index 0000000..9f4bc67 --- /dev/null +++ b/src/delay_line.vhd @@ -0,0 +1,100 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +-- Variable Size Delay Line +-- This entity is based on a single port RAM from which every clock cycle the old contents of an address +-- are read out and updated with new contents. By incrementing the addresses in a pre-defined loop we +-- have effectively a ring buffer that we can vary in size (up to the maximum capacity of the memory). +-- NOTE: Changing the 'delay' value may lead to glitches during the first "delay period", due to the +-- way the address generation is made. More specifically, these glitches happen when the 'delay' is +-- increased (which is unavoidable), and when it is decreased while the counter is the same as the new +-- delay [single cycle glitch]. + +entity delay_line is + generic ( + DATA_WIDTH : integer := 12; + DELAY_WIDTH : integer := 8; + MAX_DELAY : integer := 200 + ); + port ( + clk : in std_logic; + delay : in std_logic_vector(DELAY_WIDTH-1 downto 0); + data_in : in std_logic_vector(DATA_WIDTH-1 downto 0); + data_out : out std_logic_vector(DATA_WIDTH-1 downto 0) + ); +end entity; + +architecture arch of delay_line is + + --*****COMPONENT DECLARATION***** + component single_port_ram is + generic ( + ADDR_WIDTH : integer := 8; + DATA_WIDTH : integer := 12; + MEMORY_DEPTH : integer := 200 + ); + port ( + clk : in std_logic; + addr : in std_logic_vector(ADDR_WIDTH-1 downto 0); + wen : in std_logic; + ren : in std_logic; + write_data : in std_logic_vector(DATA_WIDTH-1 downto 0); + read_data : out std_logic_vector(DATA_WIDTH-1 downto 0) + ); + end component; + + --*****SIGNAl DECLARATION***** + signal cnt, cnt_next, cnt_max, cnt_max_next : integer range 0 to MAX_DELAY := 0; + signal memory_out : std_logic_vector(DATA_WIDTH-1 downto 0) := (others => '0'); + +begin + + --*****COMPONENT INSTANTIATION***** + ram_inst : single_port_ram + generic map( + ADDR_WIDTH => DELAY_WIDTH, + DATA_WIDTH => DATA_WIDTH, + MEMORY_DEPTH => MAX_DELAY + ); + port map( + clk => clk, + addr => cnt, + wen => '1', + ren => '1', + write_data => data_in, + read_data => memory_out + ); + + cntrl : process(all) + begin + -- DEFAULT VALUES + cnt_next <= cnt; + cnt_max_next <= cnt_max; + + if(to_integer(unsigned(addr)) = 0) then + data_out <= data_in; + else + data_out <= memory_out; + -- COUNT GENERATION + cnt_max_next <= to_integer(unsigned(addr)) - 1; + if (cnt >= cnt_max) then + cnt_next <= 0; + else + cnt_next <= cnt + 1; + end if; + end if; + end process; + + sync : process(clk, reset) + begin + if (reset = '1') then + cnt <= 0; + cnt_max <= 0; + elsif(rising_edge(clk)) then + cnt <= cnt_next; + cnt_max <= cnt_max_next; + end if; + end process; + +end architecture; \ No newline at end of file diff --git a/src/feedback_loop.vhd b/src/feedback_loop.vhd new file mode 100644 index 0000000..3602cb1 --- /dev/null +++ b/src/feedback_loop.vhd @@ -0,0 +1,235 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +-- Architecture + --- ---------- ------ ------- --- +--->|ADC|--->|Delay Line|--->|Scaler|--->|ADD/SUB|--->|DAC|---> + --- ---------- ------ ------- --- +-- ^ + --- ----- | +--->|ADC|---------------------|Latch|-------- + --- ----- + +entity feedback_loop is + port ( + clk : in std_logic; + reset : in std_logic; + adc_data_in1 : in std_logic; + adc_data_in2 : in std_logic; + addsub_mode : in std_logic; + delay : in std_logic_vector(7 downto 0); + factor : in std_logic_vector(3 downto 0); + adc_cs_n : out std_logic; + dac_data_out : out std_logic; + dac_cs_n : out std_logic; + dac_ldac : out std_logic + ); +end entity; + +architecture arch of feedback_loop is + + --*****SIGNAL DECLARATION***** + signal adc_data1, adc_data2 : std_logic_vector(11 downto 0) := (others => '0'); + signal adc_done : std_logic := '0'; + + --*****COMPONENT DECLARATION***** + component pmod_ad1_ctrl is + generic( + TRANSFER_CLK_COUNT : integer := 16; + DELAY_CLK_CNT : integer := 2; + DATA_BITS : integer := 12 + ); + port ( + sclk : in std_logic; -- PMOD-AD1 + reset : in std_logic; + sdata1 : in std_logic; -- PMOD-AD1 + sdata2 : in std_logic; -- PMOD-AD1 + enable : in std_logic; + cs_n : out std_logic;-- PMOD-AD1 + data1 : out std_logic_vector(DATA_BITS-1 downto 0); + data2 : out std_logic_vector(DATA_BITS-1 downto 0); + done : out std_logic + ); + end component; + + component pmod_da3_ctrl is + generic( + TRANSFER_CLK_COUNT : integer := 16; + DATA_BITS : integer := 16 + ); + port ( + sclk : in std_logic; -- PMOD-DA3 + reset : in std_logic; + start : in std_logic; + data : in std_logic_vector(DATA_BITS-1 downto 0); + cs_n : out std_logic;-- PMOD-DA3 + sdata : out std_logic;-- PMOD-DA3 + ldac : out std_logic;-- PMOD-DA3 + done : out std_logic + ); + end component; + + component scaler is + generic ( + DATA_WIDTH : integer := 12; + FACTOR_WIDTH : integer := 4; + PIPELINE_STAGES : integer := 1 + ); + port ( + clk : in std_logic; + data_in : in std_logic_vector(DATA_WIDTH-1 downto 0); + factor : in std_logic_vector(FACTOR_WIDTH-1 downto 0); + data_out : out std_logic_vector(DATA_WIDTH+FACTOR_WIDTH-1 downto 0) + ); + end component; + + component addsub is + generic ( + PIPELINE_STAGES : integer := 1; + DATA_WIDTH : integer := 16 + ); + port ( + clk : std_logic; + reset : std_logic; + mode : std_logic; + A : std_logic_vector(DATA_WIDTH-1 downto 0); + B : std_logic_vector(DATA_WIDTH-1 downto 0); + RES : std_logic_vector(DATA_WIDTH-1 downto 0) + ); + end component; + + component delay_line is + generic ( + DATA_WIDTH : integer := 12; + DELAY_WIDTH : integer := 8; + MAX_DELAY : integer := 200 + ); + port ( + clk : in std_logic; + delay : in std_logic_vector(DELAY_WIDTH-1 downto 0); + data_in : in std_logic_vector(DATA_WIDTH-1 downto 0); + data_out : out std_logic_vector(DATA_WIDTH-1 downto 0) + ); + end component; + + --*****SIGNAL DECLARATION***** + signal delay_out, latch_out : std_logic_vector(12 downto 0) := (others => '0'); + signal scaler_out, addsub_out : std_logic_vector(15 downto 0) := (others => '0'); + signal scaler_done, addsub_done : std_logic := '0'; + +begin + + --*****STAGE I***** + adc_inst : pmod_ad1_ctrl + generic map( + TRANSFER_CLK_COUNT => 16, + DELAY_CLK_CNT => 2, + DATA_BITS => 12 + ) + port map( + sclk => clk, + reset => areset, + sdata1 => adc_data_in1, + sdata2 => adc_data_in2, + enable => '1', + cs_n => adc_cs_n, + data1 => adc_data1, + data2 => adc_data2, + done => adc_done + ); + + --*****STAGE II***** + delay_line_inst : delay_line + generic map( + DATA_WIDTH => 13, + DELAY_WIDTH => 8, + MAX_DELAY => 200 + ) + port map( + clk => clk, + delay => delay, + data_in => (adc_done & adc_data1), + data_out => delay_out + ); + + --*****STAGE III***** + scaler_inst : scaler + generic map( + DATA_WIDTH => 12, + FACTOR_WIDTH => 4, + PIPELINE_STAGES => 1 + ) + port map( + clk => clk, + data_in => delay_out(11 downto 0), + factor => factor, + data_out => scaler_out + ); + + process(clk) + begin + if (rising_edge(clk)) then + if (reset = '1') then + scaler_done <= (others => '0'); + else + scaler_done <= delay_out(12); + end if; + end if; + end process; + + latch : process(clk) + begin + if (rising_edge(clk)) then + if (reset = '1') then + latch_out <= (others => '0'); + elsif (adc_done) then + latch_out <= adc_data2; + end if; + end if; + end process; + + --*****STAGE IV***** + addsub_inst : addsub + generic map( + PIPELINE_STAGES => 1, + DATA_WIDTH => 16 + ) + port map( + clk => clk, + reset => reset, + mode => addsub_mode, + A => scaler_out, + B => latch_out & "0000", + RES => addsub_out + ); + + process(clk) + begin + if (rising_edge(clk)) then + if (reset = '1') then + addsub_done <= '0'; + else + addsub_done <= scaler_done; + end if; + end if; + end process; + + --*****STAGE V***** + dac_inst : pmod_da3_ctrl + generic map( + TRANSFER_CLK_COUNT => 16, + DATA_BITS => 16 + ) + port map( + sclk => clk, + reset => reset, + start => addsub_done, + data => addsub_out, + cs_n => dac_cs_n, + sdata => dac_data_out, + ldac => dac_ldac, + done => open + ); + +end architecture; \ No newline at end of file diff --git a/src/mult.vhd b/src/mult.vhd new file mode 100644 index 0000000..41665a9 --- /dev/null +++ b/src/mult.vhd @@ -0,0 +1,45 @@ +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; + +entity mult is + generic ( + A_WIDTH : integer := 12; + B_WIDTH : integer := 4; + PIPELINE_STAGES : integer := 1 + ); + port ( + clk : in std_logic; + A : in std_logic_vector(A_WIDTH-1 downto 0); + B : in std_logic_vector(B_WIDTH-1 downto 0); + P : out std_logic_vector(A_WIDTH+B_WIDTH-1 downto 0) + ); +end entity; + +architecture arch of mult is + + +begin + + MULT_MACRO_inst : MULT_MACRO + generic map ( + DEVICE => "7SERIES", -- Target Device: "VIRTEX5", "7SERIES", "SPARTAN6" + LATENCY => PIPELINE_STAGES, -- Desired clock cycle latency, 0-4 + WIDTH_A => A_WIDTH, -- Multiplier A-input bus width, 1-25 + WIDTH_B => B_WIDTH) -- Multiplier B-input bus width, 1-18 + port map ( + P => P, -- Multiplier ouput bus, width determined by WIDTH_P generic + A => A, -- Multiplier input A bus, width determined by WIDTH_A generic + B => B, -- Multiplier input B bus, width determined by WIDTH_B generic + CE => '1', -- 1-bit active high input clock enable + CLK => clk, -- 1-bit positive edge clock input + RST => '0' -- 1-bit input active high reset + ); + +end architecture; \ No newline at end of file diff --git a/src/scaler.vhd b/src/scaler.vhd new file mode 100644 index 0000000..79fcff4 --- /dev/null +++ b/src/scaler.vhd @@ -0,0 +1,54 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +-- Scaler +-- This entity scales the 'data_in' input by the factor 'factor'. + +entity scaler is + generic ( + DATA_WIDTH : integer := 12; + FACTOR_WIDTH : integer := 4; + PIPELINE_STAGES : integer := 1 + ); + port ( + clk : in std_logic; + data_in : in std_logic_vector(DATA_WIDTH-1 downto 0); + factor : in std_logic_vector(FACTOR_WIDTH-1 downto 0); + data_out : out std_logic_vector(DATA_WIDTH+FACTOR_WIDTH-1 downto 0) + ); +end entity; + +architecture arch of scaler is + + --*****COMPONENT DECLARATION***** + component mult is + generic ( + A_WIDTH : integer := 12; + B_WIDTH : integer := 4; + PIPELINE_STAGES : integer := 1 + ); + port ( + clk : in std_logic; + A : in std_logic_vector(A_WIDTH-1 downto 0); + B : in std_logic_vector(B_WIDTH-1 downto 0); + P : out std_logic_vector(A_WIDTH+B_WIDTH-1 downto 0) + ); + end component; + +begin + + mult_inst : mult + generic map( + A_WIDTH => DATA_WIDTH, + B_WIDTH => FACTOR_WIDTH, + PIPELINE_STAGES => PIPELINE_STAGES + ); + port ( + clk => clk, + A => data_in, + B => factor, + P => data_out + ); + +end architecture; \ No newline at end of file diff --git a/src/single_port_ram.vhd b/src/single_port_ram.vhd new file mode 100644 index 0000000..85dc69c --- /dev/null +++ b/src/single_port_ram.vhd @@ -0,0 +1,65 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +Library xpm; +use xpm.vcomponents.all; + +entity single_port_ram is + generic ( + ADDR_WIDTH : integer := 8; + DATA_WIDTH : integer := 12; + MEMORY_DEPTH : integer := 200 + ); + port ( + clk : in std_logic; + addr : in std_logic_vector(ADDR_WIDTH-1 downto 0); + wen : in std_logic; + ren : in std_logic; + write_data : in std_logic_vector(DATA_WIDTH-1 downto 0); + read_data : out std_logic_vector(DATA_WIDTH-1 downto 0) + ); +end entity; + +architecture arch of single_port_ram is + +begin + + xpm_memory_spram_inst : xpm_memory_spram + generic map ( + ADDR_WIDTH_A => ADDR_WIDTH, + AUTO_SLEEP_TIME => 0, + BYTE_WRITE_WIDTH_A => DATA_WIDTH, + ECC_MODE => "no_ecc", + MEMORY_INIT_FILE => "none", + MEMORY_INIT_PARAM => "0", + MEMORY_OPTIMIZATION => "true", + MEMORY_PRIMITIVE => "auto", + MEMORY_SIZE => DATA_WIDTH*MEMORY_DEPTH, + MESSAGE_CONTROL => 0, + READ_DATA_WIDTH_A => DATA_WIDTH, + READ_LATENCY_A => 1, + READ_RESET_VALUE_A => "0", + RST_MODE_A => "SYNC", + USE_MEM_INIT => 1, + WAKEUP_TIME => "disable_sleep", + WRITE_DATA_WIDTH_A => DATA_WIDTH, + WRITE_MODE_A => "read_first" + ) + port map ( + dbiterra => open, + douta => read_data, + sbiterra => open, + addra => addr, + clka => clk, + dina => write_data, + ena => (ren or wen), + injectdbiterra => '0', + injectsbiterra => '0', + regcea => '1', + rsta => '0', + sleep => '0', + wea => wen + ); + +end architecture; \ No newline at end of file diff --git a/syn/labor-mst.xpr b/syn/labor-mst.xpr index 46e35cf..07753bb 100644 --- a/syn/labor-mst.xpr +++ b/syn/labor-mst.xpr @@ -41,13 +41,13 @@