* Moved config/constants to central package
* Made cap of addsub selectable via signal
* Added debug reporting
- MAX ADC Input 1
- MAX ADC Input 2
- MAX Scaler output
- MAX DAC Output
* Added Async FIFO
* Added Simple Dual Port RAM
* Added Feedback Controller
* Added Xillybus Link
* Moved testbenches to seperate directory
This commit is contained in:
parent
aa53591056
commit
779cd73e8d
213
src/UNUSED/memory_mapped_registers.vhd
Normal file
213
src/UNUSED/memory_mapped_registers.vhd
Normal file
@ -0,0 +1,213 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity memory_mapped_registers is
|
||||
port (
|
||||
clk : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
--***AXI4-LITE INTERFACE***
|
||||
-- WRITE ADDRESS CHANNEL
|
||||
AWVALID : in std_logic;
|
||||
AWREADY : out std_logic;
|
||||
AWADDR : in std_logic_vector(1 downto 0);
|
||||
AWPROT : in std_logic_vector(2 downto 0);
|
||||
-- WRITE DATA CHANNEL
|
||||
WVALID : in std_logic;
|
||||
WREADY : out std_logic;
|
||||
WDATA : in std_logic_vector(31 downto 0);
|
||||
WSTRB : in std_logic_vector(3 downto 0);
|
||||
-- WRITE RESPONSE CHANNEL
|
||||
BVALID : out std_logic;
|
||||
BREADY : in std_logic;
|
||||
BRESP : out std_logic_vector(1 downto 0);
|
||||
-- READ ADDRESS CHANNEL
|
||||
ARVALID : in std_logic;
|
||||
ARREADY : out std_logic;
|
||||
ARADDR : in std_logic_vector(1 downto 0);
|
||||
ARPROT : in std_logic_vector(2 downto 0);
|
||||
-- READ DATA CHANNEL
|
||||
RVALID : out std_logic;
|
||||
RREADY : in std_logic;
|
||||
RDATA : out std_logic_vector(31 downto 0);
|
||||
RRESP : out std_logic_vector(1 downto 0);
|
||||
|
||||
-- DEBUG
|
||||
reset_debug : out std_logic;
|
||||
adc_data1_max : in std_logic_vector(11 downto 0);
|
||||
adc_data2_max : in std_logic_vector(11 downto 0);
|
||||
scaler_max : in std_logic_vector(15 downto 0);
|
||||
dac_max : in std_logic_vector(15 downto 0)
|
||||
|
||||
-- DYNAMIC CONFIGURATION
|
||||
addsub_mode : out std_logic;
|
||||
delay : out std_logic_vector(7 downto 0);
|
||||
factor : out std_logic_vector(3 downto 0);
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture arch of memory_mapped_registers is
|
||||
|
||||
--*****TYPE DECLARATION*****
|
||||
type WRITE_STAGE_TYPE is (WRITE_ADDR, WRITE_DATA, WRITE_RESP);
|
||||
type READ_STAGE_TYPE is (READ_ADDR, READ_DATA);
|
||||
|
||||
--*****SIGNAL DECLARATION*****
|
||||
signal read_stage, read_stage_next : READ_STAGE_TYPE := READ_ADDR;
|
||||
signal write_stage, write_stage_next : WRITE_STAGE_TYPE := WRITE_ADDR;
|
||||
signal arready_next, arready, addsub_mode_next, rvalid, rvalid_next : std_logic := '0';
|
||||
signal awready, awready_next, wready, wready_next, bvalid, bvalid_next : std_logic := '0';
|
||||
signal rdata, rdata_next : std_logic_vector(31 downto 0) := (others => '0');
|
||||
signal factor_next : std_logic_vector(3 downto 0) := (others => '0');
|
||||
signal delay_next : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal awaddr, awaddr_next : std_logic_vector(1 downto 0) := (others => '0');
|
||||
signal reset_debug : std_logic := '0';
|
||||
|
||||
begin
|
||||
|
||||
BRESP <= (others => '0');
|
||||
RRESP <= (others => '0');
|
||||
AWREADY <= awready;
|
||||
AWADDR <= awaddr;
|
||||
WREADY <= wready;
|
||||
BVALID <= bvalid;
|
||||
ARREADY <= arready;
|
||||
RVALID <= rvalid;
|
||||
|
||||
read_ctrl : process(all)
|
||||
begin
|
||||
--DEFAULT VALUES
|
||||
read_stage_next <= read_stage;
|
||||
arready_next <= arready;
|
||||
rdata_next <= rdata;
|
||||
rvalid_next <= rvalid;
|
||||
|
||||
case(read_stage)
|
||||
when READ_ADDR =>
|
||||
arready_next <= '1';
|
||||
rvalid_next <= '0';
|
||||
if (ARVALID = '1') then
|
||||
case(to_integer(unsigned(ARADDR)))
|
||||
when 0 =>
|
||||
rdata_next <= (others => '0');
|
||||
rdata_next(30) <= addsub_mode_next;
|
||||
rdata_next(19 downto 16) <= factor_next;
|
||||
rdata_next(7 downto 0) <= delay_next;
|
||||
when 1 =>
|
||||
rdata_next <= (others => '0');
|
||||
rdata_next(11 downto 0) <= adc_data1_max;
|
||||
rdata_next(27 downto 16)<= adc_data2_max;
|
||||
when 2 =>
|
||||
rdata_next <= (others => '0');
|
||||
rdata_next(15 downto 0) <= dac_max;
|
||||
rdata_next(31 downto 16)<= scaler_max;
|
||||
when others =>
|
||||
rdata_next <= (others => '0');
|
||||
end case;
|
||||
arready_next <= '0';
|
||||
rvalid_next <= '1';
|
||||
read_stage_next <= READ_DATA;
|
||||
end if;
|
||||
when READ_DATA =>
|
||||
arready_next <= '0';
|
||||
rvalid_next <= '1';
|
||||
if (RREADY = '1') then
|
||||
arready_next <= '1';
|
||||
rvalid_next <= '0';
|
||||
read_stage_next <= READ_ADDR;
|
||||
end if;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
read_ctrl : process(all)
|
||||
begin
|
||||
--DEFAULT VALUES
|
||||
write_stage_next <= write_stage;
|
||||
awready_next <= awready;
|
||||
awaddr_next <= awaddr;
|
||||
wready_next <= wready;
|
||||
bvalid_next <= bvalid;
|
||||
reset_debug_next <= '0';
|
||||
|
||||
case(write_stage)
|
||||
when WRITE_ADDR =>
|
||||
awready_next <= '1';
|
||||
wready_next <= '0';
|
||||
bvalid <= '0';
|
||||
if (AWVALID = '1') then
|
||||
awaddr_next <= AWADDR;
|
||||
awready_next <= '0';
|
||||
wready_next <= '1';
|
||||
write_stage_next <= WRITE_DATA;
|
||||
end if;
|
||||
when WRITE_DATA =>
|
||||
awready_next <= '0';
|
||||
wready_next <= '1';
|
||||
bvalid <= '0';
|
||||
if (WVALID = '1') then
|
||||
case(to_integer(unsigned(awaddr)))
|
||||
when 0 =>
|
||||
reset_debug_next <= WDATA(31);
|
||||
addsub_mode_next <= WDATA(30);
|
||||
factor_next <= WDATA(19 downto 16);
|
||||
delay_next <= WDATA(7 downto 0);
|
||||
when others =>
|
||||
null;
|
||||
end case;
|
||||
wready_next <= '0';
|
||||
bvalid_next <= '1';
|
||||
write_stage_next <= WRITE_RESP;
|
||||
end if;
|
||||
when WRITE_RESP =>
|
||||
awready_next <= '0';
|
||||
wready_next <= '0';
|
||||
bvalid_next <= '1';
|
||||
if (BREADY = '1') then
|
||||
bvalid_next <= '0';
|
||||
awready_next <= '1';
|
||||
write_stage_next <= WRITE_ADDR;
|
||||
end if;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
sync : process(clk)
|
||||
begin
|
||||
if (rising_edge(clk)) then
|
||||
if (reset = '1') then
|
||||
awready <= '0';
|
||||
awaddr <= (others => '0');
|
||||
wready <= '0';
|
||||
bvalid <= '0';
|
||||
arready <= '0';
|
||||
rvalid <= '0';
|
||||
|
||||
read_stage <= READ_ADDR;
|
||||
write_stage <= WRITE_ADDR;
|
||||
|
||||
addsub_mode <= '0';
|
||||
factor <= (others => '0');
|
||||
delay <= (others => '0');
|
||||
|
||||
rdata <= (others => '0');
|
||||
else
|
||||
awready <= awready_next;
|
||||
awaddr <= awaddr_next;
|
||||
wready <= wready_next;
|
||||
bvalid <= bvalid_next;
|
||||
arready <= arready_next;
|
||||
rvalid <= rvalid_next;
|
||||
|
||||
read_stage <= read_stage_next;
|
||||
write_stage <= write_stage_next;
|
||||
|
||||
addsub_mode <= addsub_mode_next;
|
||||
factor <= factor_next;
|
||||
delay <= delay_next;
|
||||
|
||||
rdata <= rdata_next;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
@ -10,7 +10,7 @@ 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.
|
||||
-- If 'cap' is high, on Overfolw/Underflow conditions the result is capped at max/min value.
|
||||
|
||||
entity addsub is
|
||||
generic (
|
||||
@ -18,12 +18,13 @@ entity addsub is
|
||||
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)
|
||||
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;
|
||||
|
||||
@ -59,7 +60,7 @@ begin
|
||||
RES <= result;
|
||||
|
||||
--Overflow/Underflow
|
||||
if(carry = '1') then
|
||||
if(carry = '1' and cap = '1') then
|
||||
--ADD
|
||||
if(mode = '1') then
|
||||
--CAP AT MAX VALUE
|
||||
|
||||
90
src/async_fifo.vhd
Normal file
90
src/async_fifo.vhd
Normal file
@ -0,0 +1,90 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
Library xpm;
|
||||
use xpm.vcomponents.all;
|
||||
|
||||
-- Read and Write requests are ignored while the FIFO is in a reset state (reset busy signal high)
|
||||
|
||||
entity async_fifo is
|
||||
generic (
|
||||
DATA_WIDTH : integer := 32;
|
||||
FIFO_DEPTH : integer := 16; -- (16 - 4194304)
|
||||
PROG_EMPTY : integer := 3; -- MIN:3 MAX:(FIFO_DEPTH-3)
|
||||
PROG_FULL : integer := 13 -- MIN:3+CDC_SYNC_STAGES MAX:(FIFO_DEPTH-3)
|
||||
);
|
||||
port (
|
||||
wr_clk : in std_logic;
|
||||
rd_clk : in std_logic;
|
||||
reset : in std_logic; --wr_clk synchronous
|
||||
wen : in std_logic;
|
||||
ren : in std_logic;
|
||||
empty : out std_logic;
|
||||
almost_empty: out std_logic;
|
||||
prog_empty : out std_logic;
|
||||
full : out std_logic;
|
||||
almost_full : out std_logic;
|
||||
prog_full : out std_logic;
|
||||
wr_data : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
rd_data : out std_logic_vector(DATA_WIDTH-1 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture arch of async_fifo is
|
||||
|
||||
--*****SIGNAL DECLARATION*****
|
||||
signal rd_busy, wr_busy : std_logic := '0';
|
||||
|
||||
begin
|
||||
|
||||
xpm_fifo_async_inst : xpm_fifo_async
|
||||
generic map (
|
||||
CDC_SYNC_STAGES => 2,
|
||||
DOUT_RESET_VALUE => "0",
|
||||
ECC_MODE => "no_ecc",
|
||||
FIFO_MEMORY_TYPE => "auto",
|
||||
FIFO_READ_LATENCY => 1,
|
||||
FIFO_WRITE_DEPTH => FIFO_DEPTH,
|
||||
FULL_RESET_VALUE => 1,
|
||||
PROG_EMPTY_THRESH => PROG_EMPTY,
|
||||
PROG_FULL_THRESH => PROG_FULL,
|
||||
RD_DATA_COUNT_WIDTH => 1,
|
||||
READ_DATA_WIDTH => DATA_WIDTH,
|
||||
READ_MODE => "std",
|
||||
RELATED_CLOCKS => 0,
|
||||
USE_ADV_FEATURES => "0A0A",
|
||||
WAKEUP_TIME => 0,
|
||||
WRITE_DATA_WIDTH => DATA_WIDTH,
|
||||
WR_DATA_COUNT_WIDTH => 1
|
||||
)
|
||||
port map (
|
||||
almost_empty => almost_empty,
|
||||
almost_full => almost_full,
|
||||
data_valid => open,
|
||||
dbiterr => open,
|
||||
dout => rd_data,
|
||||
empty => empty,
|
||||
full => full,
|
||||
overflow => open,
|
||||
prog_empty => prog_empty,
|
||||
prog_full => prog_full,
|
||||
rd_data_count => open,
|
||||
rd_rst_busy => rd_busy,
|
||||
sbiterr => open,
|
||||
underflow => open,
|
||||
wr_ack => open,
|
||||
wr_data_count => open,
|
||||
wr_rst_busy => wr_busy,
|
||||
din => wr_data,
|
||||
injectdbiterr => '0',
|
||||
injectsbiterr => '0',
|
||||
rd_clk => rd_clk,
|
||||
rd_en => ren and (not rd_busy),
|
||||
rst => reset,
|
||||
sleep => '0',
|
||||
wr_clk => wr_clk,
|
||||
wr_en => wr_en and (not wr_busy)
|
||||
);
|
||||
|
||||
end architecture;
|
||||
@ -6,6 +6,12 @@ library UNISIM;
|
||||
use UNISIM.VCOMPONENTS.ALL;
|
||||
|
||||
entity clockgen is
|
||||
generic (
|
||||
CLKFBOUT_MULT : integer := 41;
|
||||
CLKIN1_PERIOD : real := 10.000000;
|
||||
CLKOUT0_DIVIDE : integer := 41;
|
||||
DIVCLK_DIVIDE : integer := 5
|
||||
);
|
||||
port (
|
||||
clk_in : in std_logic;
|
||||
clk_out : out std_logic
|
||||
@ -29,11 +35,11 @@ begin
|
||||
plle2_adv_inst: unisim.vcomponents.PLLE2_ADV
|
||||
generic map(
|
||||
BANDWIDTH => "OPTIMIZED",
|
||||
CLKFBOUT_MULT => 41,
|
||||
CLKFBOUT_MULT => CLKFBOUT_MULT,
|
||||
CLKFBOUT_PHASE => 0.000000,
|
||||
CLKIN1_PERIOD => 10.000000,
|
||||
CLKIN1_PERIOD => CLKIN1_PERIOD,
|
||||
CLKIN2_PERIOD => 0.000000,
|
||||
CLKOUT0_DIVIDE => 41,
|
||||
CLKOUT0_DIVIDE => CLKOUT0_DIVIDE,
|
||||
CLKOUT0_DUTY_CYCLE => 0.500000,
|
||||
CLKOUT0_PHASE => 0.000000,
|
||||
CLKOUT1_DIVIDE => 1,
|
||||
@ -52,7 +58,7 @@ begin
|
||||
CLKOUT5_DUTY_CYCLE => 0.500000,
|
||||
CLKOUT5_PHASE => 0.000000,
|
||||
COMPENSATION => "ZHOLD",
|
||||
DIVCLK_DIVIDE => 5,
|
||||
DIVCLK_DIVIDE => DIVCLK_DIVIDE,
|
||||
IS_CLKINSEL_INVERTED => '0',
|
||||
IS_PWRDWN_INVERTED => '0',
|
||||
IS_RST_INVERTED => '0',
|
||||
|
||||
@ -8,14 +8,14 @@ use ieee.numeric_std.all;
|
||||
-- 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].
|
||||
-- increased (which is unavoidable), and when it is decreased while the momentarily counter value is
|
||||
-- the same as the new delay value [single cycle glitch].
|
||||
|
||||
entity delay_line is
|
||||
generic (
|
||||
DATA_WIDTH : integer := 12;
|
||||
DELAY_WIDTH : integer := 8;
|
||||
MAX_DELAY : integer := 200
|
||||
MAX_DELAY : integer := 200;
|
||||
DELAY_WIDTH : integer := 8
|
||||
);
|
||||
port (
|
||||
clk : in std_logic;
|
||||
@ -31,16 +31,15 @@ architecture arch of delay_line is
|
||||
component single_port_ram is
|
||||
generic (
|
||||
ADDR_WIDTH : integer := 8;
|
||||
DATA_WIDTH : integer := 12;
|
||||
MEMORY_DEPTH : integer := 200
|
||||
DATA_WIDTH : integer := 12
|
||||
);
|
||||
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)
|
||||
wr_data : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
rd_data : out std_logic_vector(DATA_WIDTH-1 downto 0)
|
||||
);
|
||||
end component;
|
||||
|
||||
@ -54,30 +53,29 @@ begin
|
||||
ram_inst : single_port_ram
|
||||
generic map(
|
||||
ADDR_WIDTH => DELAY_WIDTH,
|
||||
DATA_WIDTH => DATA_WIDTH,
|
||||
MEMORY_DEPTH => MAX_DELAY
|
||||
DATA_WIDTH => DATA_WIDTH
|
||||
);
|
||||
port map(
|
||||
clk => clk,
|
||||
addr => cnt,
|
||||
addr => std_logic_vector(to_unsigned(cnt,DELAY_WIDTH)),
|
||||
wen => '1',
|
||||
ren => '1',
|
||||
write_data => data_in,
|
||||
read_data => memory_out
|
||||
wr_data => data_in,
|
||||
rd_data => memory_out
|
||||
);
|
||||
|
||||
cntrl : process(all)
|
||||
ctrl : process(all)
|
||||
begin
|
||||
-- DEFAULT VALUES
|
||||
cnt_next <= cnt;
|
||||
cnt_max_next <= cnt_max;
|
||||
|
||||
if(to_integer(unsigned(addr)) = 0) then
|
||||
if(to_integer(unsigned(delay)) = 0) then
|
||||
data_out <= data_in;
|
||||
else
|
||||
data_out <= memory_out;
|
||||
-- COUNT GENERATION
|
||||
cnt_max_next <= to_integer(unsigned(addr)) - 1;
|
||||
cnt_max_next <= to_integer(unsigned(delay)) - 1;
|
||||
if (cnt >= cnt_max) then
|
||||
cnt_next <= 0;
|
||||
else
|
||||
|
||||
75
src/dual_port_ram.vhd
Normal file
75
src/dual_port_ram.vhd
Normal file
@ -0,0 +1,75 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
Library xpm;
|
||||
use xpm.vcomponents.all;
|
||||
|
||||
-- NOTE: Simutanous reads and writes to the same addresses have to be prevented by external means!
|
||||
|
||||
entity dual_port_ram is
|
||||
generic (
|
||||
ADDR_WIDTH : integer := 4;
|
||||
DATA_WIDTH : integer := 16
|
||||
);
|
||||
port (
|
||||
wr_clk : in std_logic;
|
||||
rd_clk : in std_logic;
|
||||
rd_addr : in std_logic_vector(ADDR_WIDTH-1 downto 0);
|
||||
wr_addr : in std_logic_vector(ADDR_WIDTH-1 downto 0);
|
||||
wen : in std_logic;
|
||||
ren : in std_logic;
|
||||
wr_data : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
rd_data : out std_logic_vector(DATA_WIDTH-1 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture arch of dual_port_ram is
|
||||
|
||||
begin
|
||||
|
||||
xpm_memory_sdpram_inst : xpm_memory_sdpram
|
||||
generic map (
|
||||
ADDR_WIDTH_A => ADDR_WIDTH,
|
||||
ADDR_WIDTH_B => ADDR_WIDTH,
|
||||
AUTO_SLEEP_TIME => 0,
|
||||
BYTE_WRITE_WIDTH_A => DATA_WIDTH,
|
||||
CLOCKING_MODE => "independent_clock",
|
||||
ECC_MODE => "no_ecc",
|
||||
MEMORY_INIT_FILE => "none",
|
||||
MEMORY_INIT_PARAM => "0",
|
||||
MEMORY_OPTIMIZATION => "true",
|
||||
MEMORY_PRIMITIVE => "auto",
|
||||
MEMORY_SIZE => DATA_WIDTH*(2**ADDR_WIDTH),
|
||||
MESSAGE_CONTROL => 0,
|
||||
READ_DATA_WIDTH_B => DATA_WIDTH,
|
||||
READ_LATENCY_B => 1,
|
||||
READ_RESET_VALUE_B => "0",
|
||||
RST_MODE_A => "SYNC",
|
||||
RST_MODE_B => "SYNC",
|
||||
USE_EMBEDDED_CONSTRAINT => 1, --TODO
|
||||
USE_MEM_INIT => 1,
|
||||
WAKEUP_TIME => "disable_sleep",
|
||||
WRITE_DATA_WIDTH_A => DATA_WIDTH,
|
||||
WRITE_MODE_B => "no_change"
|
||||
)
|
||||
port map (
|
||||
dbiterrb => open,
|
||||
doutb => rd_data,
|
||||
sbiterrb => open,
|
||||
addra => wr_addr,
|
||||
addrb => rd_addr,
|
||||
clka => wr_clk,
|
||||
clkb => rd_clk,
|
||||
dina => wr_data,
|
||||
ena => wen,
|
||||
enb => ren,
|
||||
injectdbiterra => '0',
|
||||
injectsbiterra => '0',
|
||||
regceb => '1',
|
||||
rstb => '0',
|
||||
sleep => '0',
|
||||
wea => wen
|
||||
);
|
||||
|
||||
end architecture;
|
||||
124
src/feedback_controller.vhd
Normal file
124
src/feedback_controller.vhd
Normal file
@ -0,0 +1,124 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
use work.typedef_package.all;
|
||||
|
||||
-- Feedback Controller
|
||||
-- This entity reads from the config memory and applies the resepctive configuration when the relevant
|
||||
-- timestamp is reached or exceeded. The timer starts counting when a high level is detected in the 'sync'
|
||||
-- signal after a reset.
|
||||
-- NOTE: This entity is continuosly reading from the memory, except when the 'reset' signal is held high.
|
||||
|
||||
-- Config Mapping:
|
||||
-- mem_data(63) : Slot Enable
|
||||
-- mem_data(62) : Addsub_mode
|
||||
-- mem_data(61) : Add_input_mux
|
||||
-- mem_data(47-40) : delay
|
||||
-- mem_data(35-32) : factor
|
||||
-- mem_data(31-0) : timestamp
|
||||
|
||||
|
||||
entity feedback_controller is
|
||||
port (
|
||||
clk : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
sync : in std_logic;
|
||||
|
||||
mem_addr : out std_logic_vector(CONFIG_MEM_ADDR_WIDTH-1 downto 0);
|
||||
mem_ren : out std_logic;
|
||||
mem_data : in std_logic_vector(CONFIG_DATA_WIDTH-1 downto 0);
|
||||
|
||||
addsub_mode : out std_logic;
|
||||
add_input_mux : out std_logic;
|
||||
delay : out std_logic_vector(DELAY_WIDTH-1 downto 0);
|
||||
factor : out std_logic_vector(FACTOR_WIDTH-1 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture arch of feedback_controller is
|
||||
--*****CONSTANT DECLARATION*****
|
||||
constant inc : unsigned(CONFIG_MEM_ADDR_WIDTH-1 downto 0) := to_unsigned(1,CONFIG_MEM_ADDR_WIDTH);
|
||||
|
||||
--*****SIGNAL DECLARATION*****
|
||||
signal slot_nr, slot_nr_next : std_logic_vector(CONFIG_MEM_ADDR_WIDTH-1 downto 0) : (others => '0');
|
||||
signal timer : std_logic_vector(TIMESTAMP_WIDTH-1 downto 0) := (others => '0');
|
||||
signal sync_arrived : std_logic;
|
||||
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 factor_next, factor_sig : std_logic_vector(FACTOR_WIDTH-1 downto 0) := (others => '0');
|
||||
|
||||
begin
|
||||
|
||||
--OUTPUT SIGNALS
|
||||
-- Intermediate "_sig" signals needed because we cannot read from output pins
|
||||
mem_ren <= not reset;
|
||||
mem_addr <= slot_nr_next; -- Use 'next' signal to "asynchronously" set addr (Save 1 clock cycle)
|
||||
addsub_mode <= addsub_mode_sig;
|
||||
add_input_mux <= add_input_mux_sig;
|
||||
delay <= delay_sig;
|
||||
factor <= factor_sig;
|
||||
|
||||
ctrl : process(all)
|
||||
begin
|
||||
--DEFAULT
|
||||
slot_nr_next <= slot_nr;
|
||||
addsub_mode_next <= addsub_mode_sig;
|
||||
add_input_mux_next <= add_input_mux_sig;
|
||||
delay_next <= delay_sig;
|
||||
factor_next <= factor_sig;
|
||||
|
||||
if(mem_data(CONFIG_DATA_WIDTH-1) = '1') then
|
||||
-- If timestamp is reached (or exceeded), apply configuration and fetch next configuration
|
||||
-- slot
|
||||
if (unsigned(timer) >= unsigned(mem_data(TIMESTAMP_WIDTH-1 downto 0))) then
|
||||
addsub_mode_next <= mem_data(CONFIG_DATA_WIDTH-2);
|
||||
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);
|
||||
factor_next <= mem_data(TIMESTAMP_WIDTH+FACTOR_WIDTH-1 downto TIMESTAMP_WIDTH);
|
||||
|
||||
slot_nr_next <= std_logic_vector(unsigned(slot_nr) + inc);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
sync : process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if (reset = '1') then
|
||||
slot_nr <= (others => '0');
|
||||
addsub_mode_sig <= '0';
|
||||
add_input_mux_sig <= '0';
|
||||
delay_sig <= (others => '0');
|
||||
factor_sig <= (others => '0');
|
||||
else
|
||||
slot_nr <= slot_nr_next;
|
||||
addsub_mode_sig <= addsub_mode_next;
|
||||
add_input_mux_sig <= add_input_mux_next;
|
||||
delay_sig <= delay_next;
|
||||
factor_sig <= factor_next;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
timer : process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if (reset = '1') then
|
||||
timer <= (others => '0');
|
||||
sync_arrived <= '0';
|
||||
else
|
||||
if (sync_arrived = '0') then
|
||||
-- Wait for rising edge of sync pulse
|
||||
if (sync = '1') then
|
||||
sync_arrived <= '1';
|
||||
end if;
|
||||
else
|
||||
timer <= std_logic_vector(unsigned(timer) + inc);
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
@ -2,14 +2,23 @@ library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
use work.typedef_package.all;
|
||||
|
||||
-- Architecture
|
||||
--- ---------- ------ ------- ---
|
||||
-- --- ---------- ------ ------- ---
|
||||
--->|ADC|--->|Delay Line|--->|Scaler|--->|ADD/SUB|--->|DAC|--->
|
||||
--- ---------- ------ ------- ---
|
||||
-- --- ---------- ------ ------- ---
|
||||
-- ^
|
||||
--- ----- |
|
||||
--->|ADC|---------------------|Latch|--------
|
||||
--- -----
|
||||
-- --- ----- --- |
|
||||
--->|ADC|-------------------->|Latch|->| | |
|
||||
-- --- ----- |MUX|--
|
||||
-- GND--->| |
|
||||
-- ---
|
||||
|
||||
-- Feedback Loop
|
||||
-- This entity implements the feedback loop as defined above.
|
||||
-- In addition to that, this entity latches and provides various max values that can be used for debug
|
||||
-- purposes.
|
||||
|
||||
entity feedback_loop is
|
||||
port (
|
||||
@ -17,20 +26,27 @@ entity feedback_loop is
|
||||
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
|
||||
dac_ldac : out std_logic;
|
||||
-- DYNAMIC CONFIGURATION
|
||||
addsub_mode : in std_logic; -- (1=ADD, 0=SUB)
|
||||
add_input_mux : in std_logic; -- (1=ADC Input 2, 0=GND)
|
||||
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
|
||||
-- DEBUG
|
||||
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 entity;
|
||||
|
||||
architecture arch of feedback_loop is
|
||||
|
||||
--*****SIGNAL DECLARATION*****
|
||||
signal adc_data1, adc_data2 : std_logic_vector(11 downto 0) := (others => '0');
|
||||
signal adc_data1, adc_data2 : std_logic_vector(ADC_DATA_WIDTH-1 downto 0) := (others => '0');
|
||||
signal adc_done : std_logic := '0';
|
||||
|
||||
--*****COMPONENT DECLARATION*****
|
||||
@ -38,7 +54,7 @@ architecture arch of feedback_loop is
|
||||
generic(
|
||||
TRANSFER_CLK_COUNT : integer := 16;
|
||||
DELAY_CLK_CNT : integer := 2;
|
||||
DATA_BITS : integer := 12
|
||||
DATA_WIDTH : integer := 12
|
||||
);
|
||||
port (
|
||||
sclk : in std_logic; -- PMOD-AD1
|
||||
@ -47,8 +63,8 @@ architecture arch of feedback_loop is
|
||||
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);
|
||||
data1 : out std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
data2 : out std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
done : out std_logic
|
||||
);
|
||||
end component;
|
||||
@ -56,13 +72,13 @@ architecture arch of feedback_loop is
|
||||
component pmod_da3_ctrl is
|
||||
generic(
|
||||
TRANSFER_CLK_COUNT : integer := 16;
|
||||
DATA_BITS : integer := 16
|
||||
DATA_WIDTH : 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);
|
||||
data : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
cs_n : out std_logic;-- PMOD-DA3
|
||||
sdata : out std_logic;-- PMOD-DA3
|
||||
ldac : out std_logic;-- PMOD-DA3
|
||||
@ -90,12 +106,13 @@ architecture arch of feedback_loop is
|
||||
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)
|
||||
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;
|
||||
|
||||
@ -114,18 +131,19 @@ architecture arch of feedback_loop is
|
||||
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 delay_out, latch_out : std_logic_vector(ADC_DATA_WIDTH downto 0) := (others => '0');
|
||||
signal scaler_out, addsub_out, dac_max, scaler_max, inputA : std_logic_vector(DAC_DATA_WIDTH-1 downto 0) := (others => '0');
|
||||
signal scaler_done, addsub_done : std_logic := '0';
|
||||
signal adc_data1_max, adc_data2_max : std_logic_vector(ADC_DATA_WIDTH-1 downto 0) := (others => '0');
|
||||
|
||||
begin
|
||||
|
||||
--*****STAGE I*****
|
||||
adc_inst : pmod_ad1_ctrl
|
||||
generic map(
|
||||
TRANSFER_CLK_COUNT => 16,
|
||||
DELAY_CLK_CNT => 2,
|
||||
DATA_BITS => 12
|
||||
TRANSFER_CLK_COUNT => ADC_TRANSFER_CLK_COUNT,
|
||||
DELAY_CLK_CNT => ADC_DELAY_CLK_CNT,
|
||||
DATA_WIDTH => ADC_DATA_WIDTH
|
||||
)
|
||||
port map(
|
||||
sclk => clk,
|
||||
@ -142,9 +160,9 @@ begin
|
||||
--*****STAGE II*****
|
||||
delay_line_inst : delay_line
|
||||
generic map(
|
||||
DATA_WIDTH => 13,
|
||||
DELAY_WIDTH => 8,
|
||||
MAX_DELAY => 200
|
||||
DATA_WIDTH => ADC_DATA_WIDTH+1,
|
||||
DELAY_WIDTH => DELAY_WIDTH,
|
||||
MAX_DELAY => MAX_DELAY
|
||||
)
|
||||
port map(
|
||||
clk => clk,
|
||||
@ -156,13 +174,13 @@ begin
|
||||
--*****STAGE III*****
|
||||
scaler_inst : scaler
|
||||
generic map(
|
||||
DATA_WIDTH => 12,
|
||||
FACTOR_WIDTH => 4,
|
||||
DATA_WIDTH => ADC_DATA_WIDTH,
|
||||
FACTOR_WIDTH => FACTOR_WIDTH,
|
||||
PIPELINE_STAGES => 1
|
||||
)
|
||||
port map(
|
||||
clk => clk,
|
||||
data_in => delay_out(11 downto 0),
|
||||
data_in => delay_out(ADC_DATA_WIDTH-1 downto 0),
|
||||
factor => factor,
|
||||
data_out => scaler_out
|
||||
);
|
||||
@ -171,9 +189,9 @@ begin
|
||||
begin
|
||||
if (rising_edge(clk)) then
|
||||
if (reset = '1') then
|
||||
scaler_done <= (others => '0');
|
||||
scaler_done <= '0';
|
||||
else
|
||||
scaler_done <= delay_out(12);
|
||||
scaler_done <= delay_out(ADC_DATA_WIDTH);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
@ -190,17 +208,28 @@ begin
|
||||
end process;
|
||||
|
||||
--*****STAGE IV*****
|
||||
|
||||
mux: process(all)
|
||||
begin
|
||||
if (input_mux = '1') then
|
||||
inputA <= latch_out & "0000";
|
||||
else
|
||||
inputA <= (others => '0');
|
||||
end if;
|
||||
end process;
|
||||
|
||||
addsub_inst : addsub
|
||||
generic map(
|
||||
PIPELINE_STAGES => 1,
|
||||
DATA_WIDTH => 16
|
||||
DATA_WIDTH => DAC_DATA_WIDTH
|
||||
)
|
||||
port map(
|
||||
clk => clk,
|
||||
reset => reset,
|
||||
mode => addsub_mode,
|
||||
A => scaler_out,
|
||||
B => latch_out & "0000",
|
||||
cap => input_mux,
|
||||
A => inputA,
|
||||
B => scaler_out,
|
||||
RES => addsub_out
|
||||
);
|
||||
|
||||
@ -218,8 +247,8 @@ begin
|
||||
--*****STAGE V*****
|
||||
dac_inst : pmod_da3_ctrl
|
||||
generic map(
|
||||
TRANSFER_CLK_COUNT => 16,
|
||||
DATA_BITS => 16
|
||||
TRANSFER_CLK_COUNT => DAC_TRANSFER_CLK_COUNT,
|
||||
DATA_WIDTH => DAC_DATA_WIDTH
|
||||
)
|
||||
port map(
|
||||
sclk => clk,
|
||||
@ -232,4 +261,36 @@ begin
|
||||
done => open
|
||||
);
|
||||
|
||||
--*****DEBUG*****
|
||||
process(clk)
|
||||
begin
|
||||
if (rising_edge(clk)) then
|
||||
if (reset = '1' or reset_debug = '1') then
|
||||
adc_data1_max <= (others => '0');
|
||||
adc_data2_max <= (others => '0');
|
||||
dac_max <= (others => '0');
|
||||
scaler_max <= (others => '0');
|
||||
-- ADC MAX VALUES
|
||||
elsif (adc_done = '1') then
|
||||
if (to_integer(unsigned(adc_data1)) >= to_integer(unsigned(adc_data1_max))) then
|
||||
adc_data1_max <= adc_data1;
|
||||
elsif (to_integer(unsigned(adc_data2)) >= to_integer(unsigned(adc_data2_max))) then
|
||||
adc_data2_max <= adc_data2;
|
||||
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
|
||||
elsif (scaler_done = '1') then
|
||||
if (to_integer(unsigned(scaler_out)) >= to_integer(unsigned(scaler_max))) then
|
||||
scaler_max <= scaler_out;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
|
||||
|
||||
end architecture;
|
||||
@ -2,6 +2,8 @@ library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
use work.typedef_package.all;
|
||||
|
||||
entity open_loop is
|
||||
port (
|
||||
clk : in std_logic;
|
||||
@ -17,7 +19,7 @@ end entity;
|
||||
architecture arch of open_loop is
|
||||
|
||||
--*****SIGNAL DECLARATION*****
|
||||
signal interconnect : std_logic_vector(15 downto 0) := (others => '0');
|
||||
signal interconnect : std_logic_vector(DAC_DATA_WIDTH-1 downto 0) := (others => '0');
|
||||
signal adc_done : std_logic := '0';
|
||||
|
||||
--*****COMPONENT DECLARATION*****
|
||||
@ -25,7 +27,7 @@ architecture arch of open_loop is
|
||||
generic(
|
||||
TRANSFER_CLK_COUNT : integer := 16;
|
||||
DELAY_CLK_CNT : integer := 2;
|
||||
DATA_BITS : integer := 12
|
||||
DATA_WIDTH : integer := 12
|
||||
);
|
||||
port (
|
||||
sclk : in std_logic; -- PMOD-AD1
|
||||
@ -34,8 +36,8 @@ architecture arch of open_loop is
|
||||
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);
|
||||
data1 : out std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
data2 : out std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
done : out std_logic
|
||||
);
|
||||
end component;
|
||||
@ -43,13 +45,13 @@ architecture arch of open_loop is
|
||||
component pmod_da3_ctrl is
|
||||
generic(
|
||||
TRANSFER_CLK_COUNT : integer := 16;
|
||||
DATA_BITS : integer := 16
|
||||
DATA_WIDTH : 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);
|
||||
data : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
cs_n : out std_logic;-- PMOD-DA3
|
||||
sdata : out std_logic;-- PMOD-DA3
|
||||
ldac : out std_logic;-- PMOD-DA3
|
||||
@ -62,9 +64,9 @@ begin
|
||||
--*****COMPONENT INSTANTIATION*****
|
||||
adc : pmod_ad1_ctrl
|
||||
generic map(
|
||||
TRANSFER_CLK_COUNT => 16,
|
||||
DELAY_CLK_CNT => 2,
|
||||
DATA_BITS => 12
|
||||
TRANSFER_CLK_COUNT => ADC_TRANSFER_CLK_COUNT,
|
||||
DELAY_CLK_CNT => ADC_DELAY_CLK_CNT,
|
||||
DATA_WIDTH => ADC_DATA_WIDTH
|
||||
)
|
||||
port map(
|
||||
sclk => clk,
|
||||
@ -73,15 +75,15 @@ begin
|
||||
sdata2 => '0',
|
||||
enable => '1',
|
||||
cs_n => adc_cs_n,
|
||||
data1 => interconnect(15 downto 4),
|
||||
data1 => interconnect(DAC_DATA_WIDTH-1 downto DAC_DATA_WIDTH-ADC_DATA_WIDTH),
|
||||
data2 => open,
|
||||
done => adc_done
|
||||
);
|
||||
|
||||
dac : pmod_da3_ctrl
|
||||
generic map(
|
||||
TRANSFER_CLK_COUNT => 16,
|
||||
DATA_BITS => 16
|
||||
TRANSFER_CLK_COUNT => DAC_TRANSFER_CLK_COUNT,
|
||||
DATA_WIDTH => DAC_DATA_WIDTH
|
||||
)
|
||||
port map(
|
||||
sclk => clk,
|
||||
|
||||
@ -14,7 +14,7 @@ entity pmod_ad1_ctrl is
|
||||
generic(
|
||||
TRANSFER_CLK_COUNT : integer := 16;
|
||||
DELAY_CLK_CNT : integer := 2;
|
||||
DATA_BITS : integer := 12
|
||||
DATA_WIDTH : integer := 12
|
||||
);
|
||||
port (
|
||||
sclk : in std_logic; -- PMOD-AD1
|
||||
@ -23,8 +23,8 @@ entity pmod_ad1_ctrl is
|
||||
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);
|
||||
data1 : out std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
data2 : out std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
done : out std_logic
|
||||
);
|
||||
end entity;
|
||||
@ -35,9 +35,9 @@ architecture arch of pmod_ad1_ctrl is
|
||||
type STAGE_TYPE is (IDLE, TRANSFER, DELAY);
|
||||
|
||||
--*****SIGNAL DECLARATIONS*****
|
||||
signal buf1, buf2, buf1_next, buf2_next : std_logic_vector(DATA_BITS-1 downto 0) := (others => '0');
|
||||
signal buf1, buf2, buf1_next, buf2_next : std_logic_vector(DATA_WIDTH-1 downto 0) := (others => '0');
|
||||
signal stage, stage_next : STAGE_TYPE := IDLE;
|
||||
signal count, count_next : integer range 0 to 16 := 0;
|
||||
signal count, count_next : integer range 0 to TRANSFER_CLK_COUNT := 0;
|
||||
-- Output Signals
|
||||
signal cs_n_next : std_logic := '1';
|
||||
signal done_next : std_logic := '0';
|
||||
@ -65,8 +65,8 @@ begin
|
||||
-- to shift out the initial zero bits of the tranfer.
|
||||
when TRANSFER =>
|
||||
-- Shift Bits into buffer
|
||||
buf1_next <= buf1(DATA_BITS-2 downto 0) & sdata1;
|
||||
buf2_next <= buf2(DATA_BITS-2 downto 0) & sdata2;
|
||||
buf1_next <= buf1(DATA_WIDTH-2 downto 0) & sdata1;
|
||||
buf2_next <= buf2(DATA_WIDTH-2 downto 0) & sdata2;
|
||||
cs_n_next <= '0';
|
||||
if (count = TRANSFER_CLK_COUNT) then
|
||||
stage_next <= DELAY;
|
||||
|
||||
@ -13,13 +13,13 @@ use ieee.numeric_std.all;
|
||||
entity pmod_da3_ctrl is
|
||||
generic(
|
||||
TRANSFER_CLK_COUNT : integer := 16;
|
||||
DATA_BITS : integer := 16
|
||||
DATA_WIDTH : 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);
|
||||
data : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
cs_n : out std_logic;-- PMOD-DA3
|
||||
sdata : out std_logic;-- PMOD-DA3
|
||||
ldac : out std_logic;-- PMOD-DA3
|
||||
@ -33,9 +33,9 @@ architecture arch of pmod_da3_ctrl is
|
||||
type STAGE_TYPE is (IDLE, TRANSFER);
|
||||
|
||||
--*****SIGNAL DECLARATIONS*****
|
||||
signal buf, buf_next : std_logic_vector(DATA_BITS-1 downto 0) := (others => '0');
|
||||
signal buf, buf_next : std_logic_vector(DATA_WIDTH-1 downto 0) := (others => '0');
|
||||
signal stage, stage_next : STAGE_TYPE := IDLE;
|
||||
signal count, count_next : integer range 0 to 16 := 0;
|
||||
signal count, count_next : integer range 0 to TRANSFER_CLK_COUNT := 0;
|
||||
-- Output Signals
|
||||
signal cs_n_next : std_logic := '1';
|
||||
signal sdata_next : std_logic := '0';
|
||||
@ -63,13 +63,13 @@ begin
|
||||
cs_n_next <= '0';
|
||||
count_next <= 1;
|
||||
-- Shift first bit into DAC
|
||||
buf_next <= data(DATA_BITS-2 downto 0) & '0';
|
||||
sdata_next <= data(DATA_BITS-1);
|
||||
buf_next <= data(DATA_WIDTH-2 downto 0) & '0';
|
||||
sdata_next <= data(DATA_WIDTH-1);
|
||||
end if;
|
||||
when TRANSFER =>
|
||||
-- Shift Bits into DAC
|
||||
buf_next <= buf(DATA_BITS-2 downto 0) & '0';
|
||||
sdata_next <= buf(DATA_BITS-1);
|
||||
buf_next <= buf(DATA_WIDTH-2 downto 0) & '0';
|
||||
sdata_next <= buf(DATA_WIDTH-1);
|
||||
cs_n_next <= '0';
|
||||
if (count = TRANSFER_CLK_COUNT) then
|
||||
cs_n_next <= '1';
|
||||
|
||||
@ -8,16 +8,15 @@ use xpm.vcomponents.all;
|
||||
entity single_port_ram is
|
||||
generic (
|
||||
ADDR_WIDTH : integer := 8;
|
||||
DATA_WIDTH : integer := 12;
|
||||
MEMORY_DEPTH : integer := 200
|
||||
DATA_WIDTH : integer := 12
|
||||
);
|
||||
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)
|
||||
wr_data : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
rd_data : out std_logic_vector(DATA_WIDTH-1 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
@ -35,7 +34,7 @@ begin
|
||||
MEMORY_INIT_PARAM => "0",
|
||||
MEMORY_OPTIMIZATION => "true",
|
||||
MEMORY_PRIMITIVE => "auto",
|
||||
MEMORY_SIZE => DATA_WIDTH*MEMORY_DEPTH,
|
||||
MEMORY_SIZE => DATA_WIDTH*(2**ADDR_WIDTH),
|
||||
MESSAGE_CONTROL => 0,
|
||||
READ_DATA_WIDTH_A => DATA_WIDTH,
|
||||
READ_LATENCY_A => 1,
|
||||
@ -48,11 +47,11 @@ begin
|
||||
)
|
||||
port map (
|
||||
dbiterra => open,
|
||||
douta => read_data,
|
||||
douta => rd_data,
|
||||
sbiterra => open,
|
||||
addra => addr,
|
||||
clka => clk,
|
||||
dina => write_data,
|
||||
dina => wr_data,
|
||||
ena => (ren or wen),
|
||||
injectdbiterra => '0',
|
||||
injectsbiterra => '0',
|
||||
|
||||
@ -39,7 +39,7 @@ architecture arch of top is
|
||||
);
|
||||
end component;
|
||||
|
||||
--*****DIGNAL DECLARATION*****
|
||||
--*****SIGNAL DECLARATION*****
|
||||
signal clk_20 : std_logic := '0';
|
||||
|
||||
begin
|
||||
|
||||
65
src/typedef_package.vhd
Normal file
65
src/typedef_package.vhd
Normal file
@ -0,0 +1,65 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
package typedef_package is
|
||||
|
||||
--*****CONSTANT DECLARATIONS*****
|
||||
-- FIXED
|
||||
constant ADC_DATA_WIDTH : integer := 12;--*
|
||||
constant DAC_DATA_WIDTH : integer := 16;--*
|
||||
|
||||
--* If these values are changed, the signal mappings in 'xillybus_link' have to be updated.
|
||||
|
||||
constant ADC_TRANSFER_CLK_COUNT : integer := 16;
|
||||
constant ADC_DELAY_CLK_CNT : integer := 2;
|
||||
constant DAC_TRANSFER_CLK_COUNT : integer := 16;
|
||||
|
||||
constant MAX_DELAY : integer := 200;
|
||||
constant DELAY_WIDTH : integer := 8; --at least log2(MAX_DELAY)
|
||||
constant FACTOR_WIDTH : integer := 4;
|
||||
|
||||
constant TIMESTAMP_WIDTH : integer := 32;
|
||||
|
||||
--XILLYBUS
|
||||
constant DEBUG_FIFO_DATA_WIDTH : integer := 32;
|
||||
constant DEBUG_FIFO_DEPTH : integer := 16;
|
||||
|
||||
constant CONFIG_MEM_DATA_WIDTH : integer := 32;
|
||||
constant CONFIG_DATA_WIDTH : integer := CONFIG_MEM_DATA_WIDTH*2;
|
||||
constant CONFIG_MEM_ADDR_WIDTH : integer := 15;
|
||||
|
||||
|
||||
--***CLOCKGEN SETTINGS***
|
||||
--100 MHz IN, 20 MHz OUT
|
||||
constant CLKFBOUT_MULT : integer := 41;
|
||||
constant CLKIN1_PERIOD : real := 10.000000;
|
||||
constant CLKOUT0_DIVIDE : integer := 41;
|
||||
constant DIVCLK_DIVIDE : integer := 5;
|
||||
|
||||
--TODO: 3-stage sync to delay write-mode 1 clk cycle
|
||||
|
||||
--*****FUNCTION DECLARATIONS*****
|
||||
function log2c(constant value : in integer) return integer;
|
||||
|
||||
end package;
|
||||
|
||||
package body typedef_package is
|
||||
|
||||
|
||||
--*****FUNCTION DEFINITIONS*****
|
||||
function log2c(constant value : in integer) return integer is
|
||||
variable ret_value : integer;
|
||||
variable cur_value : integer;
|
||||
begin
|
||||
ret_value := 0;
|
||||
cur_value := 1;
|
||||
while cur_value < value loop
|
||||
ret_value := ret_value + 1;
|
||||
cur_value := cur_value * 2;
|
||||
end loop;
|
||||
return ret_value;
|
||||
end function log2c;
|
||||
|
||||
|
||||
end package body;
|
||||
214
src/xillybus_link.vhd
Normal file
214
src/xillybus_link.vhd
Normal file
@ -0,0 +1,214 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
use work.typedef_package.all;
|
||||
|
||||
-- Xillybus Link
|
||||
-- This entity is the link between the xillybus IP core, and the rest of the FPGA logic.
|
||||
-- This entity contains asynchronous FIFOs and RAMs handling the clock domain crossing between
|
||||
-- the xillybus and the FPGA logic.
|
||||
|
||||
-- The current xillybus IP core is configured for a 32-bit FPGA-to-HOST FIFO used for sending debug
|
||||
-- stats to the host every "DEBUG_SEND_INTERVAL" clock cycles, and 32-bit HOST-to-FPGA 16-bit address
|
||||
-- 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.
|
||||
|
||||
-- NOTE: It has to be made sure that the read and write port to not access the smae address at the same
|
||||
-- time
|
||||
|
||||
entity xillybus_link is
|
||||
generic (
|
||||
DEBUG_SEND_INTERVAL : integer := 20000000
|
||||
);
|
||||
port (
|
||||
--***XILLYBUS IF***
|
||||
xillybus_clk : in std_logic;
|
||||
-- FIFO
|
||||
fifo_rd_data : out std_logic_vector(DEBUG_FIFO_DATA_WIDTH-1 downto 0);
|
||||
fifo_ren : in std_logic;
|
||||
fifo_empty : out std_logic;
|
||||
-- RAM
|
||||
mem_addr : in std_logic_vector(CONFIG_MEM_ADDR_WIDTH downto 0);
|
||||
mem_wr_data : in std_logic_vector(CONFIG_MEM_DATA_WIDTH-1 downto 0);
|
||||
mem_wen : in std_logic;
|
||||
--***FPGA IF***
|
||||
fpga_clk : in std_logic;
|
||||
reset : in std_logic;
|
||||
-- Dynamic Configuration
|
||||
config_addr : in std_logic_vector(CONFIG_MEM_ADDR_WIDTH-1 downto 0);
|
||||
config_ren : in std_logic;
|
||||
config_data : out std_logic_vector(CONFIG_DATA_WIDTH-1 downto 0);
|
||||
-- DEBUG
|
||||
adc_data1_max : in std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
|
||||
adc_data2_max : in std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
|
||||
scaler_max : in std_logic_vector(DAC_DATA_WIDTH-1 downto 0);
|
||||
dac_max : in std_logic_vector(DAC_DATA_WIDTH-1 downto 0)
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture arch of xillybus_link is
|
||||
|
||||
--*****COMPONENT DECLARATION*****
|
||||
component dual_port_ram is
|
||||
generic (
|
||||
ADDR_WIDTH : integer := 8;
|
||||
DATA_WIDTH : integer := 16;
|
||||
MEMORY_DEPTH : integer := 20
|
||||
);
|
||||
port (
|
||||
wr_clk : in std_logic;
|
||||
rd_clk : in std_logic;
|
||||
rd_addr : in std_logic_vector(ADDR_WIDTH-1 downto 0);
|
||||
wr_addr : in std_logic_vector(ADDR_WIDTH-1 downto 0);
|
||||
wen : in std_logic;
|
||||
ren : in std_logic;
|
||||
wr_data : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
rd_data : out std_logic_vector(DATA_WIDTH-1 downto 0)
|
||||
);
|
||||
end component;
|
||||
|
||||
component async_fifo is
|
||||
generic (
|
||||
DATA_WIDTH : integer := 32;
|
||||
FIFO_DEPTH : integer := 16; -- (16 - 4194304)
|
||||
PROG_EMPTY : integer := 3; -- MIN:3 MAX:(FIFO_DEPTH-3)
|
||||
PROG_FULL : integer := 13 -- MIN:3+CDC_SYNC_STAGES MAX:(FIFO_DEPTH-3)
|
||||
);
|
||||
port (
|
||||
wr_clk : in std_logic;
|
||||
rd_clk : in std_logic;
|
||||
reset : in std_logic; --wr_clk synchronous
|
||||
wen : in std_logic;
|
||||
ren : in std_logic;
|
||||
empty : out std_logic;
|
||||
almost_empty: out std_logic;
|
||||
prog_empty : out std_logic;
|
||||
full : out std_logic;
|
||||
almost_full : out std_logic;
|
||||
prog_full : out std_logic;
|
||||
wr_data : in std_logic_vector(DATA_WIDTH-1 downto 0);
|
||||
rd_data : out std_logic_vector(DATA_WIDTH-1 downto 0)
|
||||
);
|
||||
end component;
|
||||
|
||||
--*****TYPE DEFINITION*****
|
||||
type STAGE_TYPE is (WAIT_COUNTER, WAIT_FIFO, SEND1, SEND2);
|
||||
|
||||
--*****SIGNAL DEFINITION*****
|
||||
signal cnt, cnt_next : integer range 0 to DEBUG_SEND_INTERVAL := 0;
|
||||
signal stage : STAGE_TYPE := WAIT_COUNTER;
|
||||
signal fifo_almost_full, fifo_wen : std_logic := '0';
|
||||
signal fifo_wr_data : std_logic_vector(DEBUG_FIFO_DATA_WIDTH-1 downto 0) := (others => '0');
|
||||
|
||||
begin
|
||||
|
||||
--*****COMPONENT INSTANTIATION*****
|
||||
config_mem_high : dual_port_ram
|
||||
generic map (
|
||||
ADDR_WIDTH => CONFIG_MEM_ADDR_WIDTH,
|
||||
DATA_WIDTH => CONFIG_MEM_DATA_WIDTH
|
||||
)
|
||||
port map (
|
||||
wr_clk => xillybus_clk,
|
||||
rd_clk => fpga_clk,
|
||||
rd_addr => config_addr,
|
||||
wr_addr => mem_addr(CONFIG_MEM_ADDR_WIDTH downto 1),
|
||||
wen => mem_wen and (not mem_addr(0)), -- Only even adresses
|
||||
ren => config_ren,
|
||||
wr_data => mem_wr_data,
|
||||
rd_data => config_data(CONFIG_DATA_WIDTH-1 downto CONFIG_MEM_DATA_WIDTH)
|
||||
);
|
||||
|
||||
config_mem_low : dual_port_ram
|
||||
generic map (
|
||||
ADDR_WIDTH => CONFIG_MEM_ADDR_WIDTH,
|
||||
DATA_WIDTH => CONFIG_MEM_DATA_WIDTH
|
||||
)
|
||||
port map (
|
||||
wr_clk => xillybus_clk,
|
||||
rd_clk => fpga_clk,
|
||||
rd_addr => config_addr,
|
||||
wr_addr => mem_addr(CONFIG_MEM_ADDR_WIDTH downto 1),
|
||||
wen => mem_wen and (mem_addr(0)), -- Only odd adresses
|
||||
ren => config_ren,
|
||||
wr_data => mem_wr_data,
|
||||
rd_data => config_data(CONFIG_MEM_DATA_WIDTH-1 downto 0)
|
||||
);
|
||||
|
||||
|
||||
debug_fifo : async_fifo
|
||||
generic map (
|
||||
DATA_WIDTH => DEBUG_FIFO_DATA_WIDTH,
|
||||
FIFO_DEPTH => DEBUG_FIFO_DEPTH
|
||||
)
|
||||
port map(
|
||||
wr_clk => fpga_clk,
|
||||
rd_clk => xillybus_clk,
|
||||
reset => reset,
|
||||
wen => fifo_wen,
|
||||
ren => fifo_ren,
|
||||
empty => fifo_empty,
|
||||
almost_empty=> open,
|
||||
prog_empty => open,
|
||||
full => open,
|
||||
almost_full => fifo_almost_full,
|
||||
prog_full => open,
|
||||
wr_data => fifo_wr_data,
|
||||
rd_data => fifo_rd_data
|
||||
);
|
||||
|
||||
debug_prc : process(all)
|
||||
begin
|
||||
-- DEFAULT VALUES
|
||||
stage_next <= stage;
|
||||
cnt_next <= cnt;
|
||||
fifo_wen <= '0';
|
||||
fifo_wr_data<= (others => '0');
|
||||
|
||||
case (stage)
|
||||
when WAIT_COUNTER =>
|
||||
if(cnt = DEBUG_SEND_INTERVAL) then
|
||||
if(fifo_almost_full = '1') then
|
||||
stage_next => WAIT_FIFO;
|
||||
else
|
||||
stage_next => SEND1;
|
||||
end if;
|
||||
else
|
||||
cnt_next => cnt + 1;
|
||||
end if;
|
||||
when WAIT_FIFO =>
|
||||
if(fifo_almost_full = '0') then
|
||||
stage_next => SEND1;
|
||||
end if;
|
||||
when SEND1 =>
|
||||
fifo_wen <= '1';
|
||||
fifo_wr_data(11 downto 0) <= adc_data1_max;
|
||||
fifo_wr_data(27 downto 16) <= adc_data2_max;
|
||||
|
||||
stage_next <= SEND2;
|
||||
when SEND2 =>
|
||||
fifo_wen <= '1';
|
||||
fifo_wr_data(15 downto 0) <= dac_max;
|
||||
fifo_wr_data(31 downto 16) <= scaler_max;
|
||||
|
||||
stage_next <= WAIT_COUNTER;
|
||||
cnt_next <= 0;
|
||||
end case;
|
||||
end process;
|
||||
|
||||
|
||||
sync : process(fpga_clk)
|
||||
begin
|
||||
if rising_edge(fpga_clk) then
|
||||
if(reset = '1') then
|
||||
stage <= WAIT_COUNTER;
|
||||
cnt <= 0;
|
||||
else
|
||||
stage <= stage_next;
|
||||
cnt <= cnt_next;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
end architecture;
|
||||
Loading…
Reference in New Issue
Block a user