Commit 227bbaa4 authored by David Cussans's avatar David Cussans

Checking in current code.

Some documentation changes

Changed Slow control shift register to have optional reset before shifting data.
( Still at least one bug - doesn't store data shifted out of MAROC correctly )

Added register stages to risingEdgeDetect




git-svn-id: https://svn2.phy.bris.ac.uk/svn/uob-hep-pc049a/trunk@35 e1591323-3689-4d5a-aa31-d1a7cbdc5706
parent e48ef112
......@@ -7,6 +7,7 @@ files = [
# "clocks_s6_extclk.vhd" ,
"clocks_s6_basex.vhd" ,
"counterWithReset_rtl.vhd" ,
"ipbusCounters_rtl.vhd",
"fineTimeStamp_rtl.vhd" ,
"marocTriggerGenerator_rtl.vhd" ,
# "generate_test_signals.vhd" ,
......@@ -32,6 +33,10 @@ files = [
"singleFineTimeStamp_rtl.vhd" ,
"stretchPulse_rtl.vhd" ,
"timeStampDPRAM_rtl.vhd",
"fallingEdgeDetect_rtl.vhd",
"risingEdgeDetect_rtl.vhd",
# "dpram.vhdl" ,
"ipbusDPRAM.vhdl"
"ipbusDPRAM.vhdl",
"synchronizeRegisters_rtl.vhd",
"i2c_master_rtl.vhd"
]
......@@ -56,18 +56,25 @@ ENTITY counterWithReset IS
END counterWithReset;
ARCHITECTURE rtl OF counterWithReset IS
SIGNAL s_result_reg : UNSIGNED ( g_COUNTER_WIDTH-1 downto 0);
SIGNAL s_result_reg : UNSIGNED ( g_COUNTER_WIDTH-1 downto 0);
signal s_reset_d1 , s_reset_d2 : std_logic := '0';
BEGIN
PROCESS (clock_i)
BEGIN
IF (clock_i'event AND clock_i = '1' ) THEN
IF (reset_i = '1') THEN
s_result_reg <= (others => '0');
ELSIF (enable_i='1') THEN
s_result_reg <= s_result_reg + 1;
END IF;
END IF;
END PROCESS;
PROCESS (clock_i)
BEGIN
IF rising_edge(clock_i) THEN
result_o <= STD_LOGIC_VECTOR(s_result_reg);
-- Put some register stages in reset to ease timing
s_reset_d1 <= reset_i;
s_reset_d2 <= s_reset_d1;
IF (s_reset_d2 = '1') THEN
s_result_reg <= (others => '0');
ELSIF (enable_i='1') THEN
s_result_reg <= s_result_reg + 1;
END IF;
END IF;
END PROCESS;
result_o <= STD_LOGIC_VECTOR(s_result_reg);
END rtl;
--=============================================================================
--! @file i2c_master_rtl.vhd
--=============================================================================
--
-------------------------------------------------------------------------------
-- --
-- University of Bristol, High Energy Physics Group.
-- --
------------------------------------------------------------------------------- --
-- VHDL Architecture work.i2c_master.rtl
--
--! @brief Wraps the Wishbone I2C master in a wrapper where the IPBus signals\n
--! are bundled together in a record\n
--
--! @author David Cussans , David.Cussans@bristol.ac.uk
--
--! @date 17:22:12 11/30/12
--
--! @version v0.1
--
--! @details
--!
--!
--! <b>Dependencies:</b>\n
--!
--! <b>References:</b>\n
--!
--! <b>Modified by:</b>\n
--! Author:
-------------------------------------------------------------------------------
--! \n\n<b>Last changes:</b>\n
-------------------------------------------------------------------------------
--! @todo <next thing to do> \n
--! <another thing to do> \n
--
--------------------------------------------------------------------------------
--
-- Created using using Mentor Graphics HDL Designer(TM) 2010.3 (Build 21)
--
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
USE work.ipbus.all;
ENTITY i2c_master IS
PORT(
i2c_scl_i : IN std_logic;
i2c_sda_i : IN std_logic;
ipbus_clk_i : IN std_logic;
ipbus_i : IN ipb_wbus; -- Signals from IPBus core to slave
ipbus_reset_i : IN std_logic;
i2c_scl_enb_o : OUT std_logic;
i2c_sda_enb_o : OUT std_logic;
ipbus_o : OUT ipb_rbus -- signals from slave to IPBus core
);
-- Declarations
END ENTITY i2c_master ;
--
ARCHITECTURE rtl OF i2c_master IS
--signal s_i2c_scl, s_i2c_scl_o, s_i2c_scl_enb, s_i2c_sda, s_i2c_sda_enb : std_logic ;
BEGIN
--i2c_scl_b <= s_i2c_scl when (s_i2c_scl_enb = '0') else 'Z';
--i2c_sda_b <= s_i2c_sda when (s_i2c_sda_enb = '0') else 'Z';
i2c_interface: entity work.i2c_master_top port map(
wb_clk_i => ipbus_clk_i,
wb_rst_i => ipbus_reset_i,
arst_i => '1',
wb_adr_i => ipbus_i.ipb_addr(2 downto 0),
wb_dat_i => ipbus_i.ipb_wdata(7 downto 0),
wb_dat_o => ipbus_o.ipb_rdata(7 downto 0),
wb_we_i => ipbus_i.ipb_write,
wb_stb_i => ipbus_i.ipb_strobe,
wb_cyc_i => '1',
wb_ack_o => ipbus_o.ipb_ack,
wb_inta_o => open,
scl_pad_i => i2c_scl_i,
scl_pad_o => open,
scl_padoen_o => i2c_scl_enb_o,
sda_pad_i => i2c_sda_i,
sda_pad_o => open,
sda_padoen_o => i2c_sda_enb_o
);
ipbus_o.ipb_rdata(31 downto 8) <= ( others => '0');
ipbus_o.ipb_err <= '0'; -- never return an error.
END ARCHITECTURE rtl;
--! @file
--! @brief IPBus interface to a number of counters.
--! @details Read - contents of counter , write - reset
--! @author David Cussans
--! Institute: University of Bristol
--! @date May 2015
--
--! Modifications:
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.ipbus.all;
use work.ipbus_reg_types.all;
entity ipbusCounters is
generic (
g_DATAWIDTH : integer := 32; --! Width of word
g_ADDRWIDTH : integer := 6 --! number of counters = 2^g_ADDRWIDTH
);
port (
counter_clk_i : in std_logic; --! rising edge active
triggers_i : in std_logic_vector( (2**g_ADDRWIDTH)-1 downto 0);
-- IPBus for read-port
ipb_clk_i : in std_logic;
reset_i : in std_logic;
ipbus_i : in ipb_wbus;
ipbus_o : out ipb_rbus
);
end ipbusCounters;
architecture rtl of ipbusCounters is
-- type t_counterArray is array(natural range <>) of std_logic_vector(g_DATAWIDTH-1 downto 0);
-- signal s_counters , s_counters_ipb : t_counterArray( (2**g_ADDRWIDTH)-1 downto 0) := ( others => ( others => '0')); -- registers to store counters
signal s_counters , s_counters_ipb : ipb_reg_v( (2**g_ADDRWIDTH)-1 downto 0) := ( others => ( others => '0')); -- registers to store counters
signal s_resetLines : std_logic_vector( (2**g_ADDRWIDTH)-1 downto 0) := ( others => '0'); --! Take high to reset counter
signal s_risingEdge : std_logic_vector( triggers_i'range) := ( others => '0'); -- pulses high for one clock cycle on rising edge of triggers_i
signal s_counterIndex : integer := 0;
signal s_ipbus_ack : std_logic := '0'; -- ! Acknowledge for IPBus strobe
begin
gen_counters: for i_counter in 0 to (2**g_ADDRWIDTH)-1 generate
-- Look for rising edge on input lines
inst_edge_detect: entity work.risingEdgeDetect
port map (
clk_i => counter_clk_i,
level_i => triggers_i(i_counter),
pulse_o => s_risingEdge(i_counter)
);
inst_counter: entity work.counterWithReset
generic map (
g_COUNTER_WIDTH => g_DATAWIDTH)
port map (
clock_i => counter_clk_i,
reset_i => s_resetLines(i_counter),
enable_i => s_risingEdge(i_counter),
result_o => s_counters(i_counter)
);
end generate gen_counters;
-- Cross from counter clock to IPBus clock domain
inst_sync_reg: entity work.synchronizeRegisters
generic map (
g_NUM_REGISTERS => 2**g_ADDRWIDTH)
port map (
clk_input_i => counter_clk_i,
data_i => s_counters,
data_o => s_counters_ipb,
clk_output_i => ipb_clk_i);
-- Put the relevant counter onto the IPBus read port
s_counterIndex <= to_integer(unsigned(ipbus_i.ipb_addr(g_ADDRWIDTH-1 downto 0)));
ipbus_o.ipb_rdata <= s_counters_ipb(s_counterIndex);
p_ipbusWrite: process (ipb_clk_i) is
begin -- process p_ipbusWrite
if rising_edge(ipb_clk_i) then
if (ipbus_i.ipb_strobe = '1' and ipbus_i.ipb_write = '1') then
s_resetLines( s_counterIndex ) <= '1' ;
else
s_resetLines <= ( others =>'0' );
end if;
s_ipbus_ack <= ipbus_i.ipb_strobe and not s_ipbus_ack;
end if;
end process p_ipbusWrite;
ipbus_o.ipb_ack <= s_ipbus_ack;
ipbus_o.ipb_err <= '0';
end rtl;
This diff is collapsed.
......@@ -22,6 +22,7 @@ use work.ipbus.all;
--! addresses 0x00 - 0x1F : data to be written to MAROC ( r/w )\n
--! addresses 0x20 - 0x3F : data returned from MAROC ( ro )\n
--! address 0x40 : control/status. Writing to bit-0 starts transfer.
--! Setting bit-0 to zero resets sr before shifting.
--! Reading bit-0 returns high if transfer is in progress\n
--
--! @author David Cussans , David.Cussans@bristol.ac.uk
......@@ -85,6 +86,7 @@ architecture rtl of ipbusMarocShiftReg is
signal s_ack: std_logic;
signal s_start_p : std_logic := '0'; --! Control signal to shift reg controller. Take high for one cycle to start transfer
signal s_reset_sr_n : std_logic := '0'; --! Set to zero to reset shift register before clocking in values.
signal s_status : std_logic ; --! From shift reg controller. Goes high while transfer in progress
signal s_data_to_maroc , s_data_from_maroc : std_logic_vector( (g_NWORDS*g_BUSWIDTH)-1 downto 0) := (others => '0'); --! register storing data going to/from MAROC shift reg.
......@@ -143,7 +145,8 @@ begin
if ipbus_i.ipb_strobe='1' and ipbus_i.ipb_write='1' and
ipbus_i.ipb_addr(g_ADDRWIDTH+1)='1'
then
s_start_p <= ipbus_i.ipb_wdata(0) ;
s_start_p <= '1';
s_reset_sr_n <= ipbus_i.ipb_wdata(0) ;
else
s_start_p <= '0';
end if;
......@@ -168,6 +171,7 @@ begin
PORT MAP (
clk_system_i => clk_i,
rst_i => reset_i,
rst_before_shift_n_i => s_reset_sr_n ,
start_p_i => s_start_p,
data_i => s_data_to_maroc,
data_o => s_data_from_maroc,
......
......@@ -18,7 +18,9 @@ use work.ipbus.all;
------------------------------------------------------------------------------- --
-- unit name: ipbusMarocTriggerGenerator_rtl (ipbusMarocTriggerGenerator / rtl)
--
--! @brief Interfaces between IPBus and Maroc TriggerGenerator\n
--! @brief Interfaces between IPBus and Maroc TriggerGenerator
--
--! @details
--! Addresses ( with respect to base address)\n
--! 0x00 : Status register. Writing 1 to bit-0 resets trigger and timestamp counters\n
--! 0x01 : Manual trigger register. Write 1 to bit 0 to cause internal trigger\n
......@@ -34,8 +36,6 @@ use work.ipbus.all;
--! @date 21\1\2012
--
--! @version v0.1
--
--! @details
--!
--!
--! <b>Dependencies:</b>\n
......
......@@ -28,20 +28,32 @@ package body ipbus_addr_decode is
variable sel : integer;
begin
if std_match(addr, "-----------------00---001-------") then
if std_match(addr, "----------------000---001-------") then
sel := 0; -- scshiftreg / base 00000080 / mask 0000007f
elsif std_match(addr, "-----------------00---010-------") then
sel := 1; -- rshiftreg / base 00000100 / mask 0000007f
elsif std_match(addr, "-----------------00---110-------") then
elsif std_match(addr, "----------------000---010-------") then
sel := 1; -- rshiftreg / base 00000100 / mask 0000007f
elsif std_match(addr, "----------------000---110-------") then
sel := 2; -- triggerctrl / base 00000300 / mask 000007f
elsif std_match(addr, "-----------------01-------------") then
sel := 3; -- adcData / base 00002000 / mask 00000fff
elsif std_match(addr, "-----------------10-------------") then
sel := 4; -- adcCtrl / base 00004000 / mask 00000fff
elsif std_match(addr, "-----------------11-------------") then
sel := 5; -- expansionIO/ base 00006000 / mask 00000fff
elsif std_match(addr, "-----------------00---000-------") then
sel := 6; -- firmwareid / base 00000000 / mask 00000000
elsif std_match(addr, "----------------001-------------") then
sel := 3; -- adcData / base 00002000 / mask 00000fff
elsif std_match(addr, "----------------010-------------") then
sel := 4; -- adcCtrl / base 00004000 / mask 00000fff
elsif std_match(addr, "----------------011-------------") then
sel := 5; --trigCounters/ base 00006000 / mask 00000fff
elsif std_match(addr, "----------------100-------------") then
sel := 6; -- expansionIO/ base 00008000 / mask 00000fff
elsif std_match(addr, "----------------101-------------") then
sel := 7; -- i2c / base 0000A000 / mask 00000fff
elsif std_match(addr, "----------------000---000-------") then
sel := 8; -- firmwareid / base 00000000 / mask 00000000
else
sel := 99;
end if;
......
......@@ -20,7 +20,7 @@ architecture rtl of ipbus_ver is
begin
ipbus_out.ipb_rdata <= X"a621" & X"1008"; -- Lower 16b are ipbus firmware build ID (temporary arrangement).
ipbus_out.ipb_rdata <= X"a623" & X"1008"; -- Lower 16b are ipbus firmware build ID (temporary arrangement).
ipbus_out.ipb_ack <= ipbus_in.ipb_strobe;
ipbus_out.ipb_err <= '0';
......
......@@ -12,7 +12,7 @@ USE UNISIM.vcomponents.all;
entity marocInterface is
generic (
g_NSLAVES : positive := 5); -- number of IPBus slaves inside the maroc interface.
g_NSLAVES : positive := 6); -- number of IPBus slaves inside the maroc interface.
port (
-- Interface to IPBus
......@@ -33,7 +33,7 @@ entity marocInterface is
CK_40M_N_O: out STD_LOGIC;
HOLD2_O: out STD_LOGIC;
HOLD1_O: out STD_LOGIC;
OR_I: in STD_LOGIC_VECTOR(1 downto 0);
OR_I: in STD_LOGIC_VECTOR(2 downto 1);
MAROC_TRIGGER_I: in std_logic_vector(63 downto 0);
EN_OTAQ_O: out STD_LOGIC;
CTEST_O: out STD_LOGIC_VECTOR(5 downto 0); -- 4-bit R/2R DAC
......@@ -63,15 +63,13 @@ architecture rtl of marocInterface is
signal s_triggerNumber : std_logic_vector(c_BUSWIDTH-1 downto 0);
signal s_timeStamp : std_logic_vector(c_BUSWIDTH-1 downto 0);
signal s_tree_or : std_logic_vector( maroc_trigger_i'left+1 downto 0);
signal ck_40m : std_logic := '0'; -- internal MAROC clock.
begin -- rtl
-- Slave 0: slow control shift register controller
slave0: entity work.ipbusMarocShiftReg
slave0_sc_control: entity work.ipbusMarocShiftReg
generic map(
g_NBITS => 829, --! Number of bits to shift out to MAROC
g_NWORDS => c_NWORDS, --! Number of words in IPBUS space to store data
......@@ -94,7 +92,7 @@ begin -- rtl
);
-- Slave 1: "R" register shift register controller
slave1: entity work.ipbusMarocShiftReg
slave1_r_control: entity work.ipbusMarocShiftReg
generic map(
g_NBITS => 128, --! Number of bits to shift out to MAROC
g_NWORDS => c_NWORDS, --! Number of words in IPBUS space to store data
......@@ -117,7 +115,7 @@ begin -- rtl
);
-- Slave 2: Trigger generator
slave2: entity work.ipbusMarocTriggerGenerator
slave2_trigger: entity work.ipbusMarocTriggerGenerator
port map (
-- signals to IPBus
clk_i => ipb_clk_i,
......@@ -140,8 +138,8 @@ begin -- rtl
externalTrigger_o => s_externalTrigger_o,
-- Signals to MAROC
or1_a_i => OR_I(0),
or2_a_i => OR_I(1),
or1_a_i => OR_I(1),
or2_a_i => OR_I(2),
hold1_o => hold1_o ,
hold2_o => hold2_o ,
......@@ -153,7 +151,7 @@ begin -- rtl
-- gpio_o(5) <= s_externalTrigger_o;
-- Slave 3&4: Simple ADC controller
slave3_4: entity work.ipbusMarocADC
slave3_4_adc: entity work.ipbusMarocADC
generic map(
g_ADDRWIDTH => 12 )
port map(
......@@ -195,13 +193,23 @@ begin -- rtl
-- FIXME - clk fast
-- FIXME - connect combination of MAROC signals to an output
s_tree_or(0) <= '0';
gen_maroc_or: for i in maroc_trigger_i'range generate
s_tree_or(i+1) <= s_tree_or(i) or maroc_trigger_i(i);
end generate gen_maroc_or;
slave5_triggerCounter : entity work.ipbusCounters
generic map (
g_DATAWIDTH => 32,
g_ADDRWIDTH => 6 --! 64 counters
)
port map (
counter_clk_i => clk_fast_i,
triggers_i => maroc_trigger_i,
-- signals to IPBus
ipb_clk_i => ipb_clk_i,
reset_i => rst_i,
ipbus_i => ipb_in(5),
ipbus_o => ipb_out(5)
);
-- For now use IPBus clock as MAROC clock
ck_40m_obuf : OBUFDS
port map (
......
......@@ -5,9 +5,14 @@ use IEEE.numeric_std.ALL;
use work.ipbus.ALL;
use work.maroc.all;
--! Xilinx primitives
LIBRARY UNISIM;
USE UNISIM.vcomponents.all;
entity marocInterface is
generic (
g_NSLAVES : positive := 5); -- number of IPBus slaves inside the maroc interface.
g_NSLAVES : positive := 6); -- number of IPBus slaves inside the maroc interface.
port (
-- Interface to IPBus
......@@ -51,7 +56,6 @@ end marocInterface;
architecture rtl of marocInterface is
signal register_data: std_logic_vector(c_BUSWIDTH-1 downto 0);
signal s_adcConversionStatus : std_logic;
signal s_adcConversionEnd : std_logic;
signal s_adcConversionStart : std_logic;
......@@ -59,23 +63,13 @@ architecture rtl of marocInterface is
signal s_triggerNumber : std_logic_vector(c_BUSWIDTH-1 downto 0);
signal s_timeStamp : std_logic_vector(c_BUSWIDTH-1 downto 0);
begin -- rtl
signal ck_40m : std_logic := '0'; -- internal MAROC clock.
begin -- rtl
-- --! Slave 1: 32b register ( output from FPGA to MAROC)
-- slave0: entity work.ipbus_reg
-- generic map(addr_width => 0)
-- port map(
-- clk => ipb_clk_i,
-- reset => rst_i,
-- ipbus_in => ipb_in(0),
-- ipbus_out => ipb_out(0),
-- q => register_data
-- );
-- Slave 1: slow control shift register controller
slave1: entity work.ipbusMarocShiftReg
-- Slave 0: slow control shift register controller
slave0_sc_control: entity work.ipbusMarocShiftReg
generic map(
g_NBITS => 829, --! Number of bits to shift out to MAROC
g_NWORDS => c_NWORDS, --! Number of words in IPBUS space to store data
......@@ -97,8 +91,8 @@ begin -- rtl
rst_sr_n_o => rst_sc_n_o
);
-- Slave 2: "R" register shift register controller
slave2: entity work.ipbusMarocShiftReg
-- Slave 1: "R" register shift register controller
slave1_r_control: entity work.ipbusMarocShiftReg
generic map(
g_NBITS => 128, --! Number of bits to shift out to MAROC
g_NWORDS => c_NWORDS, --! Number of words in IPBUS space to store data
......@@ -120,51 +114,14 @@ begin -- rtl
rst_sr_n_o => rst_r_n_o
);
-- Slave 3: Simple ADC controller
slave3: entity work.ipbusMarocADC
generic map(
g_ADDRWIDTH => 10 )
port map(
-- signals to IPBus
clk_i => ipb_clk_i,
reset_i => rst_i,
control_ipbus_i => ipb_in(2),
control_ipbus_o => ipb_out(2),
data_ipbus_i => ipb_in(3),
data_ipbus_o => ipb_out(3),
-- global reset signal
logic_reset_i => '0',
-- Signals to trigger controller
adcStatus_o => s_adcConversionStatus,
adcConversionStart_i => s_adcConversionStart,
triggerNumber_i => s_triggerNumber ,
timeStamp_i => s_timeStamp ,
-- Signals to MAROC
START_ADC_N_O => START_ADC_N_O,
RST_ADC_N_O => RST_ADC_N_O,
ADC_DAV_I => ADC_DAV_I,
OUT_ADC_I => OUT_ADC_I
);
-- FIXME - this should be edge sensitive.... ir trigger generator changed to
-- be level sensitive.
s_adcConversionEnd <= s_adcConversionStatus;
-- FIXME - clk fast
-- Slave 4: Trigger generator
slave4: entity work.ipbusMarocTriggerGenerator
-- Slave 2: Trigger generator
slave2_trigger: entity work.ipbusMarocTriggerGenerator
port map (
-- signals to IPBus
clk_i => ipb_clk_i,
reset_i => rst_i,
ipbus_i => ipb_in(4),
ipbus_o => ipb_out(4),
ipbus_i => ipb_in(2),
ipbus_o => ipb_out(2),
-- Signals to MAROC and ADC controller
adcConversionEnd_i => s_adcConversionEnd,
......@@ -193,15 +150,88 @@ begin -- rtl
trigger_o <= s_externalTrigger_o;
-- gpio_o(5) <= s_externalTrigger_o;
-- Slave 3&4: Simple ADC controller
slave3_4_adc: entity work.ipbusMarocADC
generic map(
g_ADDRWIDTH => 12 )
port map(
-- FIXME - for now, just wire up any old signal to an OBUFDS
-- to get correct signal type for CK_40M
-- signals to IPBus
clk_i => ipb_clk_i,
reset_i => rst_i,
control_ipbus_i => ipb_in(4),
control_ipbus_o => ipb_out(4),
data_ipbus_i => ipb_in(3),
data_ipbus_o => ipb_out(3),
-- global reset signal
logic_reset_i => '0',
-- Signals to trigger controller
adcStatus_o => s_adcConversionStatus,
adcConversionStart_i => s_adcConversionStart,
triggerNumber_i => s_triggerNumber ,
timeStamp_i => s_timeStamp ,
-- Signals to MAROC
START_ADC_N_O => START_ADC_N_O,
RST_ADC_N_O => RST_ADC_N_O,
ADC_DAV_I => ADC_DAV_I,
OUT_ADC_I => OUT_ADC_I
);
-- Look for adc conversion status going from high ( ADC busy ) to low ( ADC
-- idle ) and produce an adcConversionEnd signal. This extra step makes more
-- sense with multiple ADCs......
edgeDetect: entity work.fallingEdgeDetect
port map (
clk_i => ipb_clk_i,
level_i => s_adcConversionStatus,
pulse_o => s_adcConversionEnd
);
-- FIXME - clk fast
slave5_triggerCounter : entity work.ipbusCounters
generic map (
g_DATAWIDTH => 32,
g_ADDRWIDTH => 6 --! 64 counters
)
port map (
counter_clk_i => clk_fast_i,
triggers_i => maroc_trigger_i,
-- signals to IPBus
ipb_clk_i => ipb_clk_i,
reset_i => rst_i,
ipbus_i => ipb_in(5),
ipbus_o => ipb_out(5)
);
-- For now use IPBus clock as MAROC clock
ck_40m_obuf : OBUFDS
port map (
I => s_externalTrigger_o,
O => CK_40M_P_O,
I => CK_40M,
O => CK_40M_P_O,
OB => CK_40M_N_O
);
-- Use a DDR output register to get from clock net onto output.
maroc_clock_buf : ODDR2
port map (
Q => CK_40M, -- 1-bit output data
C0 => ipb_clk_i , -- 1-bit clock input
C1 => not ipb_clk_i , -- 1-bit clock input
CE => '1', -- 1-bit clock enable input
D0 => '0', -- 1-bit data input (associated with C0)
D1 => '1', -- 1-bit data input (associated with C1)
R => '0', -- 1-bit reset input
S => '0' -- 1-bit set input
);
EN_OTAQ_O <= '1';
end rtl;
......@@ -56,6 +56,7 @@ entity marocShiftRegFSM is
clk_system_i : in std_logic;
rst_i : in std_logic; --! Take high to reset state machine.
sr_clk_rising_p_i : in std_logic; --! Goes high on rising edge of shift-reg clock
rst_before_shift_n_i : in std_logic; --! if low shift reg is reset before shifting in new data.
start_p_i : in std_logic;
rst_sr_n_o : out std_logic; --! reset to MAROC SR
load_sr_o : out std_logic;
......@@ -185,9 +186,9 @@ begin -- rtl
end process p_startJK;
--! Set output signals on basis of state
rst_sr_n_o <= '0' when s_state = RESETTING else '1'; --! reset to MAROC goes low when state=resetting
rst_sr_n_o <= rst_before_shift_n_i when s_state = RESETTING else '1'; --! reset to MAROC goes low when state=resetting
load_sr_o <= '1' when s_state = RESETTING else '0'; --! load shift-reg whilerst is low
load_sr_o <= '1' when s_state = RESETTING else '0'; --! load shift-reg while rst is low
enable_sr_clk_o <= '1' when s_state = SHIFTINGOUT else '0';
......
......@@ -68,6 +68,7 @@ entity marocShiftReg is
port (
clk_system_i : in std_logic; --! System clock ( probably IPBUS clock)
rst_i : in std_logic; --! active high. synchronous. Resets shift-reg controler.
rst_before_shift_n_i : in std_logic; --! if low shift reg is reset before shifting in new data.
start_p_i : in std_logic; --! take high for one cycle to initiate serial transer to MAROC;
--! Data to be written to MAROC shift reg. Integer number of IPBus words wide.
......@@ -134,6 +135,7 @@ architecture rtl of marocShiftReg is
clk_system_i : in std_logic;
rst_i : in std_logic; --! Take high to reset state machine.
sr_clk_rising_p_i : in std_logic; --! Goes high on rising edge of shift-reg clock
rst_before_shift_n_i : in std_logic; --! if low shift reg is reset before shifting in new data.
start_p_i : in std_logic;
rst_sr_n_o : out std_logic; --! reset to MAROC SR
load_sr_o : out std_logic;
......@@ -194,6 +196,7 @@ begin -- rtl
clk_system_i => clk_system_i,
rst_i => rst_i,
sr_clk_rising_p_i => s_clk_sr_rising_p ,
rst_before_shift_n_i => rst_before_shift_n_i,
start_p_i => start_p_i,
rst_sr_n_o => rst_sr_n_o,
load_sr_o => s_load_sr,
......
--! @file risingEdgeDetect_rtl
--! @brief Detects the rising edge of an incoming signal and produces a single cycle pulse
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity risingEdgeDetect is
port (
clk_i : in std_logic; -- ! rising edge active clock
level_i : in std_logic; -- ! Level
pulse_o : out std_logic); -- ! Pulses high for one clock cycle when level_i goes from low to high
end entity risingEdgeDetect;
architecture rtl of risingEdgeDetect is
signal level_d1 , level_d2 , level_p1 , level_p2 : std_logic := '0'; -- delayed version of input
begin -- architecture rtl
p_levelDetect: process (clk_i) is
begin -- process p_levelDetect
if rising_edge(clk_i) then -- rising clock edge
-- extra register stages
level_p1 <= level_i;
level_p2 <= level_p1;
level_d1 <= level_p2;
--level_d1 <= level_i;
level_d2 <= level_d1;
if (( level_d2 = '0' ) and ( level_d1 = '1')) then
pulse_o <= '1';
else
pulse_o <= '0';
end if;
end if;
end process p_levelDetect;
end architecture rtl;
--=============================================================================
--! @file synchronizeRegisters_rtl.vhd
--=============================================================================
--
-------------------------------------------------------------------------------
-- --
-- University of Bristol, High Energy Physics Group.
-- --
------------------------------------------------------------------------------- --
-- VHDL Architecture worklib.synchronizeRegisters.rtl
--
--! @brief Regularly transfers the input to the output.\n
--! One clock for input , one clock for output\n
--! Can't just put entire bus through a couple of register stages,\n
--! Since this will just swap meta-stability issues for race issues.
--
--! @author David Cussans , David.Cussans@bristol.ac.uk
--
--! @date 24/Nov/12
--
--! @version v0.1
--
--! @details A six stage "ring oscillator" is used to generate two strobes.
--! One reads data into a register. The other registers the data to the output
--! Three stages are clocked on clk_write_i , three stages are clocked on clk_read_i
--! The time taken for an edge to travel round the complete loop is
--! 2 cycles of clk_read_i and 2 cycles of clk_write_i plus two intervals
--! that depend on the relative phase of clk_read_i and clk_write_i
--!
--! Based on registerCounters
--!
--! <b>Dependencies:</b>\n
--!
--! <b>References:</b>\n
--!
--! <b>Modified by:</b>\n
--! Author:
--! David Cussans, 26/2/14 - Added registers to output to aid timing closure.
-------------------------------------------------------------------------------
--! \n\n<b>Last changes:</b>\n
-------------------------------------------------------------------------------
--! @todo <next thing to do> \n
--! <another thing to do> \n
--
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
--use work.fmcTLU.all;
use work.ipbus_reg_types.all;
entity synchronizeRegisters is
generic (
--g_DATA_WIDTH : positive := 15;
g_NUM_REGISTERS : positive := 1); -- ! Width of counter
port (
clk_input_i : in std_logic; -- ! clock for input
data_i : in ipb_reg_v(g_NUM_REGISTERS-1 downto 0); -- ! array of registers to transfer to output
data_o : out ipb_reg_v(g_NUM_REGISTERS-1 downto 0); -- ! Data now in clk_output_i domain
clk_output_i : in std_logic); -- ! clock for output
end synchronizeRegisters;
architecture rtl of synchronizeRegisters is
signal s_ring_d0 , s_ring_d1 , s_ring_d2 , s_ring_d3 , s_ring_d4, s_ring_d5: std_logic := '0'; -- stages in "ring oscillator" used to generate strobes
signal s_registered_data : ipb_reg_v(data_i'range) := ( others => ( others => '0')); -- ! Register to store data between clock domains
signal s_read_strobe , s_write_strobe : std_logic := '0'; -- ! Strobes high to register data from input and to output
begin -- rtl
-- purpose: part of "ring oscillator" transfering strobe between clock domains
-- type : combinational
-- inputs : clk_read_i
-- outputs:
p_gen_capture_strobe: process (clk_input_i)
begin -- process p_gen_capture_strobe
if rising_edge(clk_input_i) then
s_ring_d0 <= not s_ring_d5;
s_ring_d1 <= s_ring_d0;
s_ring_d2 <= s_ring_d1;
if s_read_strobe = '1' then
s_registered_data <= data_i;
end if;
end if;
end process p_gen_capture_strobe;
s_read_strobe <= s_ring_d1 xor s_ring_d2; --! Generate a strobe with
--width one clk_read_i
-- purpose: part of "ring oscillator" transfering strobe between clock domains
-- type : combinational
-- inputs : clk_output_i
-- outputs:
p_gen_output_strobe: process (clk_output_i)
begin -- process p_gen_output_strobe
if rising_edge(clk_output_i) then
s_ring_d3 <= s_ring_d2;
s_ring_d4 <= s_ring_d3;
s_ring_d5 <= s_ring_d4;
if s_write_strobe = '1' then
data_o <= s_registered_data;
end if;
end if;
end process p_gen_output_strobe;
s_write_strobe <= s_ring_d4 xor s_ring_d5; --! Generate a strobe
--
end rtl;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment