Commit 60bcd7da authored by Dimitris Lampridis's avatar Dimitris Lampridis

hdl: work in progress to update the SVEC TDC+FD reference design

parent 28f4ea27
Subproject commit f30132905e64f360372278fee7f07c60f60b97e6
Subproject commit 59a2c707c28ea99ee15a17eb1f1c903f6644c7b1
......@@ -14,13 +14,19 @@ xilinx::project open $project_file
# Not respected by ISE when passed through hdlmake:
# 1. Pack I/O Registers/Latches into IOBs
# 2. Register Duplication Map
xilinx::project set "Enable Multi-Threading" "2" -process "Map"
xilinx::project set "Enable Multi-Threading" "4" -process "Place & Route"
xilinx::project set "Pack I/O Registers into IOBs" "Yes"
xilinx::project set "Pack I/O Registers/Latches into IOBs" "For Inputs and Outputs"
xilinx::project set "Register Balancing" "Yes"
xilinx::project set "Register Duplication Map" "On"
#xilinx::project set "Placer Extra Effort Map" "Normal"
#xilinx::project set "Extra Effort (Highest PAR level only)" "Normal"
xilinx::project save
xilinx::project close
......@@ -27,6 +27,8 @@
`ifndef __WRTD_DEFINE_INCLUDED
`define __WRTD_DEFINE_INCLUDED
`include "simdrv_defs.svh"
`define WRTD_MAX_CPUS 4
`define WRTD_MAX_DEVS 4
......
# HDLMake 'develop' branch required.
#
# Due to bugs in release v3.0 of hdlmake it is necessary to use the "develop"
# branch of hdlmake, commit db4e1ab.
board = "svec"
sim_tool = "modelsim"
sim_top = "main"
action = "simulation"
target = "xilinx"
board = "svec"
syn_device = "xc6slx150t"
vcom_opt = "-93 -mixedsvvh"
fetchto="../../../dependencies"
include_dirs = [
fetchto + "/mock-turtle/hdl/testbench/include/",
fetchto + "/mock-turtle/hdl/testbench/include/regs/",
"../include",
fetchto + "/general-cores/sim/",
fetchto + "/urv-core/rtl/",
fetchto + "/mock-turtle/hdl/testbench/include/",
]
files = [
"main.sv",
"dut_env.sv",
"synthesis_descriptor.vhd",
]
......
//------------------------------------------------------------------------------
// CERN BE-CO-HT
// White Rabbit Trigger Distribution (WRTD)
// https://ohwr.org/projects/wrtd
//------------------------------------------------------------------------------
//
// unit name: dut_env
//
// description: Wrapper for the Device Under Test (SVEC-based FMC TDC+FD WRTD
// reference design) and its peripherals.
//
//------------------------------------------------------------------------------
// Copyright CERN 2019
//------------------------------------------------------------------------------
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 2.0 (the "License"); you may not use this file except
// in compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-2.0.
// Unless required by applicable law or agreed to in writing, software,
// hardware and materials distributed under this License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions
// and limitations under the License.
//------------------------------------------------------------------------------
`timescale 1ns/1ps
`include "vhd_wishbone_master.svh"
`include "simdrv_defs.svh"
module simple_tdc_driver
(
input clk,
input [3:0] addr,
inout [27:0] data,
input wr,
input rd,
output reg ef1,
output reg ef2,
input tstart,
output intflag
);
typedef struct {
int channel;
time ts;
} acam_fifo_entry;
acam_fifo_entry pulses[$];
logic [27:0] fifos[2][$];
reg [7:0] start = 0;
time start_time;
reg [16:0] start01 = 0;
reg [7:0] start_rep = 0;
const int start_timer = 15 + 1;
reg restart_pulse = 0;
time restart_time;
reg [27:0] rdata;
assign data = rdata;
assign intflag = start[7];
task push_pulse(int channel, time ts);
pulses.push_back('{channel: channel, ts: ts});
endtask
// Convert trigger to ACAM data
always begin
acam_fifo_entry t;
time now;
wait (pulses.size() != 0)
;
t = pulses.pop_front();
now = $time;
if (t.ts <= now)
$display("TDC: pulse in the past (%t now=%t)!", t.ts, now);
else
begin
const int fifo_n = t.channel / 4;
logic [27:0] val;
#(t.ts - now) ;
val[27:26] = t.channel & 2'b11;
val[25:18] = start;
val[17] = 1'b1;
val[16:0] = (t.ts - start_time) / 81ps;
$display("TDC: pulse at %t for channel %0d (start #0x%x, time_data 0x%x, start_time %t)",
t.ts, t.channel, start, val[16:0], start_time);
fifos[t.channel / 4].push_back(val);
end
end
initial begin
rdata = 28'bz;
end
always@(posedge tstart) begin
restart_pulse = 1;
restart_time = $time;
end;
// Internal start retrigger
always@(posedge clk) begin
start_rep++;
if (start_rep == start_timer) begin
start_rep = 0;
if (restart_pulse) begin
start = 1;
restart_pulse = 0;
start01 = ($time - restart_time) / 81ps;
end
else begin
start_time = $time;
start++;
end
end
end
always@(rd) begin
rdata <= 28'bz;
if (rd == 1'b0) begin
if (addr == 8) begin
rdata <= fifos[0].pop_front();
end
else if (addr == 9) begin
rdata <= fifos[1].pop_front();
end
else if (addr == 10) begin
rdata <= start01;
end
else begin
$display("invalid ACAM read 0x%x", addr);
end
end
end
assign ef1 = fifos[0].size() == 0;
assign ef2 = fifos[1].size() == 0;
always@(negedge wr) begin
// Unused in simulation mode.
$display("invalid ACAM write 0x%x <- 0x%08x", addr, data);
end
endmodule // simple_tdc_driver
module simple_fdelay_mon
(
input [3:0] len,
input [9:0] val,
input [3:0] pulse
);
typedef struct {
int channel;
time ts;
} fifo_entry;
fifo_entry pulses[$];
task push_pulse(int channel, time ts);
pulses.push_back('{channel: channel, ts: ts});
endtask
initial begin
reg [3:0] prev;
time now;
// Do nothing before 100us, hw is not initialized.
# 100us ;
prev = 0;
while (pulses.size() != 0) begin
@pulse ;
now = $time;
$display("[FDEL] <%t> Pulse: len=%x, val=%x, out=%x", now, len, val, pulse);
for(int i = 0; i < 4; i++) begin
if (prev[i] == 1'b0 && pulse[i] == 1'b1) begin
automatic fifo_entry e = pulses.pop_front();
automatic time diff;
$display("[FDEL] pulse on channel %0d", i);
if (e.channel != i) begin
$display("FAIL: [FDEL] Bad channel (expected %0d)", e.channel);
$finish(1);
end
diff = now - e.ts;
if (diff > 2us && diff < -2us) begin
$display("FAIL: [FDEL] Bad timestamp: pulse at %t, expected at %t", now, e.ts);
$finish(1);
end
end
end
prev = pulse;
end
$display("SUCCESS: done");
$finish(0);
end
endmodule // simple_fdelay_mon
module dut_env
(
IVHDWishboneMaster host,
output sfp_txp_o, sfp_txn_o,
input sfp_rxp_i, sfp_rxn_i
);
reg clk_125m_pll = 0;
reg clk_125m_gtp = 0;
reg clk_20m_vcxo = 0;
reg clk_62m5_sys = 0;
reg clk_31m5_acam = 0;
always #4ns clk_125m_pll <= ~clk_125m_pll;
always #4ns clk_125m_gtp <= ~clk_125m_gtp;
always #8ns clk_62m5_sys <= ~clk_62m5_sys;
always #16ns clk_31m5_acam <= ~clk_31m5_acam;
always #25ns clk_20m_vcxo <= ~clk_20m_vcxo;
wire tdc_ef1, tdc_ef2;
wire tdc_rd_n, tdc_wr_n;
wire tdc_int, tdc_start;
wire [3:0] tdc_addr;
wire [27:0] tdc_data;
wire [3:0] fdl_len, fdl_pulse;
wire [9:0] fdl_val;
wire sfp_scl, sfp_sda, sfp_sda_en;
//---------------------------------------------------------------------------
// The DUT
//---------------------------------------------------------------------------
wrtd_ref_svec_tdc_fd #
(
.g_SIMULATION (1),
.g_SIM_BYPASS_VME (1),
.g_WRPC_INITF ("../../../dependencies/wr-cores/bin/wrpc/wrc_phy8_sim.bram"),
.g_MT_CPU0_INITF ("../../../software/firmware/tdc/wrtd-rt-tdc.bram"),
.g_MT_CPU1_INITF ("../../../software/firmware/fd/wrtd-rt-fd.bram")
)
DUT
(
.rst_n_i (1'b1),
.clk_125m_pllref_p_i (clk_125m_pll),
.clk_125m_pllref_n_i (~clk_125m_pll),
.clk_125m_gtp_p_i (clk_125m_gtp),
.clk_125m_gtp_n_i (~clk_125m_gtp),
.clk_20m_vcxo_i (clk_20m_vcxo),
.sim_wb_i (host.out),
.sim_wb_o (host.in),
.carrier_onewire_b (),
.sfp_txp_o (sfp_txp_o),
.sfp_txn_o (sfp_txn_o),
.sfp_rxp_i (sfp_rxp_i),
.sfp_rxn_i (sfp_rxn_i),
.sfp_mod_def0_i (1'b0),
.sfp_mod_def1_b (sfp_scl),
.sfp_mod_def2_b (sfp_sda),
.sfp_rate_select_o (),
.sfp_tx_fault_i (1'b0),
.sfp_tx_disable_o (),
.sfp_los_i (1'b0),
.spi_sclk_o (),
.spi_ncs_o (),
.spi_mosi_o (),
.spi_miso_i (1'b0),
.uart_rxd_i (1'b0),
.uart_txd_o (),
.fmc0_tdc_pll_status_i (1'b1),
.fmc0_tdc_125m_clk_p_i (clk_125m_pll),
.fmc0_tdc_125m_clk_n_i (~clk_125m_pll),
.fmc0_tdc_acam_refclk_p_i (clk_31m5_acam),
.fmc0_tdc_acam_refclk_n_i (~clk_31m5_acam),
.fmc0_tdc_start_from_fpga_o (tdc_start),
.fmc0_tdc_ef1_i (tdc_ef1),
.fmc0_tdc_ef2_i (tdc_ef2),
.fmc0_tdc_err_flag_i (1'b0),
.fmc0_tdc_int_flag_i (tdc_int),
.fmc0_tdc_data_bus_io (tdc_data),
.fmc0_tdc_address_o (tdc_addr),
.fmc0_tdc_rd_n_o (tdc_rd_n),
.fmc0_tdc_wr_n_o (tdc_wr_n),
.fmc1_fd_clk_ref_p_i (clk_125m_pll),
.fmc1_fd_clk_ref_n_i (~clk_125m_pll),
.fmc1_fd_delay_len_o (fdl_len),
.fmc1_fd_delay_val_o (fdl_val),
.fmc1_fd_delay_pulse_o (fdl_pulse)
);
//---------------------------------------------------------------------------
// TDC driver
//---------------------------------------------------------------------------
simple_tdc_driver
TDC
(
.clk(clk_31m5_acam),
.addr(tdc_addr),
.data(tdc_data),
.wr(tdc_wr_n),
.rd(tdc_rd_n),
.ef1(tdc_ef1),
.ef2(tdc_ef2),
.tstart(tdc_start),
.intflag(tdc_int)
);
//---------------------------------------------------------------------------
// Fine Delay monitor
//---------------------------------------------------------------------------
simple_fdelay_mon
FDL
(
.len (fdl_len),
.val (fdl_val),
.pulse (fdl_pulse)
);
//---------------------------------------------------------------------------
// SFP I2C Adapter
//---------------------------------------------------------------------------
gc_sfp_i2c_adapter
SFP_I2C
(
.clk_i (clk_125m_pll),
.rst_n_i (1'b1),
.scl_i (sfp_scl),
.sda_i (sfp_sda),
.sda_en_o (sfp_sda_en),
.sfp_det_valid_i (1'b1),
.sfp_data_i (128'h0123456789ABCDEF0123456789ABCDEF)
);
assign sfp_sda = (sfp_sda_en) ? 1'b0:1'bz;
//---------------------------------------------------------------------------
// Initial processes
//---------------------------------------------------------------------------
task push_pulse(int channel, time ts);
TDC.push_pulse(channel, ts);
FDL.push_pulse(channel, ts + 100us); // Delay time (from fd firmware)
endtask
initial begin
// No pulse before: WR (300us) + TDC setup.
automatic time start = 480us;
push_pulse(0, start + 10us);
push_pulse(1, start + 30us);
push_pulse(2, start + 50us);
#(start + 200us) ;
// Should have been finished by the FD monitor.
$fatal(1, "FAILED");
end
initial begin
// Skip WR SoftPLL lock
force DUT.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.U_SOFTPLL.U_Wrapped_Softpll.out_locked_o = 3'b111;
// Silence Xilinx unisim DSP48A1 warnings about invalid OPMODE
force DUT.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.LM32_CORE.gen_profile_medium_icache.U_Wrapped_LM32.cpu.
multiplier.D1.OPMODE_dly = 0;
force DUT.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.LM32_CORE.gen_profile_medium_icache.U_Wrapped_LM32.cpu.
multiplier.D2.OPMODE_dly = 0;
force DUT.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.LM32_CORE.gen_profile_medium_icache.U_Wrapped_LM32.cpu.
multiplier.D3.OPMODE_dly = 0;
end // initial begin
endmodule // dut_env
//------------------------------------------------------------------------------
// CERN BE-CO-HT
// LHC Instability Trigger Distribution (LIST)
// https://ohwr.org/projects/list
// White Rabbit Trigger Distribution (WRTD)
// https://ohwr.org/projects/wrtd
//------------------------------------------------------------------------------
//
// unit name: main
//
// description: A SystemVerilog testbench to exercise all the main features of
// LIST
// description: Testbench for the SPEC150T-based FMC ADC WRTD reference design.
//
//------------------------------------------------------------------------------
// Copyright CERN 2018
// Copyright CERN 2018-2019
//------------------------------------------------------------------------------
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 2.0 (the "License"); you may not use this file except
......@@ -23,418 +22,55 @@
// and limitations under the License.
//------------------------------------------------------------------------------
`include "list_driver.svh"
`include "vhd_wishbone_master.svh"
`timescale 1ns/10fs
module simple_tdc_driver
(
input clk,
input [3:0] addr,
inout [27:0] data,
input wr,
input rd,
output reg ef1,
output reg ef2,
input tstart,
output intflag
);
typedef struct {
int channel;
time ts;
} acam_fifo_entry;
acam_fifo_entry pulses[$];
logic [27:0] fifos[2][$];
reg [7:0] start = 0;
time start_time;
reg [16:0] start01 = 0;
reg [7:0] start_rep = 0;
const int start_timer = 15 + 1;
reg restart_pulse = 0;
time restart_time;
reg [27:0] rdata;
assign data = rdata;
assign intflag = start[7];
task push_pulse(int channel, time ts);
pulses.push_back('{channel: channel, ts: ts});
endtask
// Convert trigger to ACAM data
always begin
acam_fifo_entry t;
time now;
wait (pulses.size() != 0)
;
t = pulses.pop_front();
now = $time;
if (t.ts <= now)
$display("TDC: pulse in the past (%t now=%t)!", t.ts, now);
else
begin
const int fifo_n = t.channel / 4;
logic [27:0] val;
#(t.ts - now) ;
val[27:26] = t.channel & 2'b11;
val[25:18] = start;
val[17] = 1'b1;
val[16:0] = (t.ts - start_time) / 81ps;
$display("TDC: pulse at %t for channel %d (start #0x%x, time_data 0x%x, start_time %t)",
t.ts, t.channel, start, val[16:0], start_time);
fifos[t.channel / 4].push_back(val);
end
end
initial begin
rdata = 28'bz;
end
always@(posedge tstart) begin
restart_pulse = 1;
restart_time = $time;
end;
// Internal start retrigger
always@(posedge clk) begin
start_rep++;
if (start_rep == start_timer) begin
start_rep = 0;
if (restart_pulse) begin
start = 1;
restart_pulse = 0;
start01 = ($time - restart_time) / 81ps;
end
else begin
start_time = $time;
start++;
end
end
end
always@(rd) begin
rdata <= 28'bz;
if (rd == 1'b0) begin
if (addr == 8) begin
rdata <= fifos[0].pop_front();
end
else if (addr == 9) begin
rdata <= fifos[1].pop_front();
end
else if (addr == 10) begin
rdata <= start01;
end
else begin
$display("invalid ACAM read 0x%x", addr);
end
end
end
assign ef1 = fifos[0].size() == 0;
assign ef2 = fifos[1].size() == 0;
always@(negedge wr) begin
// Unused in simulation mode.
$display("invalid ACAM write 0x%x <- 0x%08x", addr, data);
end
endmodule // simple_tdc_driver
module simple_fdelay_mon
(
input [3:0] len,
input [9:0] val,
input [3:0] pulse
);
typedef struct {
int channel;
time ts;
} fifo_entry;
fifo_entry pulses[$];
task push_pulse(int channel, time ts);
pulses.push_back('{channel: channel, ts: ts});
endtask
initial begin
reg [3:0] prev;
time now;
// Do nothing before 100us, hw is not initialized.
# 100us ;
prev = 0;
`timescale 1ns/1ps
while (pulses.size() != 0) begin
@pulse ;
now = $time;
$display("[FDEL] <%t> Pulse: len=%x, val=%x, out=%x", now, len, val, pulse);
for(int i = 0; i < 4; i++) begin
if (prev[i] == 1'b0 && pulse[i] == 1'b1) begin
automatic fifo_entry e = pulses.pop_front();
automatic time diff;
$display("[FDEL] pulse on channel %d", i);
if (e.channel != i) begin
$display("FAIL: [FDEL] Bad channel (expected %d)", e.channel);
$finish(1);
end
diff = now - e.ts;
if (diff > 2us && diff < -2us) begin
$display("FAIL: [FDEL] Bad timestamp: pulse at %t, expected at %t", now, e.ts);
$finish(1);
end
end
end
prev = pulse;
end
$display("SUCCESS: done");
$finish(0);
end
endmodule // simple_fdelay_mon
`include "wrtd_driver.svh"
`include "vhd_wishbone_master.svh"
module main;
reg rst_n = 0;
reg clk_125m_pllref = 0;
reg clk_20m_vcxo = 0;
reg clk_ext = 0;
reg clk_acam = 0;
wire a2btxp, a2btxn, b2atxp, b2atxn;
wire tdc_ef1, tdc_ef2;
wire tdc_rd_n, tdc_wr_n;
wire tdc_int, tdc_start;
wire [3:0] tdc_addr;
wire [27:0] tdc_data;
wire [3:0] fdl_len, fdl_pulse;
wire [9:0] fdl_val;
always #50ns clk_ext <= ~clk_ext; // 10Mhz
always #4ns clk_125m_pllref <= ~clk_125m_pllref; // 125Mhz
always #16ns clk_acam <= ~clk_acam; // 31.5Mhz
always #25ns clk_20m_vcxo <= ~clk_20m_vcxo; // 20Mhz
initial begin
repeat(20) @(posedge clk_20m_vcxo);
rst_n = 1;
end
const uint64_t mt_base = 'h2_0000;
//
// LIST transmitter (TDC)
//
simple_tdc_driver
TDC
(
.clk(clk_acam),
.addr(tdc_addr),
.data(tdc_data),
.wr(tdc_wr_n),
.rd(tdc_rd_n),
.ef1(tdc_ef1),
.ef2(tdc_ef2),
.tstart(tdc_start),
.intflag(tdc_int)
);
wrtd_ref_svec_tdc_fd #
(
.g_simulation (1),
.g_sim_bypass_vme (1),
.g_wr_dpram_initf("../../../dependencies/wr-cores/bin/wrpc/wrc_phy8_sim.bram"),
.g_mt_cpu0_initf("../../../software/firmware/tdc/wrtd-rt-tdc.bram"),
.g_mt_cpu1_initf("none")
)
DUT_A
(
.rst_n_i (rst_n),
.clk_125m_pllref_p_i (clk_125m_pllref),
.clk_125m_pllref_n_i (~clk_125m_pllref),
.clk_125m_gtp_p_i (clk_125m_pllref),
.clk_125m_gtp_n_i (~clk_125m_pllref),
.clk_20m_vcxo_i (clk_20m_vcxo),
.sim_wb_i (HostA.out),
.sim_wb_o (HostA.in),
.sfp_txp_o (a2btxp),
.sfp_txn_o (a2btxn),
.sfp_rxp_i (b2atxp),
.sfp_rxn_i (b2atxn),
.fmc0_tdc_pll_status_i (1'b1),
.fmc0_tdc_125m_clk_p_i (clk_125m_pllref),
.fmc0_tdc_125m_clk_n_i (~clk_125m_pllref),
.fmc0_tdc_acam_refclk_p_i (clk_acam),
.fmc0_tdc_acam_refclk_n_i (~clk_acam),
.fmc0_tdc_start_from_fpga_o (tdc_start),
.fmc0_tdc_ef1_i (tdc_ef1),
.fmc0_tdc_ef2_i (tdc_ef2),
.fmc0_tdc_err_flag_i (1'b0),
.fmc0_tdc_int_flag_i (tdc_int),
.fmc0_tdc_data_bus_io (tdc_data),
.fmc0_tdc_address_o (tdc_addr),
.fmc0_tdc_rd_n_o (tdc_rd_n),
.fmc0_tdc_wr_n_o (tdc_wr_n)
);
IVHDWishboneMaster HostA
(
.clk_i (DUT_A.clk_sys_62m5),
.rst_n_i (DUT_A.rst_sys_62m5_n));
IMockTurtleIRQ IrqMonitorA (`MT_ATTACH_IRQ(DUT_A.cmp_mock_turtle));
wire sfp_txp, sfp_txn, sfp_rxp, sfp_rxn;
ListDriver drvA;
IVHDWishboneMaster host (DUT.DUT.clk_sys_62m5, DUT.DUT.rst_sys_62m5_n);
initial begin
@(posedge DUT_A.rst_sys_62m5_n);
@(posedge DUT_A.clk_sys_62m5);
drvA = new (HostA.get_accessor(), mt_base, IrqMonitorA, "DUT:A");
drvA.init();
forever begin
drvA.update ();
#1us;
end
dut_env DUT (host, sfp_txp, sfp_txn, sfp_rxp, sfp_rxn);
end // initial begin DUTA
IMockTurtleIRQ MtIrqMonitor (`MT_ATTACH_IRQ(DUT.DUT.cmp_mock_turtle));
//
// LIST receiver (Fine Delay)
//
assign sfp_rxp = sfp_txp;
assign sfp_rxn = sfp_txn;
simple_fdelay_mon
FDL
(
.len (fdl_len),
.val (fdl_val),
.pulse (fdl_pulse)
);
wrtd_ref_svec_tdc_fd #
(
.g_simulation (1),
.g_sim_bypass_vme (1),
.g_wr_dpram_initf("../../../dependencies/wr-cores/bin/wrpc/wrc_phy8_sim.bram"),
.g_mt_cpu0_initf("none"),
.g_mt_cpu1_initf("../../../software/firmware/fd/wrtd-rt-fd.bram")
)
DUT_B
(
.rst_n_i (rst_n),
.clk_125m_pllref_p_i (clk_125m_pllref),
.clk_125m_pllref_n_i (~clk_125m_pllref),
.clk_125m_gtp_p_i (clk_125m_pllref),
.clk_125m_gtp_n_i (~clk_125m_pllref),
.clk_20m_vcxo_i (clk_20m_vcxo),
.sim_wb_i (HostB.out),
.sim_wb_o (HostB.in),
.sfp_txp_o (b2atxp),
.sfp_txn_o (b2atxn),
.sfp_rxp_i (a2btxp),
.sfp_rxn_i (a2btxn),
.fmc1_fd_clk_ref_p_i (clk_125m_pllref),
.fmc1_fd_clk_ref_n_i (~clk_125m_pllref),
.fmc1_fd_delay_len_o (fdl_len),
.fmc1_fd_delay_val_o (fdl_val),
.fmc1_fd_delay_pulse_o (fdl_pulse)
);
CBusAccessor acc;
IVHDWishboneMaster HostB
(
.clk_i (DUT_B.clk_sys_62m5),
.rst_n_i (DUT_B.rst_sys_62m5_n));
WrtdDrv dev;
IMockTurtleIRQ IrqMonitorB (`MT_ATTACH_IRQ(DUT_B.cmp_mock_turtle));
ListDriver drvB;
const uint64_t MT_BASE = 'h0002_0000;
initial begin
@(posedge DUT_B.rst_sys_62m5_n);
@(posedge DUT_B.clk_sys_62m5);
$timeformat (-6, 3, "us", 10);
drvB = new (HostB.get_accessor(), mt_base, IrqMonitorB, "DUT:B");
@(posedge DUT.DUT.rst_sys_62m5_n);
@(posedge DUT.DUT.clk_sys_62m5);
drvB.init();
acc = host.get_accessor();
acc.set_default_xfer_size(4);
dev = new (acc, MT_BASE, MtIrqMonitor, "DUT");
dev.init();
dev.add_rule ( "rule0" );
dev.set_rule ( "rule0", "NET0", "FD", 100000 );
dev.enable_rule ( "rule0" );
dev.add_rule ( "rule1" );
dev.set_rule ( "rule1", "TDC", "NET0", 0 );
dev.enable_rule ( "rule1" );
forever begin
drvB.update ();
if ( ( dev != null ) && ( dev.ready ) )
dev.update ();
#1us;
end
end // initial begin DUTB
initial begin // others
$timeformat (-6, 3, "us", 10);
// Skip WR SoftPLL lock
force DUT_A.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.U_SOFTPLL.U_Wrapped_Softpll.out_locked_o = 3'b111;
force DUT_B.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.U_SOFTPLL.U_Wrapped_Softpll.out_locked_o = 3'b111;
// Silence Xilinx unisim DSP48A1 warnings about invalid OPMODE
force DUT_A.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.LM32_CORE.gen_profile_medium_icache.U_Wrapped_LM32.cpu.
multiplier.D1.OPMODE_dly = 0;
force DUT_A.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.LM32_CORE.gen_profile_medium_icache.U_Wrapped_LM32.cpu.
multiplier.D2.OPMODE_dly = 0;
force DUT_A.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.LM32_CORE.gen_profile_medium_icache.U_Wrapped_LM32.cpu.
multiplier.D3.OPMODE_dly = 0;
force DUT_B.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.LM32_CORE.gen_profile_medium_icache.U_Wrapped_LM32.cpu.
multiplier.D1.OPMODE_dly = 0;
force DUT_B.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.LM32_CORE.gen_profile_medium_icache.U_Wrapped_LM32.cpu.
multiplier.D2.OPMODE_dly = 0;
force DUT_B.cmp_xwrc_board_svec.cmp_board_common.cmp_xwr_core.
WRPC.LM32_CORE.gen_profile_medium_icache.U_Wrapped_LM32.cpu.
multiplier.D3.OPMODE_dly = 0;
end // initial begin
task push_pulse(int channel, time ts);
TDC.push_pulse(channel, ts);
FDL.push_pulse(channel, ts + 100us); // Delay time (from fd firmware)
endtask
initial begin
// No pulse before: WR (300us) + TDC setup.
automatic time start = 480us;
push_pulse(0, start + 10us);
push_pulse(1, start + 30us);
push_pulse(2, start + 50us);
#(start + 200us) ;
// Should have been finished by the FD monitor.
$fatal(1, "FAILED");
end
endmodule // main
vsim -quiet -L unisim work.main -novopt -suppress 8683,8684,8822
vsim -quiet -t 10fs -L unisim work.main
set StdArithNoWarnings 1
set NumericStdNoWarnings 1
radix -hexadecimal
run 1000us
log -r /*
run -all
# Modelsim run script for continuous integration
# execute: vsim -c -do "run_ci.do"
vsim -quiet -L unisim work.main -suppress 8683,8684,8822
vsim -quiet -t 10fs -L unisim work.main
set StdArithNoWarnings 1
set NumericStdNoWarnings 1
run 1000us
run -all
exit
......@@ -236,7 +236,7 @@ architecture arch of wrtd_ref_spec150t_adc is
constant c_WB_SLAVE_SPEC_CSR : integer := 0;
constant c_WB_SLAVE_VIC : integer := 1;
constant c_WB_SLAVE_BASE : integer := 2;
constant c_WB_SLAVE_DMA : integer := c_WB_SLAVE_BASE + 0;
constant c_WB_SLAVE_DMA : integer := c_WB_SLAVE_BASE + 0;
constant c_WB_SLAVE_DMA_EIC : integer := c_WB_SLAVE_BASE + 1;
constant c_WB_SLAVE_FMC_ADC : integer := c_WB_SLAVE_BASE + 2;
......@@ -310,14 +310,13 @@ architecture arch of wrtd_ref_spec150t_adc is
constant c_WB_LAYOUT : t_sdb_record_array(c_NUM_WB_SLAVES + 1 downto 0) := (
c_WB_SLAVE_SPEC_CSR => f_sdb_embed_device(c_WB_SPEC_CSR_SDB, x"00001000"),
c_WB_SLAVE_VIC => f_sdb_embed_device(c_XWB_VIC_SDB, x"00001200"),
c_WB_SLAVE_DMA => f_sdb_embed_device(c_WB_DMA_CTRL_SDB, x"00002000"),
c_WB_SLAVE_DMA_EIC => f_sdb_embed_device(c_WB_DMA_EIC_SDB, x"00002200"),
c_WB_SLAVE_FMC_ADC => f_sdb_embed_bridge(c_FMC_BRIDGE_SDB, x"00004000"),
c_WB_SLAVE_MT => f_sdb_embed_device(c_MOCK_TURTLE_SDB, x"00020000"),
c_WB_SLAVE_WRC => f_sdb_embed_bridge(c_wrc_bridge_sdb, x"00040000"),
c_WB_DESC_SYN => f_sdb_embed_synthesis(c_SDB_SYNTHESIS_INFO),
c_WB_DESC_URL => f_sdb_embed_repo_url(c_SDB_REPO_URL));
c_WB_SLAVE_DMA => f_sdb_embed_device(c_WB_DMA_CTRL_SDB, x"00002000"),
c_WB_SLAVE_DMA_EIC => f_sdb_embed_device(c_WB_DMA_EIC_SDB, x"00002200"),
c_WB_SLAVE_FMC_ADC => f_sdb_embed_bridge(c_FMC_BRIDGE_SDB, x"00004000"),
c_WB_SLAVE_MT => f_sdb_embed_device(c_MOCK_TURTLE_SDB, x"00020000"),
c_WB_SLAVE_WRC => f_sdb_embed_bridge(c_wrc_bridge_sdb, x"00040000"),
c_WB_DESC_SYN => f_sdb_embed_synthesis(c_SDB_SYNTHESIS_INFO),
c_WB_DESC_URL => f_sdb_embed_repo_url(c_SDB_REPO_URL));
-- not really used, will be reprogrammed by software
constant c_VIC_VECTOR_TABLE : t_wishbone_address_array(0 to 5) := (
......@@ -457,8 +456,8 @@ architecture arch of wrtd_ref_spec150t_adc is
signal eth_rx_in : t_wrf_sink_in;
-- MT Dedicated WB interfaces to FMCs
signal fmc_dp_wb_out : t_wishbone_master_out_array(0 to 1 - 1);
signal fmc_dp_wb_in : t_wishbone_master_in_array(0 to 1 - 1);
signal fmc_dp_wb_out : t_wishbone_master_out;
signal fmc_dp_wb_in : t_wishbone_master_in;
-- WRPC TM interface and aux clocks
signal tm_link_up : std_logic;
......@@ -708,8 +707,8 @@ begin -- architecture arch
rst_n_i => rst_sys_62m5_n,
sp_master_o => open,
sp_master_i => c_DUMMY_WB_MASTER_IN,
dp_master_o => fmc_dp_wb_out,
dp_master_i => fmc_dp_wb_in,
dp_master_o(0) => fmc_dp_wb_out,
dp_master_i(0) => fmc_dp_wb_in,
rmq_endpoint_o => rmq_endpoint_out,
rmq_endpoint_i => rmq_endpoint_in,
host_slave_i => cnx_slave_in(c_WB_SLAVE_MT),
......@@ -1120,8 +1119,8 @@ begin -- architecture arch
port map (
clk_sys_i => clk_sys_62m5,
rst_n_i => rst_sys_62m5_n,
slave_i(0) => fmc_dp_wb_out(0),
slave_o(0) => fmc_dp_wb_in(0),
slave_i(0) => fmc_dp_wb_out,
slave_o(0) => fmc_dp_wb_in,
master_i(1) => wb_adc0_trigout_slave_out,
master_i(0) => wb_adc0_trigin_slave_out,
master_o(1) => wb_adc0_trigout_slave_in,
......
......@@ -52,9 +52,9 @@ use unisim.vcomponents.all;
entity wrtd_ref_svec_tdc_fd is
generic (
g_WR_DPRAM_INITF : string := "../../../dependencies/wr-cores/bin/wrpc/wrc_phy8.bram";
g_MT_CPU0_INITF : string := "../../../software/firmware/tdc/wrtd-rt-tdc.bram";
g_MT_CPU1_INITF : string := "../../../software/firmware/fd/wrtd-rt-fd.bram";
g_WRPC_INITF : string := "../../../dependencies/wr-cores/bin/wrpc/wrc_phy8.bram";
g_MT_CPU0_INITF : string := "../../../software/firmware/tdc/wrtd-rt-tdc.bram";
g_MT_CPU1_INITF : string := "../../../software/firmware/fd/wrtd-rt-fd.bram";
-- Simulation-mode enable parameter. Set by default (synthesis) to 0, and
-- changed to non-zero in the instantiation of the top level DUT in the
-- testbench. Its purpose is to reduce some internal counters/timeouts
......@@ -151,7 +151,7 @@ entity wrtd_ref_svec_tdc_fd is
-- Onewire interface
---------------------------------------------------------------------------
onewire_b : inout std_logic;
carrier_onewire_b : inout std_logic;
---------------------------------------------------------------------------
-- UART
......@@ -338,27 +338,27 @@ architecture arch of wrtd_ref_svec_tdc_fd is
constant c_WB_SLAVE_FDL : integer := 2;
constant c_WB_SLAVE_MT : integer := 3;
constant c_WB_SLAVE_WRC : integer := 4;
constant c_WB_DESC_SYN : integer := 5;
constant c_WB_DESC_URL : integer := 6;
constant c_WB_DESC_SYN : integer := c_NUM_WB_SLAVES;
constant c_WB_DESC_URL : integer := c_NUM_WB_SLAVES + 1;
-- sdb header address on primary crossbar
constant c_SDB_ADDRESS : t_wishbone_address := x"00000000";
-- f_xwb_bridge_manual_sdb(size, sdb_addr)
-- Note: sdb_addr is the sdb records address relative to the bridge base address
constant c_wrc_bridge_sdb : t_sdb_bridge :=
constant c_WRC_BRIDGE_SDB : t_sdb_bridge :=
f_xwb_bridge_manual_sdb(x"0003ffff", x"00030000");
constant c_tdc_bridge_sdb : t_sdb_bridge :=
constant c_TDC_BRIDGE_SDB : t_sdb_bridge :=
f_xwb_bridge_manual_sdb(x"00007FFF", x"00000000");
-- Primary wishbone crossbar layout
constant c_WB_LAYOUT : t_sdb_record_array(c_NUM_WB_SLAVES + 1 downto 0) := (
c_WB_SLAVE_VIC => f_sdb_embed_device(c_XWB_VIC_SDB, x"00002000"),
c_WB_SLAVE_TDC => f_sdb_embed_bridge(c_tdc_bridge_sdb, x"00010000"),
c_WB_SLAVE_FDL => f_sdb_embed_device(c_FD_SDB_DEVICE, x"00018000"),
c_WB_SLAVE_VIC => f_sdb_embed_device(c_XWB_VIC_SDB, x"00002000"),
c_WB_SLAVE_TDC => f_sdb_embed_bridge(c_TDC_BRIDGE_SDB, x"00010000"),
c_WB_SLAVE_FDL => f_sdb_embed_device(c_FD_SDB_DEVICE, x"00018000"),
c_WB_SLAVE_MT => f_sdb_embed_device(c_MOCK_TURTLE_SDB, x"00020000"),
c_WB_SLAVE_WRC => f_sdb_embed_bridge(c_wrc_bridge_sdb, x"00040000"),
c_WB_SLAVE_WRC => f_sdb_embed_bridge(c_WRC_BRIDGE_SDB, x"00040000"),
c_WB_DESC_SYN => f_sdb_embed_synthesis(c_SDB_SYNTHESIS_INFO),
c_WB_DESC_URL => f_sdb_embed_repo_url(c_SDB_REPO_URL));
......@@ -376,7 +376,7 @@ architecture arch of wrtd_ref_svec_tdc_fd is
constant c_FMC_MUX_MASK : t_wishbone_address_array(0 downto 0) :=
(0 => x"10000000");
constant c_mt_config : t_mt_config :=
constant c_MT_CONFIG : t_mt_config :=
(
app_id => x"115790de",
cpu_count => 2,
......@@ -384,22 +384,14 @@ architecture arch of wrtd_ref_svec_tdc_fd is
0 | 1 => (
memsize => 8192,
hmq_config => (
slot_count => 2,
slot_count => 1,
slot_config => (
0 => (
-- Control
entries_bits => 3,
entries_bits => 4,
width_bits => 7,
header_bits => 2,
endpoint_id => x"0000_0000",
enable_config_space => FALSE),
1 => (
-- Log
entries_bits => 7,
width_bits => 4,
header_bits => 2,
endpoint_id => x"0000_0000",
enable_config_space => FALSE),
others => c_DUMMY_MT_MQUEUE_SLOT)),
rmq_config => (
slot_count => 1,
......@@ -413,7 +405,7 @@ architecture arch of wrtd_ref_svec_tdc_fd is
others => c_DUMMY_MT_MQUEUE_SLOT))),
others => (
0, c_MT_DEFAULT_MQUEUE_CONFIG, c_MT_DEFAULT_MQUEUE_CONFIG)),
shared_mem_size => 1024
shared_mem_size => 256
);
-----------------------------------------------------------------------------
......@@ -544,7 +536,7 @@ architecture arch of wrtd_ref_svec_tdc_fd is
signal fmc0_scl_out : std_logic;
signal fmc0_sda_out : std_logic;
attribute iob : string;
attribute iob : string;
attribute iob of pps : signal is "FORCE";
begin -- architecture arch
......@@ -632,7 +624,6 @@ begin -- architecture arch
vme_addr_dir_o <= vme_addr_dir_int;
vme_data_dir_o <= vme_data_dir_int;
end generate gen_with_vme64_core;
gen_without_vme64_core : if g_SIM_BYPASS_VME generate
......@@ -752,9 +743,11 @@ begin -- architecture arch
cmp_xwrc_board_svec : xwrc_board_svec
generic map (
g_simulation => g_simulation,
g_dpram_initf => g_WR_DPRAM_INITF,
g_aux_clks => 2)
g_SIMULATION => g_SIMULATION,
g_VERBOSE => FALSE,
g_WITH_EXTERNAL_CLOCK_INPUT => TRUE,
g_DPRAM_INITF => g_WRPC_INITF,
g_AUX_CLKS => 2)
port map (
clk_20m_vcxo_i => clk_20m_vcxo_i,
clk_125m_pllref_p_i => clk_125m_pllref_p_i,
......@@ -832,8 +825,8 @@ begin -- architecture arch
sfp_sda_in <= sfp_mod_def2_b;
-- tri-state onewire access
onewire_b <= '0' when (onewire_oe = '1') else 'Z';
onewire_data <= onewire_b;
carrier_onewire_b <= '0' when (onewire_oe = '1') else 'Z';
onewire_data <= carrier_onewire_b;
-----------------------------------------------------------------------------
-- FMC TDC (SVEC slot #1)
......@@ -841,8 +834,8 @@ begin -- architecture arch
U_TDC_Core : fmc_tdc_wrapper
generic map (
g_simulation => f_int2bool(g_simulation),
g_with_direct_readout => TRUE)
g_SIMULATION => f_int2bool(g_SIMULATION),
g_WITH_DIRECT_READOUT => TRUE)
port map (
clk_sys_i => clk_sys_62m5,
rst_sys_n_i => rst_sys_62m5_n,
......@@ -939,10 +932,10 @@ begin -- architecture arch
U_FineDelay_Core : fine_delay_core
generic map (
g_with_wr_core => TRUE,
g_simulation => f_int2bool(g_simulation),
g_interface_mode => PIPELINED,
g_address_granularity => BYTE)
g_WITH_WR_CORE => TRUE,
g_SIMULATION => f_int2bool(g_SIMULATION),
g_INTERFACE_MODE => PIPELINED,
g_ADDRESS_GRANULARITY => BYTE)
port map (
clk_ref_0_i => dcm1_clk_ref_0,
clk_ref_180_i => dcm1_clk_ref_180,
......@@ -1044,10 +1037,10 @@ begin -- architecture arch
cmp_led_controller : gc_bicolor_led_ctrl
generic map(
g_nb_column => 4,
g_nb_line => 2,
g_clk_freq => 62500000, -- in Hz
g_refresh_rate => 250 -- in Hz
g_NB_COLUMN => 4,
g_NB_LINE => 2,
g_CLK_FREQ => 62500000, -- in Hz
g_REFRESH_RATE => 250 -- in Hz
)
port map(
rst_n_i => rst_sys_62m5_n,
......@@ -1062,21 +1055,21 @@ begin -- architecture arch
line_oen_o => fp_led_line_oen_o);
-- LED 1
svec_led(1 downto 0) <= c_led_green when wr_led_link = '1' else c_led_red;
svec_led(1 downto 0) <= c_LED_GREEN when wr_led_link = '1' else c_LED_RED;
-- LED 2
svec_led(3 downto 2) <= c_led_green when tm_clk_aux_locked(0) = '1' else c_led_red;
svec_led(3 downto 2) <= c_LED_GREEN when tm_clk_aux_locked(0) = '1' else c_LED_RED;
-- LED 3
svec_led(5 downto 4) <= c_led_green when tm_time_valid = '1' else c_led_red;
svec_led(5 downto 4) <= c_LED_GREEN when tm_time_valid = '1' else c_LED_RED;
-- LED 4
svec_led(7 downto 6) <= c_led_red_green when vme_access_led = '1' else c_led_off;
svec_led(7 downto 6) <= c_LED_RED_GREEN when vme_access_led = '1' else c_LED_OFF;
-- LED 5
svec_led(9 downto 8) <= c_led_red_green when wr_led_act = '1' else c_led_off;
svec_led(9 downto 8) <= c_LED_RED_GREEN when wr_led_act = '1' else c_LED_OFF;
-- LED 6
svec_led(11 downto 10) <= c_led_green when tm_clk_aux_locked(1) = '1' else c_led_red;
svec_led(11 downto 10) <= c_LED_GREEN when tm_clk_aux_locked(1) = '1' else c_LED_RED;
-- LED 7
svec_led(13 downto 12) <= c_led_off;
svec_led(13 downto 12) <= c_LED_OFF;
-- LED 8
svec_led(15 downto 14) <= c_led_green when pps_led = '1' else c_led_off;
svec_led(15 downto 14) <= c_LED_GREEN when pps_led = '1' else c_LED_OFF;
-- Div by 2 reference clock to LEMO connector
process(clk_ref_125m)
......
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