Commit 6cb4c9ee authored by Maciej Lipinski's avatar Maciej Lipinski

Merge branch 'dio_extension' into 'master'

Dio extension

See merge request !4
parents 31e53528 1c190a5f
......@@ -53,3 +53,5 @@ modules.order
# Project Specifi #
###################
wr-dio.mod*
sw/irq-demo/irq-demo
sw/irq-demo/*.log
\ No newline at end of file
*~
*.aux
*.cp
*.cps
*.fn
*.html
*.info
*.ky
*.log
*.pdf
*.pg
*.texi
*.toc
*.tp
/*.txt
*.vr
#
# Makefile for the documentation directory
#
# Copyright 1994,2000,2010,2011 Alessandro Rubini <rubini@linux.it>
#
#################
# There is not basenames here, all *.in are considered input
INPUT = $(wildcard *.in)
TEXI = $(INPUT:.in=.texi)
INFO = $(INPUT:.in=.info)
HTML = $(INPUT:.in=.html)
TXT = $(INPUT:.in=.txt)
PDF = $(INPUT:.in=.pdf)
ALL = $(INFO) $(HTML) $(TXT) $(PDF)
MAKEINFO ?= makeinfo
RELEASE=$(shell git describe --always --dirty)
%.texi: %.in
@rm -f $@
sed s/__RELEASE_GIT_ID__/$(RELEASE)/ $< | sed -f ./infofilter > $@
emacs -batch --no-site-file -l fixinfo $@
chmod -w $@
%.pdf: %.texi
texi2pdf --batch $<
%.info: %.texi
$(MAKEINFO) $< -o $@
%.html: %.texi
$(MAKEINFO) --html --no-split -o $@ $<
%.txt: %.texi
$(MAKEINFO) --no-headers $< > $@
##############################################
.PHONY: all images check terse clean install
.INTERMEDIATE: $(TEXI)
all: images $(ALL)
$(MAKE) terse
images::
if [ -d images ]; then $(MAKE) -C images || exit 1; fi
check: _err.ps
gs -sDEVICE=linux -r320x200x16 $<
terse:
for n in cp fn ky pg toc tp vr aux log; do rm -f *.$$n; done
rm -f *~
clean: terse
rm -f $(ALL) $(TEXI)
install:
# add the other unused targets, so the rule in ../Makefile works
modules modules_install:
;; use:
;; emacs -batch -l ./fixinfo.el <file>
;; or, better:
;; emacs -batch --no-site-file -l ./fixinfo.el <file>
(defun fixinfo (file)
(find-file-other-window file)
(message (concat "Maxing texinfo tree in " file))
(texinfo-all-menus-update)
(texinfo-every-node-update)
(save-buffer)
(kill-buffer (current-buffer))
)
;; loop over command line arguments
(mapcar 'fixinfo command-line-args-left)
(kill-emacs)
This diff is collapsed.
#! /usr/bin/sed -f
# allow "%" as a comment char, but only at the beginning of the line
s/^%/@c /
#s/[^\\]%.*$//
s/^\\%/%/
#preserve blanks and braces in @example blocks
/^@example/,/^@end example/ s/{/@{/g
/^@example/,/^@end example/ s/}/@}/g
/^@example/,/^@end example/ p
/^@example/,/^@end example/ d
/^@smallexample/,/^@end smallexample/ s/{/@{/g
/^@smallexample/,/^@end smallexample/ s/}/@}/g
/^@smallexample/,/^@end smallexample/ p
/^@smallexample/,/^@end smallexample/ d
# remove leading blanks
s/^[ ]*//
......@@ -3,6 +3,7 @@ files = ["wr_dio_wb.vhd",
"wr_dio.vhd",
"wr_dio_pkg.vhd",
"pulse_gen_pl.vhd",
"immed_pulse_counter.vhd",
"dummy_time.vhd" ]
"immed_pulse_counter.vhd",
"dummy_time.vhd",
"imm_pulse_train_gen.vhd" ]
-------------------------------------------------------------------------------
-- Title : Immediate pulse train generator
-- Project : White Rabbit Network Interface
-------------------------------------------------------------------------------
-- File : imm_pulse_train_gen.vhd
-- Author : Jorge Machado
-- Company : Seven Solutions
-- Created : 2020-03-19
-- Last update:
-- Platform : FPGA-generic
-- Standard : VHDL
-------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity imm_pulse_train_gen is
generic(
pulse_period_width : integer := 28
);
port(
clk_ref_i : in std_logic;
rst_n_i : in std_logic;
dio_pulse_immed_stb_i : in std_logic;
pulse_period_i : in std_logic_vector(pulse_period_width-1 downto 0);
pulse_output_o : out std_logic
);
end imm_pulse_train_gen;
architecture Behavioral of imm_pulse_train_gen is
signal nozeroperiod, nozeroperiod_aux : boolean;
signal pulse_period : std_logic_vector(pulse_period_width-1 downto 0);
signal dio_pulse_immed_stb_d0, dio_pulse_immed_stb_d1,
dio_pulse_immed_stb_d2, dio_pulse_immed_stb_d3 : std_logic;
-- Internal registers to hold pulse duration
signal counter : unsigned (pulse_period_width-1 downto 0);
-- Signals for states
type counter_state is (WAIT_ST, COUNTING, CAPTURE_PERIOD, TRIGGER);
signal state : counter_state;
signal repeat_pulse : std_logic;
-- Aux
constant zeros : std_logic_vector(pulse_period_width-1 downto 0) := (others => '0');
constant initial_pulse_delay_compensation : integer := 7;
constant repeat_pulse_delay_compensation : integer := 4;
begin
synchronization : process(clk_ref_i, rst_n_i)
begin
if (rst_n_i = '0') then
dio_pulse_immed_stb_d0 <= '0';
dio_pulse_immed_stb_d1 <= '0';
dio_pulse_immed_stb_d2 <= '0';
dio_pulse_immed_stb_d3 <= '0';
elsif rising_edge(clk_ref_i) then
dio_pulse_immed_stb_d0 <= dio_pulse_immed_stb_i;
dio_pulse_immed_stb_d1 <= dio_pulse_immed_stb_d0;
dio_pulse_immed_stb_d2 <= dio_pulse_immed_stb_d1;
dio_pulse_immed_stb_d3 <= dio_pulse_immed_stb_d2;
--pulse_period <= pulse_period_i;
nozeroperiod_aux <= pulse_period_i /= zeros;
if ((dio_pulse_immed_stb_d2 = '1' and dio_pulse_immed_stb_d1 = '0') or (state = CAPTURE_PERIOD)) then
nozeroperiod <= nozeroperiod_aux;
pulse_period <= pulse_period_i;
end if;
end if;
end process;
state_process : process(clk_ref_i, rst_n_i)
begin
if (rst_n_i = '0') then
counter <= (others => '0');
state <= WAIT_ST;
repeat_pulse <= '0';
elsif rising_edge(clk_ref_i) then
case state is
when WAIT_ST =>
if dio_pulse_immed_stb_d3 = '1' and nozeroperiod then
state <= COUNTING;
--Store the period two cycle before than the immed_pulse_counter_process to not lost one cycle.
counter <= unsigned(pulse_period)-initial_pulse_delay_compensation;
elsif repeat_pulse = '1' and nozeroperiod then
state <= COUNTING;
--Store the period four cycles before
counter <= unsigned(pulse_period)-repeat_pulse_delay_compensation;
else
state <= WAIT_ST;
end if;
when COUNTING =>
if counter = 0 then
state <= CAPTURE_PERIOD;
elsif dio_pulse_immed_stb_d2 = '1' then
state <= WAIT_ST;
else
state <= COUNTING;
counter <= counter-1;
end if;
when CAPTURE_PERIOD =>
state <= TRIGGER;
when TRIGGER =>
state <= WAIT_ST;
if(nozeroperiod) then
repeat_pulse <= '1';
else
repeat_pulse <= '0';
end if;
when others =>
state <= WAIT_ST;
end case;
end if;
end process;
output_process : process(rst_n_i, state)
begin
if (rst_n_i = '0') then
pulse_output_o <= '0';
else
case state is
when WAIT_ST =>
pulse_output_o <= '0';
when COUNTING =>
pulse_output_o <= '0';
when TRIGGER =>
pulse_output_o <= '1';
when others =>
pulse_output_o <= '0';
end case;
end if;
end process;
end Behavioral;
......@@ -66,6 +66,8 @@ architecture rtl of immed_pulse_counter is
-- Aux
constant zeros : std_logic_vector(pulse_length_width-1 downto 0) := (others => '0');
signal pulse_length : std_logic_vector(pulse_length_width-1 downto 0);
begin -- architecture rtl
synchronization : process(clk_i, rst_n_i)
......@@ -81,8 +83,10 @@ begin -- architecture rtl
pulse_start_d2 <= pulse_start_d1;
pulse_start_d3 <= pulse_start_d2;
nozerolength_aux <= pulse_length_i /= zeros;
--pulse_length <= pulse_length_i;
if (pulse_start_d2 = '1' and pulse_start_d1 = '0') then
nozerolength <= nozerolength_aux;
nozerolength <= nozerolength_aux;
pulse_length <= pulse_length_i;
end if;
end if;
end process;
......@@ -97,7 +101,7 @@ begin -- architecture rtl
when WAIT_ST =>
if pulse_start_d3 = '1' and nozerolength then
state <= COUNTING;
counter <= unsigned(pulse_length_i)-1;
counter <= unsigned(pulse_length)-1;
else
state <= WAIT_ST;
end if;
......@@ -114,7 +118,7 @@ begin -- architecture rtl
end if;
end process;
output_process : process(counter, state)
output_process : process(rst_n_i, state)
begin
if (rst_n_i = '0') then
pulse_output_o <= '0';
......
......@@ -76,8 +76,9 @@ entity pulse_gen_pl is
trig_utc_i : in std_logic_vector(39 downto 0);
trig_cycles_i : in std_logic_vector(27 downto 0);
trig_valid_p1_i : in std_logic;
pulse_length_i : in std_logic_vector(27 downto 0)
);
pulse_length_i : in std_logic_vector(27 downto 0);
pulse_period_i : in std_logic_vector(27 downto 0)
);
end pulse_gen_pl;
......@@ -87,7 +88,7 @@ architecture rtl of pulse_gen_pl is
signal trig_utc, trig_utc_ref : std_logic_vector(39 downto 0);
signal trig_cycles, trig_cycles_ref : std_logic_vector(27 downto 0);
signal pulse_length, pulse_length_ref : std_logic_vector(27 downto 0);
signal pulse_period, pulse_period_ref : std_logic_vector(27 downto 0);
-- Signals for the synchronizer
signal trig_valid_sys_d1, trig_valid_sys_d2 : std_logic;
signal rst_from_sync, rst_from_sync_d1 : std_logic;
......@@ -97,8 +98,11 @@ architecture rtl of pulse_gen_pl is
-- Aux
constant zeros : std_logic_vector(27 downto 0) := (others => '0');
signal counter : unsigned (27 downto 0);
signal nozerolength : boolean;
signal counter, train_counter : unsigned (27 downto 0);
signal nozerolength, nozeroperiod : boolean;
signal pulse_o_internal : std_logic;
signal pulse_train_trigger : std_logic;
signal load_values : std_logic;
begin -- architecture rtl
......@@ -110,10 +114,12 @@ begin -- architecture rtl
trig_utc <= (others => '0');
trig_cycles <= (others => '0');
pulse_length <= (others => '0');
pulse_period <= (others => '0');
elsif trig_valid_p1_i = '1' then
trig_utc <= trig_utc_i;
trig_cycles <= trig_cycles_i;
pulse_length <= pulse_length_i;
pulse_period <= pulse_period_i;
end if;
end if;
end process trig_regs;
......@@ -166,11 +172,13 @@ begin -- architecture rtl
trig_regs_ref : process (clk_ref_i)
begin
if clk_ref_i'event and clk_ref_i = '1' then
if trig_valid_ref_p1 = '1' then
if trig_valid_ref_p1 = '1' or load_values = '1' then
trig_utc_ref <= trig_utc;
trig_cycles_ref <= trig_cycles;
pulse_length_ref <= pulse_length;
pulse_period_ref <= pulse_period;
pulse_length_ref <= pulse_length;
nozerolength <= pulse_length /= zeros;
nozeroperiod <= pulse_period /= zeros;
end if;
end if;
end process trig_regs_ref;
......@@ -192,6 +200,7 @@ begin -- architecture rtl
end if;
end process ready_for_trig;
-- Produce output
-- Note rst_n_i is used as an async reset because it comes from the
-- clk_sys_i domain. Not the most elegant but it ensures no glitches
......@@ -201,19 +210,37 @@ begin -- architecture rtl
gen_out : process (rst_n_i, clk_ref_i)
begin
if rst_n_i = '0' then
pulse_o <= '0';
pulse_o_internal <= '0';
elsif clk_ref_i'event and clk_ref_i = '1' then
if tm_time_valid_i = '0' then
pulse_o <= '0';
elsif tm_utc_i = trig_utc_ref and tm_cycles_i = trig_cycles_ref and nozerolength then
pulse_o <= '1';
pulse_o_internal <= '0';
elsif tm_utc_i = trig_utc_ref and tm_cycles_i = trig_cycles_ref and nozerolength then --Original trigger
pulse_o_internal <= '1';
counter <= unsigned(pulse_length_ref)-1;
elsif counter /= 0 then
train_counter <= unsigned(pulse_period_ref); --Store the value of the period
elsif counter /= 0 then --The period counter is reduced at the same time than the pulse counter
counter <= counter-1;
if(train_counter /= 0) then
train_counter <= train_counter-1;
end if;
-- elsif(train_counter = 10) then --Load new values for then next cycle
-- load_values <= '1';
elsif(train_counter = 1) then --Period trigger. Rearm both counters
pulse_o_internal <= '1';
counter <= unsigned(pulse_length_ref)-1;
train_counter <= unsigned(pulse_period_ref);
--load_values <= '1';
elsif train_counter > 1 then
train_counter <= train_counter-1;
pulse_o_internal <= '0';
load_values <= '0';
else
pulse_o <= '0';
pulse_o_internal <= '0';
load_values <= '0';
end if;
end if;
end process gen_out;
end architecture rtl;
pulse_o <= pulse_o_internal;
end architecture rtl;
\ No newline at end of file
This diff is collapsed.
......@@ -70,10 +70,10 @@ package wr_dio_pkg is
wbd_width => x"7", -- 8/16/32-bit port granularity
sdb_component => (
addr_first => x"0000000000000000",
addr_last => x"00000000000000ff",
addr_last => x"00000000000003ff",
product => (
vendor_id => x"00000000000075CB", -- SEVEN SOLUTIONS
device_id => x"00000001",
device_id => x"00000003",
version => x"00000002",
date => x"20120709",
name => "WR-DIO-Registers ")));
......
This diff is collapsed.
This diff is collapsed.
......@@ -216,8 +216,13 @@ entity dio_common_top is
-- I2C interface for accessing FMC EEPROM. Deprecated, was used in
-- pre-v3.0 releases to store WRPC configuration. Now we use Flash for this.
dio_scl_b : inout std_logic;
dio_sda_b : inout std_logic
dio_sda_b : inout std_logic;
-- Leap second
leap_second_value_i : in std_logic_vector(15 downto 0);
leap_second_flag_59_i : in std_logic;
leap_second_flag_61_i : in std_logic;
leap_second_flag_valid_i : in std_logic
);
end entity dio_common_top;
......@@ -240,10 +245,10 @@ architecture top of dio_common_top is
dio_clk_i : in std_logic;
dio_pps_i : in std_logic;
dio_in_i : in std_logic_vector(4 downto 0);
dio_out_o : out std_logic_vector(4 downto 0);
dio_oe_n_o : out std_logic_vector(4 downto 0);
dio_term_en_o : out std_logic_vector(4 downto 0);
dio_in_i : in std_logic_vector(5 downto 0);
dio_out_o : out std_logic_vector(5 downto 0);
dio_oe_n_o : out std_logic_vector(5 downto 0);
dio_term_en_o : out std_logic_vector(5 downto 0);
dio_onewire_b : inout std_logic;
dio_sdn_n_o : out std_logic;
dio_sdn_ck_n_o : out std_logic;
......@@ -265,7 +270,13 @@ architecture top of dio_common_top is
slave_i : in t_wishbone_slave_in;
slave_o : out t_wishbone_slave_out;
dio_int : out std_logic
dio_int : out std_logic;
-- Leap second
leap_second_value_i : in std_logic_vector(15 downto 0);
leap_second_flag_59_i : in std_logic;
leap_second_flag_61_i : in std_logic;
leap_second_flag_valid_i : in std_logic
);
end component;
......@@ -325,8 +336,8 @@ architecture top of dio_common_top is
signal svec_led : std_logic_vector(15 downto 0);
-- DIO Mezzanine
signal dio_in : std_logic_vector(4 downto 0);
signal dio_out : std_logic_vector(4 downto 0);
signal dio_in : std_logic_vector(5 downto 0);
signal dio_out : std_logic_vector(5 downto 0);
-- Timecode output
signal tm_time_valid : std_logic;
......@@ -349,6 +360,9 @@ architecture top of dio_common_top is
-- VIC-only signals
signal vic_only_irqs : std_logic_vector(3 downto 0);
signal dio_oe_n_o_internal : std_logic_vector(5 downto 0);
signal dio_term_en_o_internal : std_logic_vector(5 downto 0);
begin -- architecture top
......@@ -663,8 +677,8 @@ begin -- architecture top
dio_pps_i => wrc_pps_out,
dio_in_i => dio_in,
dio_out_o => dio_out,
dio_oe_n_o => dio_oe_n_o,
dio_term_en_o => dio_term_en_o,
dio_oe_n_o => dio_oe_n_o_internal,
dio_term_en_o => dio_term_en_o_internal,
dio_onewire_b => dio_onewire_b,
dio_sdn_n_o => dio_sdn_n_o,
dio_sdn_ck_n_o => dio_sdn_ck_n_o,
......@@ -676,9 +690,16 @@ begin -- architecture top
tm_cycles_i => tm_cycles,
slave_i => cnx_slave_in(c_WB_SLAVE_DIO),
slave_o => cnx_slave_out(c_WB_SLAVE_DIO),
dio_int => dio_int
dio_int => dio_int,
leap_second_value_i => leap_second_value_i,
leap_second_flag_59_i => leap_second_flag_59_i,
leap_second_flag_61_i => leap_second_flag_61_i,
leap_second_flag_valid_i => leap_second_flag_valid_i
);
dio_oe_n_o <= dio_oe_n_o_internal(4 downto 0);
dio_term_en_o <= dio_term_en_o_internal(4 downto 0);
vic_vec_int(0) <= dio_int;
NIC_GEN : if g_dio_mode = DIO_NIC generate
......
......@@ -205,12 +205,16 @@ package dio_common_top_pkg is
dio_onewire_b : inout std_logic;
dio_sdn_n_o : out std_logic;
dio_sdn_ck_n_o : out std_logic;
-- I2C interface for accessing FMC EEPROM. Deprecated, was used in
-- pre-v3.0 releases to store WRPC configuration. Now we use Flash for this.
dio_scl_b : inout std_logic;
dio_sda_b : inout std_logic
dio_sda_b : inout std_logic;
-- Leap second
leap_second_value_i : in std_logic_vector(15 downto 0);
leap_second_flag_59_i : in std_logic;
leap_second_flag_61_i : in std_logic;
leap_second_flag_valid_i : in std_logic
);
end component;
......@@ -238,7 +242,7 @@ package dio_common_top_pkg is
constant c_nic_bridge_sdb : t_sdb_bridge :=
f_xwb_bridge_manual_sdb(x"0001ffff", x"00011000");
constant c_wr_dio_bridge_sdb : t_sdb_bridge :=
f_xwb_bridge_product_manual_sdb(x"00000fff", x"00000400", c_xwr_dio_sdb);
f_xwb_bridge_product_manual_sdb(x"00000fff", x"00000800", c_xwr_dio_sdb);
-- Primary wishbone crossbar layout (NIC)
constant c_NIC_WB_LAYOUT : t_sdb_record_array(c_NUM_WB_SLAVES - 1 downto 0) := (
......
......@@ -283,7 +283,11 @@ begin
dio_sdn_n_o => dio_sdn_n_o,
dio_sdn_ck_n_o => dio_sdn_ck_n_o,
dio_scl_b => dio_scl_b,
dio_sda_b => dio_sda_b
dio_sda_b => dio_sda_b,
leap_second_value_i => x"0025", -- leapSeoncs=37 in 2020
leap_second_flag_59_i => '0',
leap_second_flag_61_i => '0',
leap_second_flag_valid_i => '1'
);
end architecture top;
......@@ -15,6 +15,8 @@ export FMC_BUS_ABS
DIRS = $(FMC_BUS_ABS) kernel tools
CFLAGS += $(WR_DIO_CFLAGS)
.PHONY: all clean modules install modules_install $(DIRS)
all clean modules install modules_install: $(DIRS)
......
CFLAGS += -I./dep
irq-demo: irq-demo.c ./dep/*.c
gcc -o irq-demo irq-demo.c ./dep/*.c $(CFLAGS) -lm
clean:
-rm irq-demo
-rm .irq-demo.log
/*
* Copyright (C) 2020 CERN (www.cern.ch)
*
* Author: Miguel Jimenez Lopez <miguel.jimenez@sevensols.com>
*
* Released to the public domain as sample code to be customized.
*
* This work is part of the White Rabbit project, a research effort led
* by CERN, the European Institute for Nuclear Research.
*/
#ifndef __FILE_LOG_PRIVATE_H__
#define __FILE_LOG_PRIVATE_H__
struct file_log_private {
FILE *fp;
char *path;
};
static int check_file_log_priv(log_device dev);
static struct file_log_private * get_private_info(log_device dev);
static void init_file_log_device(log_device dev);
static void send_to_file_log_device(log_device, const char *msg);
static void deinit_file_log_device(log_device dev);
#endif
/*
* Copyright (C) 2020 CERN (www.cern.ch)
*
* Author: Miguel Jimenez Lopez <miguel.jimenez@sevensols.com>
*
* Released to the public domain as sample code to be customized.
*
* This work is part of the White Rabbit project, a research effort led
* by CERN, the European Institute for Nuclear Research.
*/
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include "log-device.h"
#include "file-log-private.h"
static struct log_device_iface _file_log_iface =
{
.init_log_device = init_file_log_device,
.send_to_log_device = send_to_file_log_device,
.clear_log_device = NULL,
.deinit_log_device = deinit_file_log_device,
};
static const log_device_interface file_log_iface = &_file_log_iface;
log_device create_file_log_device(const char *path)
{
return create_log_device((void *)path, file_log_iface);
}
static void init_file_log_device(log_device dev)
{
struct file_log_private *priv;
priv = calloc(1, sizeof(*priv));
priv->path = dev->private;
priv->fp = fopen(priv->path, "w+");
dev->private = priv;
}
static void send_to_file_log_device(log_device dev, const char *msg)
{
struct file_log_private *priv;
if(!check_file_log_priv(dev)) {
priv = get_private_info(dev);
if(priv && priv->fp) {
fputs(msg, priv->fp);
fputs("\n", priv->fp);
}
}
}
static void deinit_file_log_device(log_device dev)
{
struct file_log_private *priv;
if(!check_file_log_priv(dev)) {
priv = get_private_info(dev);
if(priv) {
if(priv->fp) {
fclose(priv->fp);