Commit bf9b1ed2 authored by Tristan Gingold's avatar Tristan Gingold

testbench: improve TDC emulation.

parent 55ff58bb
......@@ -30,12 +30,15 @@
module simple_tdc_driver
(
input [3:0] addr,
output reg [27:0] data,
input wr,
input rd,
output reg ef1,
output reg ef2
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 {
......@@ -43,53 +46,108 @@ module simple_tdc_driver
time ts;
} acam_fifo_entry;
acam_fifo_entry fifo1[$], fifo2[$];
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 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;
acam_fifo_entry ent;
wait (pulses.size() != 0)
;
ent.channel = channel % 4;
ent.ts = ts;
t = pulses.pop_front();
now = $time;
if (channel >= 0 && channel <= 3)
fifo1.push_back(ent);
if (t.ts <= now)
$display("TDC: pulse in the past (%t now=%t)!", t.ts, now);
else
fifo2.push_back(ent);
begin
const int fifo_n = t.channel / 4;
logic [27:0] val;
#100ns;
if(fifo1.size())
ef1 = 0;
if(fifo2.size())
ef2 = 0;
#(t.ts - now) ;
endtask // pulse
val[27:26] = t.channel & 2'b11;
val[25:18] = start;
val[17] = 1'b1;
val[16:0] = (t.ts - start_time) / 81ps;
initial begin
ef1 = 1;
ef2 = 1;
data = 28'bz;
end
$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);
always@(negedge rd) begin
if (addr == 8) begin
acam_fifo_entry ent;
ent=fifo1.pop_front();
data <= ent.ts | (ent.channel << 26) | (1<<17);
fifos[t.channel / 4].push_back(val);
end
end
end else if (addr == 9) begin
acam_fifo_entry ent;
ent=fifo2.pop_front();
data <= ent.ts | (ent.channel << 26) | (1<<17);
initial begin
rdata = 28'bz;
end
end else
data <= 28'bz;
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
#10ns;
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
ef1 <= (fifo1.size() ? 0 : 1);
ef2 <= (fifo2.size() ? 0 : 1);
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
......@@ -123,20 +181,20 @@ module main;
wire a2btxp, a2btxn, b2atxp, b2atxn;
wire tdc_ef1, tdc_ef2, tdc_rd_n;
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;
always #4ns clk_125m_pllref <= ~clk_125m_pllref;
always #16ns clk_acam <= ~clk_acam;
always #20ns clk_20m_vcxo <= ~clk_20m_vcxo;
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);
......@@ -152,12 +210,15 @@ module main;
simple_tdc_driver
TDC
(
.clk(clk_acam),
.addr(tdc_addr),
.data(tdc_data),
.wr(1'b0),
.wr(tdc_wr_n),
.rd(tdc_rd_n),
.ef1(tdc_ef1),
.ef2(tdc_ef2)
.ef2(tdc_ef2),
.tstart(tdc_start),
.intflag(tdc_int)
);
svec_list_top #
......@@ -170,30 +231,32 @@ module main;
)
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_ef1_i (tdc_ef1),
.fmc0_tdc_ef2_i (tdc_ef2),
.fmc0_tdc_err_flag_i (1'b0),
.fmc0_tdc_int_flag_i (1'b0),
.fmc0_tdc_data_bus_io (tdc_data),
.fmc0_tdc_address_o (tdc_addr),
.fmc0_tdc_rd_n_o (tdc_rd_n)
.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
......@@ -322,9 +385,9 @@ module main;
forever begin
#200us;
TDC.pulse(0, 0);
TDC.pulse(1, 0);
TDC.pulse(2, 0);
TDC.pulse(0, $time + 10us);
TDC.pulse(1, $time + 20us);
TDC.pulse(2, $time + 30us);
end
end // initial begin others
......
......@@ -90,10 +90,10 @@ class WrtdLogMsg;
str = $sformatf ( {"[%8s] TYPE: %8s, SEQ: %3d, CHANNEL: %2d, ",
"TRIG_SYS: %0d, TRIG_PORT: %0d, TRIG_ID: %0d, ",
"TS_SEC: %2d, TS_TICKS: %10d" },
"TS_SEC: %2d, TS_TICKS: %10dns" },
origin.name(), ltype.name(), seq, channel,
id.system, id.source_port, id.trigger,
ts.seconds, ts.ticks);
ts.seconds, ts.ticks * 8);
if ( ts.frac > 0 )
str = { str, $sformatf ( ", TS_FRAC: %0d", ts.frac ) };
......
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