Commit bf9b1ed2 authored by Tristan Gingold's avatar Tristan Gingold

testbench: improve TDC emulation.

parent 55ff58bb
...@@ -30,12 +30,15 @@ ...@@ -30,12 +30,15 @@
module simple_tdc_driver module simple_tdc_driver
( (
input [3:0] addr, input clk,
output reg [27:0] data, input [3:0] addr,
input wr, inout [27:0] data,
input rd, input wr,
output reg ef1, input rd,
output reg ef2 output reg ef1,
output reg ef2,
input tstart,
output intflag
); );
typedef struct { typedef struct {
...@@ -43,53 +46,108 @@ module simple_tdc_driver ...@@ -43,53 +46,108 @@ module simple_tdc_driver
time ts; time ts;
} acam_fifo_entry; } 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); 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; t = pulses.pop_front();
ent.ts = ts; now = $time;
if (channel >= 0 && channel <= 3) if (t.ts <= now)
fifo1.push_back(ent); $display("TDC: pulse in the past (%t now=%t)!", t.ts, now);
else else
fifo2.push_back(ent); begin
const int fifo_n = t.channel / 4;
logic [27:0] val;
#100ns; #(t.ts - now) ;
if(fifo1.size())
ef1 = 0;
if(fifo2.size())
ef2 = 0;
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 $display("TDC: pulse at %t for channel %d (start #0x%x, time_data 0x%x, start_time %t)",
ef1 = 1; t.ts, t.channel, start, val[16:0], start_time);
ef2 = 1;
data = 28'bz;
end
always@(negedge rd) begin fifos[t.channel / 4].push_back(val);
if (addr == 8) begin end
acam_fifo_entry ent; end
ent=fifo1.pop_front();
data <= ent.ts | (ent.channel << 26) | (1<<17);
end else if (addr == 9) begin initial begin
acam_fifo_entry ent; rdata = 28'bz;
ent=fifo2.pop_front(); end
data <= ent.ts | (ent.channel << 26) | (1<<17);
end else always@(posedge tstart) begin
data <= 28'bz; 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); assign ef1 = fifos[0].size() == 0;
ef2 <= (fifo2.size() ? 0 : 1); 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 end
endmodule // simple_tdc_driver endmodule // simple_tdc_driver
...@@ -123,20 +181,20 @@ module main; ...@@ -123,20 +181,20 @@ module main;
wire a2btxp, a2btxn, b2atxp, b2atxn; 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 [3:0] tdc_addr;
wire [27:0] tdc_data; wire [27:0] tdc_data;
wire [3:0] fdl_len, fdl_pulse; wire [3:0] fdl_len, fdl_pulse;
wire [9:0] fdl_val; wire [9:0] fdl_val;
always #50ns clk_ext <= ~clk_ext; always #50ns clk_ext <= ~clk_ext; // 10Mhz
always #4ns clk_125m_pllref <= ~clk_125m_pllref; always #4ns clk_125m_pllref <= ~clk_125m_pllref; // 125Mhz
always #16ns clk_acam <= ~clk_acam; always #16ns clk_acam <= ~clk_acam; // 31.5Mhz
always #20ns clk_20m_vcxo <= ~clk_20m_vcxo; always #25ns clk_20m_vcxo <= ~clk_20m_vcxo; // 20Mhz
initial begin initial begin
repeat(20) @(posedge clk_20m_vcxo); repeat(20) @(posedge clk_20m_vcxo);
...@@ -152,12 +210,15 @@ module main; ...@@ -152,12 +210,15 @@ module main;
simple_tdc_driver simple_tdc_driver
TDC TDC
( (
.clk(clk_acam),
.addr(tdc_addr), .addr(tdc_addr),
.data(tdc_data), .data(tdc_data),
.wr(1'b0), .wr(tdc_wr_n),
.rd(tdc_rd_n), .rd(tdc_rd_n),
.ef1(tdc_ef1), .ef1(tdc_ef1),
.ef2(tdc_ef2) .ef2(tdc_ef2),
.tstart(tdc_start),
.intflag(tdc_int)
); );
svec_list_top # svec_list_top #
...@@ -170,30 +231,32 @@ module main; ...@@ -170,30 +231,32 @@ module main;
) )
DUT_A DUT_A
( (
.rst_n_i (rst_n), .rst_n_i (rst_n),
.clk_125m_pllref_p_i (clk_125m_pllref), .clk_125m_pllref_p_i (clk_125m_pllref),
.clk_125m_pllref_n_i (~clk_125m_pllref), .clk_125m_pllref_n_i (~clk_125m_pllref),
.clk_125m_gtp_p_i (clk_125m_pllref), .clk_125m_gtp_p_i (clk_125m_pllref),
.clk_125m_gtp_n_i (~clk_125m_pllref), .clk_125m_gtp_n_i (~clk_125m_pllref),
.clk_20m_vcxo_i (clk_20m_vcxo), .clk_20m_vcxo_i (clk_20m_vcxo),
.sim_wb_i (HostA.out), .sim_wb_i (HostA.out),
.sim_wb_o (HostA.in), .sim_wb_o (HostA.in),
.sfp_txp_o (a2btxp), .sfp_txp_o (a2btxp),
.sfp_txn_o (a2btxn), .sfp_txn_o (a2btxn),
.sfp_rxp_i (b2atxp), .sfp_rxp_i (b2atxp),
.sfp_rxn_i (b2atxn), .sfp_rxn_i (b2atxn),
.fmc0_tdc_pll_status_i (1'b1), .fmc0_tdc_pll_status_i (1'b1),
.fmc0_tdc_125m_clk_p_i (clk_125m_pllref), .fmc0_tdc_125m_clk_p_i (clk_125m_pllref),
.fmc0_tdc_125m_clk_n_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_p_i (clk_acam),
.fmc0_tdc_acam_refclk_n_i (~clk_acam), .fmc0_tdc_acam_refclk_n_i (~clk_acam),
.fmc0_tdc_ef1_i (tdc_ef1), .fmc0_tdc_start_from_fpga_o (tdc_start),
.fmc0_tdc_ef2_i (tdc_ef2), .fmc0_tdc_ef1_i (tdc_ef1),
.fmc0_tdc_err_flag_i (1'b0), .fmc0_tdc_ef2_i (tdc_ef2),
.fmc0_tdc_int_flag_i (1'b0), .fmc0_tdc_err_flag_i (1'b0),
.fmc0_tdc_data_bus_io (tdc_data), .fmc0_tdc_int_flag_i (tdc_int),
.fmc0_tdc_address_o (tdc_addr), .fmc0_tdc_data_bus_io (tdc_data),
.fmc0_tdc_rd_n_o (tdc_rd_n) .fmc0_tdc_address_o (tdc_addr),
.fmc0_tdc_rd_n_o (tdc_rd_n),
.fmc0_tdc_wr_n_o (tdc_wr_n)
); );
IVHDWishboneMaster HostA IVHDWishboneMaster HostA
...@@ -322,9 +385,9 @@ module main; ...@@ -322,9 +385,9 @@ module main;
forever begin forever begin
#200us; #200us;
TDC.pulse(0, 0); TDC.pulse(0, $time + 10us);
TDC.pulse(1, 0); TDC.pulse(1, $time + 20us);
TDC.pulse(2, 0); TDC.pulse(2, $time + 30us);
end end
end // initial begin others end // initial begin others
......
...@@ -90,10 +90,10 @@ class WrtdLogMsg; ...@@ -90,10 +90,10 @@ class WrtdLogMsg;
str = $sformatf ( {"[%8s] TYPE: %8s, SEQ: %3d, CHANNEL: %2d, ", str = $sformatf ( {"[%8s] TYPE: %8s, SEQ: %3d, CHANNEL: %2d, ",
"TRIG_SYS: %0d, TRIG_PORT: %0d, TRIG_ID: %0d, ", "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, origin.name(), ltype.name(), seq, channel,
id.system, id.source_port, id.trigger, id.system, id.source_port, id.trigger,
ts.seconds, ts.ticks); ts.seconds, ts.ticks * 8);
if ( ts.frac > 0 ) if ( ts.frac > 0 )
str = { str, $sformatf ( ", TS_FRAC: %0d", ts.frac ) }; 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