Commit 9baa3508 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

Merge branch 'etherbone_demo'

Conflicts:
	hdl/rtl/fd_main_wishbone_slave.vhd
	hdl/top/svec/wr/svec_top.vhd
	hdl/top/svec/wr/xvme64x_core.vhd
parents 96775589 985a70d9
......@@ -8,21 +8,33 @@ module random_pulse_gen
parameter real g_pulse_width = 30ns;
parameter real g_min_spacing = 300ns;
parameter real g_max_spacing = 600ns;
parameter int g_repetition = 1;
parameter real g_burst_spacing = 50ns;
int seed = 1;
initial forever
if(enable_i)
begin
int i;
real delta;
seed = $urandom(seed);
delta = $dist_uniform(seed, g_min_spacing - g_pulse_width, g_max_spacing - g_pulse_width);
pulse_o = 1;
#(g_pulse_width);
pulse_o = 0;
#(delta);
for(i=0;i<g_repetition;i++)
begin
pulse_o = 1;
#(g_pulse_width);
pulse_o = 0;
if(g_repetition > 1)
#(g_burst_spacing);
end
#(delta);
end else begin
pulse_o <= 1'b0;
@(posedge enable_i);
......
......@@ -6,7 +6,7 @@
-- Author : Tomasz Wlostowski
-- Company : CERN
-- Created : 2011-08-24
-- Last update: 2012-02-26
-- Last update: 2012-11-26
-- Platform : FPGA-generic
-- Standard : VHDL'93
-------------------------------------------------------------------------------
......@@ -347,8 +347,8 @@ begin -- behavioral
pulse_i => pps_p1,
extended_o => csync_pps_o);
irq_sync_o <= '0' when (g_with_wr_core = false) else ((dmtd_locked_d0 xor wr_clk_dmtd_locked_i) or (wr_state_changed and regs_i.tcr_wr_enable_o));
irq_sync_o <= '0' when (g_with_wr_core = false or rst_n_sys_i = '0') else (wr_state_changed and regs_i.tcr_wr_enable_o);
regs_o.tcr_wr_present_i <= '1' when (g_with_wr_core) else '0';
end behavioral;
......@@ -3,7 +3,7 @@
---------------------------------------------------------------------------------------
-- File : fd_main_wbgen2_pkg.vhd
-- Author : auto-generated by wbgen2 from fd_main_wishbone_slave.wb
-- Created : Mon Jun 4 13:42:20 2012
-- Created : Fri Dec 14 11:28:02 2012
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE fd_main_wishbone_slave.wb
......
......@@ -3,7 +3,7 @@
---------------------------------------------------------------------------------------
-- File : fd_main_wishbone_slave.vhd
-- Author : auto-generated by wbgen2 from fd_main_wishbone_slave.wb
-- Created : Wed Oct 24 15:07:30 2012
-- Created : Fri Dec 14 11:28:02 2012
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE fd_main_wishbone_slave.wb
......
......@@ -849,6 +849,7 @@ write 0: DMTD pattern generation disabled.";
name = "SCL Line out";
prefix = "SCL_OUT";
type = BIT;
reset_value = 1;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
......@@ -856,6 +857,7 @@ write 0: DMTD pattern generation disabled.";
name = "SDA Line out";
prefix = "SDA_OUT";
type = BIT;
reset_value = 1;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
......
......@@ -6,7 +6,7 @@
-- Author : Tomasz Wlostowski
-- Company : CERN
-- Created : 2011-08-24
-- Last update: 2012-08-09
-- Last update: 2012-11-23
-- Platform : FPGA-generic
-- Standard : VHDL'93
-------------------------------------------------------------------------------
......@@ -17,7 +17,7 @@
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- Public License as published by the Free Software Fsoundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
......@@ -42,6 +42,7 @@ use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.gencores_pkg.all;
use work.genram_pkg.all;
use work.wishbone_pkg.all;
use work.fd_main_wbgen2_pkg.all;
use work.fine_delay_pkg.all;
......@@ -55,6 +56,11 @@ entity fine_delay_core is
-- when true, some timeouts are reduced to speed up simulations
g_simulation : boolean := false;
-- when true, the card does not operate as a Delay, but instead
-- provides direct output from the TDC and direct inputs to the channel
-- drivers.
g_with_direct_timestamp_io : boolean := false;
-- Wishbone slave settings
g_interface_mode : t_wishbone_interface_mode := PIPELINED;
g_address_granularity : t_wishbone_address_granularity := WORD
......@@ -213,7 +219,21 @@ entity fine_delay_core is
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
wb_stall_o : out std_logic;
wb_irq_o : out std_logic
wb_irq_o : out std_logic;
---------------------------------------------------------------------------
-- Input/Output timestamp I/O
---------------------------------------------------------------------------
tdc_seconds_o : out std_logic_vector(39 downto 0);
tdc_cycles_o : out std_logic_vector(27 downto 0);
tdc_frac_o : out std_logic_vector(11 downto 0);
tdc_valid_o : out std_logic;
outx_seconds_i : in std_logic_vector(40 * 4 - 1 downto 0) := f_gen_dummy_vec('0', 40 * 4);
outx_cycles_i : in std_logic_vector(28 * 4 - 1 downto 0) := f_gen_dummy_vec('0', 28 * 4);
outx_frac_i : in std_logic_vector(12 * 4 - 1 downto 0) := f_gen_dummy_vec('0', 12 * 4);
outx_valid_i : in std_logic_vector(3 downto 0) := x"0"
);
end fine_delay_core;
......@@ -276,12 +296,20 @@ architecture rtl of fine_delay_core is
signal tsbcr_read_ack, fid_read_ack : std_logic;
signal irq_rbuf, irq_spll, irq_sync : std_logic;
type t_delay_channel is record
idle : std_logic;
pulse0, pulse1 : std_logic;
value : std_logic_vector(9 downto 0);
load : std_logic;
load_done : std_logic;
tag : t_fd_timestamp;
end record;
signal chx_delay_idle : std_logic_vector(3 downto 0);
signal chx_delay_pulse0, chx_delay_pulse1 : std_logic_vector(3 downto 0);
signal chx_delay_value : t_dly_array(0 to 3);
signal chx_delay_load , chx_delay_load_done : std_logic_vector(3 downto 0);
type t_delay_channel_array is array (integer range <>) of t_delay_channel;
signal channels : t_delay_channel_array(3 downto 0);
signal chx_delay_idle : std_logic_vector(3 downto 0);
signal cnx_out : t_wishbone_master_out_array(0 to 5);
signal cnx_in : t_wishbone_master_in_array(0 to 5);
......@@ -517,6 +545,28 @@ begin -- rtl
rbuf_mux_valid_masked <= rbuf_mux_valid and regs_fromwb.tsbcr_chan_mask_o;
gen_with_direct_io_tdc : if(g_with_direct_timestamp_io) generate
U_Sync_TDC_Valid_Out : gc_pulse_synchronizer
port map (
clk_in_i => clk_ref_0_i,
clk_out_i => clk_sys_i,
rst_n_i => rst_n_sys,
d_p_i => tag_valid,
q_p_o => tdc_valid_o);
process(clk_ref_0_i)
begin
if rising_edge(clk_ref_0_i) then
if(tag_valid = '1') then
tdc_cycles_o <= tag_coarse;
tdc_seconds_o <= tag_utc;
tdc_frac_o <= tag_frac;
end if;
end if;
end process;
end generate gen_with_direct_io_tdc;
gen_pack_rbuf_mux : for i in 0 to 4 generate
rbuf_mux_d(c_TIMESTAMP_TOTAL_BITS * (i+1) -1 downto c_TIMESTAMP_TOTAL_BITS * i) <= to_stdLogicVector(rbuf_mux_ts(i));
end generate gen_pack_rbuf_mux;
......@@ -572,6 +622,37 @@ begin -- rtl
gen_cal_pulse <= cal_pulse_mask and regs_fromwb.calr_psel_o;
gen_output_channels : for i in 0 to 3 generate
gen_with_direct_io : if g_with_direct_timestamp_io generate
U_Sync_Valid_Pulse : gc_pulse_synchronizer
port map (
clk_in_i => clk_sys_i,
clk_out_i => clk_ref_0_i,
rst_n_i => rst_n_ref,
d_p_i => outx_valid_i(i),
q_p_o => channels(i).tag.valid);
process(clk_sys_i)
begin
if rising_edge(Clk_sys_i) then
if(outx_valid_i(i) = '1')then
channels(i).tag.u <= outx_seconds_i(40 * (i+1) - 1 downto 40 * i);
channels(i).tag.c <= outx_cycles_i(28 * (i+1) - 1 downto 28 * i);
channels(i).tag.f <= outx_frac_i(12 * (i+1) -1 downto 12 * i);
end if;
end if;
end process;
end generate gen_with_direct_io;
gen_without_direct_io : if not g_with_direct_timestamp_io generate
channels(i).tag.valid <= tag_valid_masked;
channels(i).tag.u <= tag_utc;
channels(i).tag.c <= tag_coarse;
channels(i).tag.f <= tag_frac;
end generate gen_without_direct_io;
U_Output_ChannelX : fd_delay_channel_driver
generic map (
g_index => i)
......@@ -584,43 +665,53 @@ begin -- rtl
csync_utc_i => master_csync_utc,
csync_coarse_i => master_csync_coarse,
gen_cal_i => gen_cal_pulse(i),
tag_valid_i => tag_valid_masked,
tag_utc_i => tag_utc,
tag_coarse_i => tag_coarse,
tag_frac_i => tag_frac,
tag_valid_i => channels(i).tag.valid,
tag_utc_i => channels(i).tag.u,
tag_coarse_i => channels(i).tag.c,
tag_frac_i => channels(i).tag.f,
pstart_valid_o => rbuf_mux_valid(i+1),
pstart_utc_o => rbuf_mux_ts(i+1).u,
pstart_coarse_o => rbuf_mux_ts(i+1).c,
pstart_frac_o => rbuf_mux_ts(i+1).f,
delay_pulse0_o => chx_delay_pulse0(i),
delay_pulse1_o => chx_delay_pulse1(i),
delay_value_o => chx_delay_value(i),
delay_load_o => chx_delay_load(i),
delay_idle_o => chx_delay_idle(i),
delay_load_done_i => chx_delay_load_done(i),
delay_pulse0_o => channels(i).pulse0,
delay_pulse1_o => channels(i).pulse1,
delay_value_o => channels(i).value,
delay_load_o => channels(i).load,
delay_idle_o => channels(i).idle,
delay_load_done_i => channels(i).load_done,
wb_i => cnx_out(i+1),
wb_o => cnx_in(i+1));
chx_delay_idle(i) <= channels(i).idle;
U_DDR_Output : fd_ddr_driver
port map (
clk0_i => clk_ref_0_i,
clk1_i => clk_ref_180_i,
d0_i => chx_delay_pulse0(i),
d1_i => chx_delay_pulse1(i),
d0_i => channels(i).pulse0,
d1_i => channels(i).pulse1,
q_o => delay_pulse_o(i));
end generate gen_output_channels;
U_Delay_Line_Arbiter : fd_delay_line_arbiter
port map (
clk_ref_i => clk_ref_0_i,
rst_n_i => rst_n_ref,
load_i => chx_delay_load,
done_o => chx_delay_load_done,
delay_val0_i => f_reverse_bits(chx_delay_value(0)),
delay_val1_i => chx_delay_value(1),
delay_val2_i => f_reverse_bits(chx_delay_value(2)),
delay_val3_i => chx_delay_value(3),
clk_ref_i => clk_ref_0_i,
rst_n_i => rst_n_ref,
load_i(0) => channels(0).load,
load_i(1) => channels(1).load,
load_i(2) => channels(2).load,
load_i(3) => channels(3).load,
done_o(0) => channels(0).load_done,
done_o(1) => channels(1).load_done,
done_o(2) => channels(2).load_done,
done_o(3) => channels(3).load_done,
delay_val0_i => f_reverse_bits(channels(0).value),
delay_val1_i => channels(1).value,
delay_val2_i => f_reverse_bits(channels(2).value),
delay_val3_i => channels(3).value,
delay_val_o => delay_val_o,
delay_len_o => delay_len_o);
......@@ -643,6 +734,8 @@ begin -- rtl
dbg_tag_out_o => dbg_tag_out
);
tag_valid_masked <= tag_valid when unsigned(not chx_delay_idle) = 0 else '0';
U_LED_Driver : gc_extend_pulse
......
......@@ -6,7 +6,7 @@
-- Author : Tomasz Wlostowski
-- Company : CERN
-- Created : 2011-08-24
-- Last update: 2012-08-09
-- Last update: 2012-11-22
-- Platform : FPGA-generic
-- Standard : VHDL'93
-------------------------------------------------------------------------------
......@@ -44,7 +44,7 @@ use ieee.numeric_std.all;
use work.wishbone_pkg.all;
use work.fd_main_wbgen2_pkg.all;
use work.fd_channel_wbgen2_pkg.all;
use work.genram_pkg.all;
package fine_delay_pkg is
......@@ -377,10 +377,11 @@ package fine_delay_pkg is
component fine_delay_core
generic (
g_with_wr_core : boolean;
g_simulation : boolean;
g_interface_mode : t_wishbone_interface_mode;
g_address_granularity : t_wishbone_address_granularity);
g_with_wr_core : boolean := true;
g_simulation : boolean := false;
g_with_direct_timestamp_io : boolean := false;
g_interface_mode : t_wishbone_interface_mode;
g_address_granularity : t_wishbone_address_granularity);
port (
clk_ref_0_i : in std_logic;
clk_ref_180_i : in std_logic;
......@@ -443,7 +444,15 @@ package fine_delay_pkg is
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
wb_stall_o : out std_logic;
wb_irq_o : out std_logic);
wb_irq_o : out std_logic;
tdc_seconds_o : out std_logic_vector(39 downto 0);
tdc_cycles_o : out std_logic_vector(27 downto 0);
tdc_frac_o : out std_logic_vector(11 downto 0);
tdc_valid_o : out std_logic;
outx_seconds_i : in std_logic_vector(40 * 4 - 1 downto 0) := f_gen_dummy_vec('0', 40 * 4);
outx_cycles_i : in std_logic_vector(28 * 4 - 1 downto 0) := f_gen_dummy_vec('0', 28 * 4);
outx_frac_i : in std_logic_vector(12 * 4 - 1 downto 0) := f_gen_dummy_vec('0', 12 * 4);
outx_valid_i : in std_logic_vector(3 downto 0) := x"0");
end component;
function f_to_internal_time (
......
......@@ -3,6 +3,7 @@
`include "fdelay_board.svh"
`include "simdrv_fine_delay.svh"
`include "ideal_timestamper.svh"
module delay_meas(input enable, input a, input b);
......@@ -25,6 +26,7 @@ module delay_meas(input enable, input a, input b);
end
initial forever begin
wait(tag_a.num() > 0 && tag_b.num() > 0);
......@@ -88,9 +90,11 @@ module main;
random_pulse_gen
#(
.g_pulse_width (50ns),
.g_pulse_width (100ns),
.g_min_spacing (1001ns),
.g_max_spacing (1001.1ns))
.g_max_spacing (1001.1ns),
.g_repetition(1),
.g_burst_spacing(3ns))
U_Gen0
(
.enable_i(pulse_enable),
......@@ -105,6 +109,14 @@ module main;
);
delay_meas U_DMeas0 (pulse_enable, trig0, out0[0]);
ideal_timestamper tsu_in(
.clk_ref_i(I_fmc0.clk_ref_p),
.rst_n_i(rst_n),
.enable_i(1'b1),
.trig_a_i(trig0),
.csync_p1_i(1'b0));
task automatic init_vme64x_core(ref CBusAccessor_VME64x acc);
/* map func0 to 0x80000000, A32 */
......@@ -134,26 +146,63 @@ module main;
drv0.init();
dly=new;
dly.from_ps(600000);
drv0.config_output(0, CSimDrv_FineDelay::DELAY, 1, dly, 200000);
dly.from_ps(800000);
drv0.config_output(0, CSimDrv_FineDelay::DELAY, 1, dly, 250000);
$display("Init done");
pulse_enable = 1;
forever begin
drv0.rbuf_update();
if(drv0.poll())
forever begin
// drv0.rbuf_update();
// if(drv0.poll())
Timestamp ts, ts_ref;
// ts = drv0.get();
while(ts_q_fd0.size() == 0)
#1ns;
ts = ts_q_fd0.pop_front();
$display("TS: %.3f", ts.flatten());
while(tsu_in.poll())
begin
Timestamp ts;
ts = drv0.get();
// $display("TS: %.3f", ts.flatten());
ts_ref = tsu_in.get();
end
#1us;
$display("TS: %.3f, ref: %.3f, delta: %.3f", ts.flatten(), ts_ref.flatten(), ts_ref.flatten() - ts.flatten());
end
end
end // initial begin
Timestamp ts_q_fd0[$];
always@(posedge DUT.dcm0_clk_ref_0)
begin
if(DUT.U_FineDelay_Core0.tag_valid)
begin
Timestamp tr;
tr = new;
$display("Got a tag");
tr.coarse = DUT.U_FineDelay_Core0.tag_coarse;
tr.utc = 0;
tr.frac = DUT.U_FineDelay_Core0.tag_frac;
ts_q_fd0.push_back(tr);
end
end
endmodule // main
......
This diff is collapsed.
......@@ -6,17 +6,16 @@
-- Author : Tomasz Wlostowski
-- Company : CERN
-- Created : 2011-08-24
-- Last update: 2012-10-24
-- Last update: 2013-02-21
-- Platform : FPGA-generic
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: Top level for the SVEC 1.0 card with two Fine Delay FMCs.
-- Supports:
-- - A24/A32/D32 VME addressing
-- - SDB enumeration (SDB descriptor at 0x60000)
-- - SDB enumeration (SDB descriptor at 0x0)
-- - White Rabbit and Etherbone
-- Does not yet support:
-- - Interrupts
-- - Interrupts (via vme64x-core interrupter, to be verified)
-------------------------------------------------------------------------------
--
-- Copyright (c) 2011 CERN / BE-CO-HT
......@@ -334,7 +333,7 @@ architecture rtl of svec_top is
constant c_SLAVE_WRCORE : integer := 2;
constant c_SLAVE_VIC : integer := 3;
constant c_WRCORE_BRIDGE_SDB : t_sdb_bridge := f_xwb_bridge_manual_sdb(x"0003ffff", x"00070000");
constant c_WRCORE_BRIDGE_SDB : t_sdb_bridge := f_xwb_bridge_manual_sdb(x"0003ffff", x"00040000");
constant c_xwb_vic_sdb : t_sdb_device := (
abi_class => x"0000", -- undocumented device
......@@ -421,7 +420,6 @@ architecture rtl of svec_top is
signal vme_master_in : t_wishbone_master_in;
signal pins : std_logic_vector(31 downto 0);
signal rst_n_a : std_logic;
signal pps : std_logic;
signal led_divider : unsigned(22 downto 0);
......@@ -462,8 +460,32 @@ architecture rtl of svec_top is
attribute buffer_type : string; --" {bufgdll | ibufg | bufgp | ibuf | bufr | none}";
attribute buffer_type of clk_125m_pllref : signal is "BUFG";
signal powerup_reset_cnt : unsigned(7 downto 0) := "00000000";
signal powerup_rst_n : std_logic := '0';
signal sys_locked : std_logic;
begin
p_powerup_reset : process(clk_sys)
begin
if rising_edge(clk_sys) then
if(VME_RST_n_i = '0' or rst_n_i = '0') then
powerup_rst_n <= '0';
elsif sys_locked = '1' then
if(powerup_reset_cnt = "11111111") then
powerup_rst_n <= '1';
else
powerup_rst_n <= '0';
powerup_reset_cnt <= powerup_reset_cnt + 1;
end if;
else
powerup_rst_n <= '0';
powerup_reset_cnt <= "00000000";
end if;
end if;
end process;
U_Buf_CLK_GTP : IBUFDS
generic map (
DIFF_TERM => true,
......@@ -503,7 +525,7 @@ begin
CLKOUT3 => open,
CLKOUT4 => open,
CLKOUT5 => open,
LOCKED => open,
LOCKED => sys_locked,
RST => '0',
CLKFBIN => pllout_clk_fb_pllref,
CLKIN => clk_125m_pllref);
......@@ -540,12 +562,12 @@ begin
CLKFBIN => pllout_clk_fb_dmtd,
CLKIN => clk_20m_vcxo_buf);
rst_n_a <= VME_RST_n_i and rst_n_i;
-- rst_n_a <= VME_RST_n_i and rst_n_i;
U_Sync_Reset : gc_sync_ffs
port map (
clk_i => clk_sys,
rst_n_i => '1',
data_i => rst_n_a,
data_i => powerup_rst_n,
synced_o => local_reset_n);
U_Buf_CLK_PLL : IBUFGDS
......@@ -579,9 +601,9 @@ begin
U_VME_Core : xvme64x_core
port map (
clk_i => clk_sys,
rst_n_i => local_reset_n,
rst_n_i => powerup_rst_n,
VME_AS_n_i => VME_AS_n_i,
VME_RST_n_i => VME_RST_n_i,
VME_RST_n_i => powerup_rst_n,
VME_WRITE_n_i => VME_WRITE_n_i,
VME_AM_i => VME_AM_i,
VME_DS_n_i => VME_DS_n_i,
......
......@@ -51,8 +51,8 @@ architecture wrapper of xvme64x_core is
component VME64xCore_Top
generic (
g_width : integer := 32;
g_addr_width : integer := 64;
g_wb_data_width : integer := 32;
g_wb_addr_width : integer := 64;
g_CRAM_SIZE : integer := 1024);
port (
clk_i : in std_logic;
......@@ -82,13 +82,13 @@ architecture wrapper of xvme64x_core is
VME_ADDR_DIR_o : out std_logic;
VME_ADDR_OE_N_o : out std_logic;
VME_RETRY_OE_o : out std_logic;
DAT_i : in std_logic_vector(g_width - 1 downto 0);
DAT_o : out std_logic_vector(g_width - 1 downto 0);
ADR_o : out std_logic_vector(g_addr_width - 1 downto 0);
DAT_i : in std_logic_vector(g_wb_data_width - 1 downto 0);
DAT_o : out std_logic_vector(g_wb_data_width - 1 downto 0);
ADR_o : out std_logic_vector(g_wb_addr_width - 1 downto 0);
CYC_o : out std_logic;
ERR_i : in std_logic;
RTY_i : in std_logic;
SEL_o : out std_logic_vector(f_div8(g_width) - 1 downto 0);
SEL_o : out std_logic_vector(f_div8(g_wb_addr_width) - 1 downto 0);
STB_o : out std_logic;
ACK_i : in std_logic;
WE_o : out std_logic;
......@@ -157,6 +157,8 @@ begin -- wrapper
master_o.adr <= adr_out(29 downto 0) & "00";
dat_in <= master_i.dat;
-- VME_IRQ_n_o <= (others => '0');
end wrapper;
SPEC_SW ?= $(shell readlink -f ~/wr-repos/spec-sw)
ETHERBONE ?= $(shell readlink -f ~/wr-repos/etherbone-core/api)
all:
make -C lib
make -C tests
make -C lib SPEC_SW=$(SPEC_SW) ETHERBONE=$(ETHERBONE)
make -C tests SPEC_SW=$(SPEC_SW) ETHERBONE=$(ETHERBONE)
clean:
make -C lib clean
make -C tests clean
\ No newline at end of file
make -C lib clean SPEC_SW=$(SPEC_SW) ETHERBONE=$(ETHERBONE)
make -C tests clean SPEC_SW=$(SPEC_SW) ETHERBONE=$(ETHERBONE)
\ No newline at end of file
......@@ -51,12 +51,12 @@ typedef struct {
typedef struct
{
fdelay_raw_time_t raw;
int64_t utc; /* TAI seconds */ /* FIXME: replace all UTCs with TAIs or seconds for clarity */
int32_t coarse; /* 125 MHz counter cycles */
int32_t frac; /* Fractional part (<8ns) */
uint16_t seq_id; /* Sequence ID to detect missed timestamps */
fdelay_raw_time_t raw;
} fdelay_time_t;
/*
......
SPEC_SW ?= $(shell readlink -f ~/wr-repos/spec-sw)
ETHERBONE ?= $(shell readlink -f ~/wr-repos/etherbone-core/api)
OBJS = fdelay_lib.o i2c_master.o onewire.o spec_common.o spec/tools/speclib.o spec/kernel/loader-ll.o fdelay_dmtd_calibration.o
OBJS = fdelay_lib.o i2c_master.o onewire.o fdelay_bus.o spec/tools/speclib.o spec/kernel/loader-ll.o fdelay_dmtd_calibration.o simple-eb.o
CFLAGS = -I../include -g -Imini_bone -Ispec/tools
CFLAGS = -I../include -g -Imini_bone -Ispec/tools -Ietherbone
ifeq ($(SPEC_SW),)
throw_error:
......@@ -12,9 +14,10 @@ all: spec lib
spec:
ln -s $(SPEC_SW) spec
ln -s $(ETHERBONE) etherbone
lib: $(OBJS)
gcc -shared -o libfinedelay.so $(OBJS)
gcc -shared -o libfinedelay.so $(OBJS) -letherbone
ar rc libfinedelay.a $(OBJS)
clean:
......
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <getopt.h>
#include "fdelay_lib.h"
#include "simple-eb.h"
#include "spec/tools/speclib.h"
#include "fdelay_lib.h"
void printk() {};
static void fd_spec_writel(void *priv, uint32_t data, uint32_t addr)
{
spec_writel(priv, data, addr);
}
static uint32_t fd_spec_readl(void *priv, uint32_t addr)
{
return spec_readl(priv, addr);
}
#if 0
static int spec_fdelay_create(fdelay_device_t *dev, int bus, int dev_fn)
{
uint32_t base;
dev->priv_io = spec_open(bus, dev_fn);
if(!dev->priv_io)
{
fprintf(stderr,"Can't map the SPEC @ %x:%x\n", bus, dev_fn);
return -1;
}
dev->writel = fd_spec_writel;
dev->readl = fd_spec_readl;
dev->base_addr = base;
//spec_vuart_init(dev->priv_io, 0xe0500); /* for communication with WRCore during DMTD calibration */
return 0;
}
#endif
static void fd_eb_writel(void *priv, uint32_t data, uint32_t addr)
{
ebs_write((eb_device_t) priv, addr, data);
}
static uint32_t fd_eb_readl(void *priv, uint32_t addr)
{
return ebs_read((eb_device_t) priv, addr);
}
#define VENDOR_CERN 0xce42
#define DEVICE_FD_CORE 0xf19ede1a
#define DEVICE_VUART 0xe2d13d04
int fdelay_probe(fdelay_device_t *dev, const char *location)
{
int bus = -1, dev_fn = -1;
char ip_addr[128];
int use_eb = 0;
uint32_t base_core;
if(!strncmp(location, "eb:", 3))
{
snprintf(ip_addr, sizeof(ip_addr), "udp/%s", location+3);
use_eb = 1;
} else if (!strncmp(location, "spec:"), 5) {
sscanf(location+5, "%d,%d", &bus, &dev_fn);
}
if(use_eb)
{
dbg("Probing with Etherbone [%s]\n", ip_addr);
if( ebs_init() != EB_OK)
{
fprintf(stderr,"Can't initialize Etherbone library.\n");
return -1;
}
if(ebs_open((eb_device_t*) &dev->priv_io, ip_addr) != EB_OK)
{
fprintf(stderr,"Can't connect to Etherbone device %s.\n", location);
return -1;
}
if(!ebs_sdb_find_device((eb_device_t ) dev->priv_io, VENDOR_CERN, DEVICE_FD_CORE, 0, &base_core))
{
fprintf(stderr,"Can't detect the FD core. Is the bitstream loaded?\n", location);
return -1;
}
dev->writel = fd_eb_writel;
dev->readl = fd_eb_readl;
dev->base_addr = base_core;
dbg("Found FD core @ 0x%x\n", base_core);
} else {
dbg("Sorry, SPEC temporarily unsupported\n.");
return -1;
}
}
fdelay_device_t *fdelay_create()
{
return (fdelay_device_t *) malloc(sizeof(fdelay_device_t));
}
......@@ -919,12 +919,12 @@ int fdelay_init(fdelay_device_t *dev, int init_flags)
hw->calib.zero_offset[i] = 50000;
}
/* Reset the FMC hardware. */
fd_do_reset(dev, FD_RESET_HW);
/* Initialize the clock system - AD9516 PLL */
oc_spi_init(dev);
if(sgpio_init(dev) < 0)
return -1;
......@@ -1445,11 +1445,11 @@ int fdelay_configure_sync(fdelay_device_t *dev, int mode)
if(mode == FDELAY_SYNC_LOCAL)
{
// fd_writel(0, FD_REG_GCR);
fd_writel(0, FD_REG_GCR);
fd_writel(0, FD_REG_TCR);
hw->wr_enabled = 0;
} else {
// fd_writel(0, FD_REG_GCR);
fd_writel(0, FD_REG_GCR);
fd_writel(FD_TCR_WR_ENABLE, FD_REG_TCR);
hw->wr_enabled = 1;
}
......@@ -1459,13 +1459,11 @@ int fdelay_check_sync(fdelay_device_t *dev)
{
fd_decl_private(dev)
// fprintf(stderr, "TCR %x\n", fd_readl(FD_REG_TCR) & FD_TCR_WR_LOCKED);
if(hw->wr_enabled && (fd_readl(FD_REG_TCR) & FD_TCR_WR_LOCKED))
{
fd_writel(FD_EIC_ISR_SYNC_STATUS, FD_REG_EIC_ISR);
fd_writel(FD_EIC_ISR_SYNC_STATUS, FD_REG_EIC_IER);
return 1;
fd_writel(FD_EIC_ISR_SYNC_STATUS, FD_REG_EIC_ISR);
fd_writel(FD_EIC_ISR_SYNC_STATUS, FD_REG_EIC_IER);
return 1;
} else if (!hw->wr_enabled)
return 1;
......
/*
* main.c
*
* Created on: Aug 10, 2012
* Author: bbielawski
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/time.h>
#include <unistd.h>
#include "etherbone.h"
static eb_socket_t socket;
static inline void process_result(eb_status_t result)
{
if (result != EB_OK)
{
printf("Error: %s\n", eb_status(result));
// exit(1);
}
return;
}
eb_status_t ebs_block_write(eb_device_t device, eb_address_t address, eb_data_t* data, int count, int autoincrement_address)
{
int write_done = 0;
void wr_callback(eb_user_data_t data, eb_device_t device, eb_operation_t operation, eb_status_t status)
{
write_done = 1;
}
eb_cycle_t cycle;
eb_status_t status = eb_cycle_open(device, NULL, wr_callback, &cycle);
if (status != EB_OK)
return status;
int i;
for (i = 0; i < count; i++)
{
eb_cycle_write(cycle, address, EB_DATA32 | EB_LITTLE_ENDIAN, data[i]);
if (autoincrement_address)
address += 4;
}
eb_cycle_close(cycle);
status = eb_device_flush(device);
while (!write_done) eb_socket_run(socket, 10); //wait forever
return status;
}
eb_status_t ebs_block_read(eb_device_t device, eb_address_t read_address, eb_data_t *rdata, int count, int autoincrement_address)
{
int read_done = 0;
void rd_callback(eb_user_data_t data, eb_device_t device, eb_operation_t op, eb_status_t status)
{
static int c = 0;
if (status != EB_OK)
{
fprintf(stderr, "read failed: %s\n", eb_status(status));
exit(-1);
}
for(; op != EB_NULL; op = eb_operation_next(op)) {
/* We read low bits first */
*rdata++ = eb_operation_data(op);
}
read_done = 1;
}
eb_cycle_t cycle;
eb_status_t status = eb_cycle_open(device, NULL, rd_callback, &cycle);
if (status != EB_OK)
return status;
int i;
for (i = 0; i < count; i++)
{
eb_cycle_read(cycle, read_address, EB_DATA32 | EB_LITTLE_ENDIAN, NULL);
if(autoincrement_address)
read_address += 4;
}
eb_cycle_close(cycle);
status = eb_device_flush(device);
while (!read_done) eb_socket_run(socket, -1); //wait forever
return status;
}
uint32_t ebs_read(eb_device_t device, eb_address_t addr)
{
eb_data_t rdata;
ebs_block_read(device, addr, &rdata, 1, 0);
return rdata;
}
void ebs_write(eb_device_t device, eb_address_t addr, eb_data_t data)
{
ebs_block_write(device, addr, &data, 1, 0);
}
eb_status_t ebs_init()
{
eb_status_t status = EB_OK;
status = eb_socket_open(EB_ABI_CODE, 0, EB_DATA32 | EB_ADDR32, &socket);
process_result(status);
}
eb_status_t ebs_shutdown()
{
return eb_socket_close(socket);
}
eb_status_t ebs_open(eb_device_t *dev, const char *network_address)
{
eb_status_t status = EB_OK;
status = eb_device_open(socket, network_address, EB_DATA32 | EB_ADDR32, 5, dev);
process_result(status);
return status;
}
eb_status_t ebs_close(eb_device_t dev)
{
return eb_device_close(dev);
}
struct bus_record {
int i;
int stop;
eb_address_t addr_first, addr_last;
struct bus_record* parent;
};
int ebs_sdb_find_device(eb_device_t dev, uint32_t vendor, uint32_t device, int seq, uint32_t *base_addr)
{
struct bus_record br;
int done = 0, found = 0, n = 0;
void scan_cb(eb_user_data_t user, eb_device_t dev, sdb_t sdb, eb_status_t status) {
struct bus_record br;
int devices;
br.parent = (struct bus_record*)user;
br.parent->stop = 1;
if (status != EB_OK) {
fprintf(stderr, "failed to retrieve SDB: %s\n", eb_status(status));
exit(1);
}
devices = sdb->interconnect.sdb_records - 1;
for (br.i = 0; br.i < devices; ++br.i) {
sdb_record_t des;
des = &sdb->record[br.i];
if(des->empty.record_type == sdb_device)
{
if(des->device.sdb_component.product.vendor_id == vendor &&
des->device.sdb_component.product.device_id == device)
{
if(n == seq)
{
*base_addr = des->device.sdb_component.addr_first;
found = 1;
return;
}
n ++;
}
}
}
done = 1;
}
br.parent = 0;
br.i = -1;
br.stop = 0;
br.addr_first = 0;
br.addr_last = ~(eb_address_t)0;
br.addr_last >>= (sizeof(eb_address_t) - (eb_device_width(dev) >> 4))*8;
if(eb_sdb_scan_root(dev, &br, &scan_cb) != EB_OK)
return -1;
while(!done && !found) // fixme: crap code
eb_socket_run(eb_device_socket(dev), -1);
return found;
}
#if 0
main()
{
eb_device_t dev;
uint32_t base;
ebs_init();
ebs_open(&dev, "udp/192.168.10.11");
ebs_sdb_find_device(dev, 0xce42, 0xf19ede1a, 0, &base);
printf("base addr: %x\n", base);
}
#endif
#ifndef __SIMPLE_EB_H
#define __SIMPLE_EB_H
#include <stdint.h>
#include "etherbone.h"
eb_status_t ebs_block_write(eb_device_t device, eb_address_t address, eb_data_t* data, int count, int autoincrement_address);
eb_status_t ebs_block_read(eb_device_t device, eb_address_t read_address, eb_data_t *rdata, int count, int autoincrement_address);
uint32_t ebs_read(eb_device_t device, eb_address_t addr);
void ebs_write(eb_device_t device, eb_address_t addr, eb_data_t data);
eb_status_t ebs_init();
eb_status_t ebs_shutdown();
eb_status_t ebs_open(eb_device_t *dev, const char *network_address);
eb_status_t ebs_close(eb_device_t dev);
int ebs_sdb_find_device(eb_device_t dev, uint32_t vendor, uint32_t device, int seq, uint32_t *base_addr);
#endif
#include <stdio.h>
#include <stdint.h>
#include <getopt.h>
#include "spec/tools/speclib.h"
#include "fdelay_lib.h"
static void fd_spec_writel(void *priv, uint32_t data, uint32_t addr)
{
spec_writel(priv, data, addr);
}
static uint32_t fd_spec_readl(void *priv, uint32_t addr)
{
return spec_readl(priv, addr);
}
int spec_fdelay_create_bd(fdelay_device_t *dev, int bus, int dev_fn, uint32_t base)
{
dev->priv_io = spec_open(bus, dev_fn);
if(!dev->priv_io)
{
fprintf(stderr,"Can't map the SPEC @ %x:%x\n", bus, dev_fn);
return -1;
}
dev->writel = fd_spec_writel;
dev->readl = fd_spec_readl;
dev->base_addr = base;
spec_vuart_init(dev->priv_io, 0xe0500); /* for communication with WRCore during DMTD calibration */
return 0;
}
int spec_fdelay_create(fdelay_device_t *dev, int argc, char *argv[])
{
int bus = -1, dev_fn = -1, c;
uint32_t base = 0x80000;
while ((c = getopt (argc, argv, "b:d:f:")) != -1)
{
switch(c)
{
case 'b':
sscanf(optarg, "%i", &bus);
break;
case 'd':
sscanf(optarg, "%i", &dev_fn);
break;
case 'u':
sscanf(optarg, "%i", &base);
break;
default:
fprintf(stderr,
"Use: \"%s [-b bus] [-d devfn] [-u Fine Delay base] [-k]\"\n", argv[0]);
fprintf(stderr,
"By default, the first available SPEC is used and the FD is assumed at 0x%x.\n", base);
return -1;
}
}
return spec_fdelay_create_bd(dev, bus, dev_fn, base);
}
#!/usr/bin/python2
#!/usr/bin/python
import sys
import PyQt4
......@@ -70,11 +70,7 @@ def on_chk_wr():
if __name__ == "__main__":
import os,sys
if(os.getuid() != 0):
print("Sorry, I must be run as root...");
sys.exit(-1)
card = FineDelay()
card = FineDelay(sys.argv[1])
app = QApplication(sys.argv)
......
......@@ -22,35 +22,17 @@ class fd_timestamp(Structure):
return "%d:%d" % (self.utc, self.nsecs())
class FineDelay:
BASE_ADDR = 0x80000
def __init__(self, bus = -1):
self.fdelay = CDLL('../lib/libfinedelay.so')
# load the firmware for the SPEC:
SYNC_LOCAL = 1
SYNC_WR = 2
self.card = self.fdelay.spec_open(c_int(bus), c_int(-1));
if(self.card == 0):
print ("SPEC enumeration failed");
sys.exit(-1)
if ~os.path.isfile("spec_top_fd.bin"):
print ("No firmware file found. Attempting to download one from OHWR")
import urllib
urllib.urlretrieve ("http://www.ohwr.org/attachments/download/1350/spec_top.bin", "spec_top_fd.bin")
cwd = os.getcwd();
if(self.fdelay.spec_load_bitstream(c_voidp(self.card), c_char_p(cwd + "/spec_top_fd.bin")) < 0):
print ("Firmware loader failure");
sys.exit(-1)
self.fdelay.spec_close(c_voidp(self.card))
self.handle = pointer(create_string_buffer('\000' * 16384)) #allocate some memory for the fdelay_device_t
def __init__(self, location="udp/192.168.10.11"):
self.fdelay = CDLL('../lib/libfinedelay.so')
if(self.fdelay.spec_fdelay_create_bd(self.handle, c_int(bus), c_int(-1), c_ulong(self.BASE_ADDR)) < 0):
self.handle = self.fdelay.fdelay_create();
if(self.fdelay.fdelay_probe(self.handle, c_char_p(location)) < 0):
print ("FD enumeration failed")
sys.exit(-1)
......@@ -68,26 +50,30 @@ class FineDelay:
def conf_readout(self, enable):
self.fdelay.fdelay_configure_readout(self.handle, enable)
# def conf_sync(self, mode):
# self.fdelay.fdelay_configure_sync(self.handle, mode)
def conf_sync(self, mode):
self.fdelay.fdelay_configure_sync(self.handle, mode)
def conf_pulsegen(self, channel, enable, t_start_utc, t_start_coarse, width, delta, count):
t = fd_timestamp(utc=c_ulonglong(t_start_utc), coarse=c_ulong(t_start_coarse))
#print "channel:%d enable:%d start_t:%d width:%d delta:%d count:%d"%(channel, enable, t.utc, width, delta, count)
self.fdelay.fdelay_configure_pulse_gen(self.handle, c_int(channel), c_int(enable), t,
c_ulonglong(width), c_ulonglong(delta), c_int(count))
# def conf_pulsegen(self, channel, enable, t_start_utc, t_start_coarse, width, delta, count):
# t = fd_timestamp(utc=c_ulonglong(t_start_utc), coarse=c_ulong(t_start_coarse))
# #print "channel:%d enable:%d start_t:%d width:%d delta:%d count:%d"%(channel, enable, t.utc, width, delta, count)
# self.fdelay.fdelay_configure_pulse_gen(self.handle, c_int(channel), c_int(enable), t,
# c_ulonglong(width), c_ulonglong(delta), c_int(count))
def set_time(self, utc, coarse):
t = fd_timestamp(utc=c_ulonglong(utc), coarse=c_ulong(coarse))
self.fdelay.fdelay_set_time(self.handle, t)
# def set_time(self, utc, coarse):
# t = fd_timestamp(utc=c_ulonglong(utc), coarse=c_ulong(coarse))
# self.fdelay.fdelay_set_time(self.handle, t)
def get_time(self):
t = fd_timestamp()
self.fdelay.fdelay_get_time(self.handle, byref(t))
return t
# def get_time(self):
# t = fd_timestamp()
# self.fdelay.fdelay_get_time(self.handle, byref(t))
# return t
def get_sync_status(self):
return "none"; #fixme: new WR state machine
c = self.fdelay.fdelay_check_sync(self.handle)
if(c):
return "synced"
else:
return "not synced"
def read_ts(self):
buf = (fd_timestamp * 256)();
......
TESTS = dmtd_calibration gs_logger random_pulse_test sweep_test temperature_calibration
TESTS = gs_logger # dmtd_calibration gs_logger random_pulse_test sweep_test temperature_calibration
CFLAGS = -I../include
LDFLAGS = -L../lib -static -lfinedelay -lm
LDFLAGS = -L../lib ../lib/libfinedelay.a -lm -letherbone
CC=gcc
.PHONY: all
......
......@@ -44,7 +44,7 @@ struct board_def {
int term_on;
int64_t input_offset;
int64_t output_offset;
int hw_index;
char *location;
int in_use;
int fd;
int prev_seq;
......@@ -60,7 +60,7 @@ struct board_def boards[MAX_BOARDS];
static FILE *log_file = NULL;
void log_write(fdelay_time_t *t, int card_id)
void log_write(fdelay_time_t *t, const char *location)
{
struct binary_timestamp bt;
if(!log_file)
......@@ -71,7 +71,7 @@ void log_write(fdelay_time_t *t, int card_id)
bt.ts.seq_id = t->seq_id;
bt.ts.channel = 0;
bt.type = TYPE_TIMESTAMP;
bt.card_id = card_id;
bt.card_id = 0; //card_id; // fixme: hash location string?
fwrite(&bt, sizeof(struct binary_timestamp), 1, log_file);
fflush(log_file);
}
......@@ -216,10 +216,10 @@ void load_config(const char *config_file)
if(!strcmp(cmd, "hw_index"))
if(!strcmp(cmd, "location"))
{
CUR.hw_index = parse_num(args[0]);
printf("Adding board %d, hw_index %x\n", current_board, CUR.hw_index);
CUR.location = strdup(args[0]);
printf("Adding board %d, location %s\n", current_board, CUR.location);
}
......@@ -261,13 +261,12 @@ void load_config(const char *config_file)
#undef CUR
void enable_wr(fdelay_device_t *b, int index)
void enable_wr(fdelay_device_t *b)
{
int lock_retries = 50;
printf("Locking to WR network [board=%d]...", index);
printf("Locking to WR network ...");
fflush(stdout);
fdelay_configure_sync(b, FDELAY_SYNC_LOCAL);
/* sleep(2);
fdelay_configure_sync(b, FDELAY_SYNC_WR);
while(fdelay_check_sync(b) <= 0)
......@@ -283,7 +282,7 @@ void enable_wr(fdelay_device_t *b, int index)
}
printf("\n");
fflush(stdout);*/
fflush(stdout);
}
/* Add two timestamps */
......@@ -313,22 +312,22 @@ int configure_board(struct board_def *bdef)
if(spec_fdelay_create_bd(b, bdef->hw_index >>8, bdef->hw_index & 0xff, 0x80000) < 0)
if(fdelay_probe(b, bdef->location) < 0)
{
fprintf(stderr,"Can't open fdelay board @ hw_index %x\n", bdef->hw_index);
fprintf(stderr,"Can't open fdelay board @ %s\n", bdef->location);
exit(-1);
}
if(fdelay_init(b, 0) < 0)
{
fprintf(stderr,"Can't initialize fdelay board @ hw_index %x\n", bdef->hw_index);
fprintf(stderr,"Can't initialize fdelay board @ %s\n", bdef->location);
exit(-1);
}
bdef->b = b;
fdelay_configure_trigger(bdef->b, 0, bdef->term_on);
enable_wr(b, bdef->hw_index);
enable_wr(b);
int val = bdef->input_offset;
// fdelay_sysfs_set((struct __fdelay_board *)b, "fd-input/user-offset", (uint32_t *)&val);
......@@ -431,9 +430,9 @@ void handle_readout(struct board_def *bdef)
{
t_ps = (t.coarse * 8000LL) + ((t.frac * 8000LL) >> 12);
printf("card 0x%04x, seq %5i: time %lli s, %lli.%03lli ns [count %d] ", bdef->hw_index, t.seq_id, t.utc, t_ps / 1000LL, t_ps % 1000LL, (t.raw.tsbcr >> 10) & 0x3ff);
printf("card %s, seq %5i: time %lli s, %lli.%03lli ns [count %d] ", bdef->location, t.seq_id, t.utc, t_ps / 1000LL, t_ps % 1000LL, (t.raw.tsbcr >> 10) & 0x3ff);
// printf("raw utc=%lld coarse=%d startoffs=%d suboffs=%d frac=%d [%x]\n", t.raw.utc, t.raw.coarse, t.raw.start_offset, t.raw.subcycle_offset, t.raw.frac- 30000, t.raw.frac);
log_write(&t, bdef->hw_index);
log_write(&t, bdef->location);
if(((bdef->prev_seq + 1) & 0xffff) != (t.seq_id & 0xffff))
{
......
......@@ -9,7 +9,7 @@ log_file ./pp.log
board 0
# Hardware index if the board (i.e. the PCIe bus/dev)
hw_index 0x0b00
location eb:192.168.10.11
# Select termination (warning! affects the accuracy!)
termination 0
......
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