Commit 79a7656f authored by Dimitris Lampridis's avatar Dimitris Lampridis

sim: introduce spec150t_adc ref design testbench (WIP)

parent a414f0c8
Subproject commit 33b31655be05192c6a0fbb4f3c2d96cf55b3abb6
Subproject commit bb5b8f75e6f85335b43fef320375404686a74008
Subproject commit 0bf73130484cd9a0f550b68a9cf4ac3996fb526d
Subproject commit a60eac03a83cf136a5d3effac04346df874a24b0
Subproject commit 556e4c16302532ac5cb60150c18add695ea1b337
Subproject commit 0ed0cf1d2d8b21a9d92fea949a1ccaa03d9883a2
Subproject commit 10cd74b06a094c5b6c1a566676785e1814001404
Subproject commit ceb3c1227613e17d265573501fe0539b8314fb13
Subproject commit e3833c69188bd276af3697e534f6fe455a24cd16
Subproject commit 6beecf5aa562e81a1170af4edbfb59b49245bfb3
Subproject commit 70e9e78f740aa7f4d8168ccaa003bf3924824284
Subproject commit 5c7e906ceb6b15f53830061c9087cce0befef13a
Subproject commit 0d636aa520d0b547dbb1e8bd6f09d85f21203347
Subproject commit 4f1fafd72b08dee6ea9ef13715e6e9981e5d5021
......@@ -3,7 +3,7 @@
#
# Author: Adam Wujek, CERN 2017
TB_DIRS=wrtd_ref_svec_tdc_fd
TB_DIRS = wrtd_ref_svec_tdc_fd wrtd_ref_spec150t_adc
test_results_xml=test_results.xml
.PHONY: $(TB_DIRS)
......@@ -11,7 +11,8 @@ test_results_xml=test_results.xml
all: $(TB_DIRS) summary summary_total summary_xml
FW_BRAM = ../../software/firmware/fd/wrtd-rt-fd.bram \
../../software/firmware/tdc/wrtd-rt-tdc.bram \
../../software/firmware/tdc/wrtd-rt-tdc.bram \
../../software/firmware/adc/wrtd-rt-adc.bram
wrtd-system: $(FW_BRAM)
......
//------------------------------------------------------------------------------
// CERN BE-CO-HT
// White Rabbit Trigger Distribution (WRTD)
// https://ohwr.org/projects/wrtd
//------------------------------------------------------------------------------
//
// unit name: WrtdAlarm, WrtdAlarmCollection
//
// description: A SystemVerilog Class for a WRTD "alarm" repeated capability
//
//------------------------------------------------------------------------------
// 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.
//------------------------------------------------------------------------------
`ifndef __WRTD_ALARM_INCLUDED
`define __WRTD_ALARM_INCLUDED
`include "wrtd_rep_cap.svh"
class WrtdAlarm extends WrtdRepCap;
function new ( int core, int index, string name = "" );
super.new ( core, index, name );
clear();
endfunction // new
function void clear ( );
super.clear();
endfunction // clear
function repcap_data data_pack ( );
endfunction // data_pack
function void data_unpack ( repcap_data data );
endfunction // data_unpack
endclass //WrtdAlarm
class WrtdAlarmCollection extends WrtdRepCapCollection;
protected WrtdAlarm collection[];
function new ( int size, string name );
super.new ( size, name );
endfunction // new
endclass // WrtdAlarmCollection
`endif // `ifndef __WRTD_ALARM_INCLUDED
//------------------------------------------------------------------------------
// CERN BE-CO-HT
// White Rabbit Trigger Distribution (WRTD)
// https://ohwr.org/projects/wrtd
//------------------------------------------------------------------------------
//
// unit name: WrtdTstamp
//
// description: A collection of definitions and types used by the WrtdDev class.
//
// These are mostly copy-pasted from the WRTD library.
//
//------------------------------------------------------------------------------
// 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.
//------------------------------------------------------------------------------
`ifndef __WRTD_DEFINE_INCLUDED
`define __WRTD_DEFINE_INCLUDED
`define WRTD_MAX_CPUS 4
`define WRTD_MAX_DEVS 4
`define WRTD_ID_LEN 16
`define WRTD_IO_MSG_WORD_SIZE 3
`define WRTD_CFG_MSG_WORD_SIZE 5
`define WRTD_ROOT_WORD_SIZE 13
`define WRTD_RULE_WORD_SIZE 40
`define WRTD_ALRM_WORD_SIZE 15
enum {
WRTD_ACTION_GET_CONFIG,
WRTD_ACTION_READW,
WRTD_ACTION_WRITEW
} wrtd_trtl_actions;
enum {
WRTD_DIR_INPUT,
WRTD_DIR_OUTPUT
} wrtd_dir;
class WrtdTstamp;
protected string name;
protected uint32_t seconds;
protected uint32_t ns;
protected uint32_t frac;
function new ( uint32_t seconds = 0,
uint32_t ns = 0,
uint32_t frac = 0,
string name = "");
this.name = name;
set ( seconds, ns, frac );
endfunction // new
task mdisplay ( string str );
string tmp;
if (this.name == "")
tmp = $sformatf("<%t> %s", $realtime, str);
else
tmp = $sformatf("[%s] <%t> %s", this.name, $realtime, str);
$display (tmp);
endtask // mdisplay
function void set ( uint32_t seconds, uint32_t ns, uint32_t frac );
this.seconds = seconds;
this.ns = ns;
this.frac = frac;
endfunction // set
function void zero ( );
set ( 0, 0, 0);
endfunction // zero
endclass // WrtdTstamp
typedef struct {
uint32_t addr;
uint32_t nbr_alarms;
uint32_t alarms_addr;
uint32_t nbr_rules;
uint32_t rules_addr;
uint32_t nbr_devs;
uint32_t devs_addr[4];
} wrtd_root;
`endif // `ifndef __WRTD_DEFINE_INCLUDED
//------------------------------------------------------------------------------
// CERN BE-CO-HT
// White Rabbit Trigger Distribution (WRTD)
// https://ohwr.org/projects/wrtd
//------------------------------------------------------------------------------
//
// unit name: WrtdDev
//
// description: A SystemVerilog Class to provide an abstraction of a complete
// WRTD device.
//
//------------------------------------------------------------------------------
// 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.
//------------------------------------------------------------------------------
`ifndef __WRTD_DEV_INCLUDED
`define __WRTD_DEV_INCLUDED
`include "wrtd_definitions.svh"
`include "wrtd_rule.svh"
`include "wrtd_alarm.svh"
`include "mock_turtle_driver.svh"
class WrtdDev;
protected string name;
protected MockTurtleDriver mt;
protected uint32_t nbr_cpus;
protected uint32_t nbr_devs;
protected uint32_t hmq_words[];
protected wrtd_root roots[];
protected WrtdRuleCollection rules;
protected WrtdAlarmCollection alarms;
function new ( CBusAccessor acc, uint64_t base,
vIMockTurtleIRQ irq, string name = "" );
this.name = name;
this.mt = new (acc, base, irq, name);
endfunction // new
task mdisplay ( string str );
string tmp;
if (this.name == "")
tmp = $sformatf("<%t> %s", $realtime, str);
else
tmp = $sformatf("[%s] <%t> %s", this.name, $realtime, str);
$display (tmp);
endtask // mdisplay
task init ( );
int i, j, n;
uint32_t val, cpu_ready, init_done, nbr_rules, nbr_alarms;
uint32_t data[];
mt.init ( );
this.nbr_cpus = mt.rom.getCoreCount ( );
nbr_rules = 0;
nbr_alarms = 0;
this.hmq_words = new[this.nbr_cpus];
this.roots = new[this.nbr_cpus];
for ( i = 0; i < this.nbr_cpus; i++ )
begin
this.hmq_words[i] =
`TRTL_CONFIG_ROM_MQ_SIZE_PAYLOAD(mt.rom.getHmqDimensions(i, 0));
mt.enable_hmqi_irq ( i, 0, 1 );
mt.enable_console_irq ( i, 1 );
mt.reset_core ( i, 0 );
end
init_done = 0;
fork
begin
for ( i = 0; i < this.nbr_cpus; i++ )
begin
cpu_ready = 0;
while ( cpu_ready == 0 )
begin
val = 0;
mt.get_single_cpu_notification ( 0, val );
if ( val == TRTL_CPU_NOTIFY_MAIN )
cpu_ready = 1;
# 1us;
end
msg_get_config ( i, data );
this.roots[i].addr = data[0];
msg_readw ( i, this.roots[i].addr, `WRTD_ROOT_WORD_SIZE, data );
this.roots[i].nbr_rules = (data[1] & 'h00ff0000) >> 16;
this.roots[i].nbr_alarms = (data[1] & 'h0000ff00) >> 8;
this.roots[i].nbr_devs = (data[1] & 'h000000ff) >> 0;
this.roots[i].devs_addr[0:3] = data[4:7];
this.roots[i].rules_addr = data[8];
this.roots[i].alarms_addr = data[9];
this.nbr_devs += this.roots[i].nbr_devs;
nbr_rules += this.roots[i].nbr_rules;
nbr_alarms += this.roots[i].nbr_alarms;
end
this.rules = new ( nbr_rules, this.name );
n = 0;
for ( i = 0; i < this.nbr_cpus; i++ )
for ( j = 0; j < this.roots[i].nbr_rules; j++ )
begin
this.rules.init_element ( n, i, j );
n++;
end
this.alarms = new ( nbr_alarms, this.name );
n = 0;
for ( i = 0; i < this.nbr_cpus; i++ )
for ( j = 0; j < this.roots[i].nbr_alarms; j++ )
begin
this.alarms.init_element ( n, i, j );
n++;
end
init_done = 1;
end
begin
while ( init_done == 0 )
begin
mt.update ( );
# 1us;
end
end
join
mdisplay("WRTD ready!");
endtask // init
task msg_get_config ( int core, ref uint32_t data[] );
int i;
MQueueMsg msg;
if ( data.size() < `WRTD_CFG_MSG_WORD_SIZE )
data = new[`WRTD_IO_MSG_WORD_SIZE];
msg = new ( core, 0 );
msg.header.flags = `TRTL_HMQ_HEADER_FLAG_RPC | `TRTL_HMQ_HEADER_FLAG_SYNC;
msg.header.msg_id = WRTD_ACTION_GET_CONFIG;
msg.header.len = 0;
mt.hmq_send_message ( msg );
while ( mt.hmq_pending_messages ( msg.core, 0 ) == 0 ) #1us;
mt.hmq_receive_message ( msg );
for ( i = 0; i < `WRTD_IO_MSG_WORD_SIZE; i++ )
data[i] = msg.data[i];
endtask // msg_get_config
task msg_readw ( int core, uint32_t addr,
uint32_t count, ref uint32_t data[] );
int i;
MQueueMsg msg;
uint32_t tlen, offset;
if ( data.size() < count )
data = new[count];
offset = 0;
while ( offset <= count )
begin
tlen = this.hmq_words[core] - `WRTD_IO_MSG_WORD_SIZE;
if ( tlen > count )
tlen = count;
msg = new ( core, 0 );
msg.header.flags = `TRTL_HMQ_HEADER_FLAG_RPC | `TRTL_HMQ_HEADER_FLAG_SYNC;
msg.header.msg_id = WRTD_ACTION_READW;
msg.header.len = `WRTD_IO_MSG_WORD_SIZE;
msg.data = '{ addr, tlen };
mt.hmq_send_message ( msg );
while ( mt.hmq_pending_messages ( msg.core, 0 ) == 0 ) #1us;
mt.hmq_receive_message ( msg );
for ( i = 0; i < tlen; i++ )
data[offset+i] = msg.data[i];
offset += tlen;
end
endtask // msg_readw
task msg_writew ( int core, uint32_t addr,
uint32_t count, uint32_t data[] );
int i;
MQueueMsg msg;
uint32_t tlen, offset;
offset = 0;
while ( offset <= count )
begin
tlen = this.hmq_words[core] - `WRTD_IO_MSG_WORD_SIZE;
if ( tlen > count )
tlen = count;
msg = new ( core, 0 );
msg.header.flags = `TRTL_HMQ_HEADER_FLAG_RPC | `TRTL_HMQ_HEADER_FLAG_SYNC;
msg.header.msg_id = WRTD_ACTION_WRITEW;
msg.header.len = `WRTD_IO_MSG_WORD_SIZE;
msg.data = '{ addr, tlen };
for ( i = 0; i < tlen; i++ )
msg.data[i+2] = data[offset+i];
mt.hmq_send_message ( msg );
while ( mt.hmq_pending_messages ( msg.core, 0 ) == 0 ) #1us;
mt.hmq_receive_message ( msg );
offset += tlen;
end
endtask // msg_writew
task add_rule ( string rep_cap_id );
int idx;
idx = this.rules.add ( rep_cap_id );
write_rule ( idx );
endtask // add_rule
function int find_rule ( string rep_cap_id );
return this.rules.find ( rep_cap_id );
endfunction // find_rule
task remove_rule ( string rep_cap_id );
int idx;
idx = this.rules.remove ( rep_cap_id );
write_rule ( idx );
endtask // remove_rule
task set_rule ( string rep_cap_id, WrtdTstamp delay = null,
string src = "", string dst = "" );
int idx;
idx = this.rules.set ( rep_cap_id, delay, src, dst );
//apply_rules ();
endtask // set_rule
/* -----\/----- EXCLUDED -----\/-----
task apply_rules ( );
int i, count, src_cpu, dst_cpu;
for ( i = 0; i < this.rules.collection_size(); i++ )
begin
if ( this.rules.is_free( i ) == 0 )
begin
src_cpu = find_channel ( this.rules.get_src ( i ), WRTD_DIR_INPUT );
if ( src_cpu < 0 )
src_cpu = find_alarm ( this.rules.get_src ( i ) );
if ( src_cpu < 0 )
src_cpu = rx_cpu;
end
end
endtask // apply_rules
-----/\----- EXCLUDED -----/\----- */
task write_rule ( int idx );
int core, index;
uint32_t addr;
uint32_t data[];
if ( idx < 0 )
$error ( "cannot write rule with negative index" );
core = this.rules.get_core ( idx );
index = this.rules.get_index (idx );
addr = this.roots[core].rules_addr + index * `WRTD_RULE_WORD_SIZE * 4;
data = this.rules.data_pack( idx );
msg_writew ( core, addr, `WRTD_RULE_WORD_SIZE, data );
endtask // write_rule
task enable_rule ( int idx );
this.rules.set_enable ( idx );
// TODO reconfigure
endtask // enable_rule
task add_alarm ( string rep_cap_id );
int idx;
idx = this.alarms.add ( rep_cap_id );
write_alarm ( idx );
endtask // add_alarm
function int find_alarm ( string rep_cap_id );
return this.alarms.find ( rep_cap_id );
endfunction // find_alarm
task remove_alarm ( string rep_cap_id );
int idx;
idx = this.alarms.remove ( rep_cap_id );
write_alarm ( idx );
endtask // remove_alarm
task write_alarm ( int idx );
int core, index;
uint32_t addr;
uint32_t data[];
if ( idx < 0 )
$error ( "cannot write alarm with negative index" );
core = this.alarms.get_core ( idx );
index = this.alarms.get_index (idx );
addr = this.roots[core].alarms_addr + index * `WRTD_ALRM_WORD_SIZE * 4;
data = this.alarms.data_pack( idx );
msg_writew ( core, addr, `WRTD_ALRM_WORD_SIZE, data );
endtask // write_alarm
task log_read ( );
endtask // log_read
task update ( );
mt.update ( );
fork
/* -----\/----- EXCLUDED -----\/-----
check_log_queue ( 0 );
check_log_queue ( 1 );
-----/\----- EXCLUDED -----/\----- */
join
endtask // update
endclass // WrtdDev
`endif // `ifndef __WRTD_DEV_INCLUDED
//------------------------------------------------------------------------------
// CERN BE-CO-HT
// White Rabbit Trigger Distribution (WRTD)
// https://ohwr.org/projects/wrtd
//------------------------------------------------------------------------------
//
// unit name: WrtdRepCap, WrtdRepCapCollection
//
// description: A SystemVerilog Class for a WRTD "repeated capability"
//
//------------------------------------------------------------------------------
// 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.
//------------------------------------------------------------------------------
`ifndef __WRTD_REPCAP_INCLUDED
`define __WRTD_REPCAP_INCLUDED
`include "wrtd_definitions.svh"
typedef uint32_t repcap_data[];
virtual class WrtdRepCap;
protected string name;
protected string rep_cap_id;
protected int core;
protected int index;
protected int enabled;
function new ( int core, int index, string name = "" );
this.core = core;
this.index = index;
this.name = name;
clear();
endfunction // new
function void clear ( );
this.rep_cap_id = "";
this.enabled = 0;
endfunction // clear
task mdisplay ( string str );
string tmp;
if (this.name == "")
tmp = $sformatf("<%t> %s", $realtime, str);
else
tmp = $sformatf("[%s] <%t> %s", this.name, $realtime, str);
$display (tmp);
endtask // mdisplay
function int get_core ( );
return this.core;
endfunction // get_core
function int get_index ( );
return this.index;
endfunction // get_index
function string get_rep_cap_id ( );
return this.rep_cap_id;
endfunction // get_rep_cap_id
function void set_rep_cap_id ( string id );
this.rep_cap_id = id;
endfunction // set_rep_cap_id
function int match ( string id );
return ( this.rep_cap_id.compare ( id ) == 0 );
endfunction // is_equal
function int is_free ( );
return ( this.rep_cap_id.len == 0 );
endfunction // is_free
function int is_enabled ( );
return ( this.enabled > 0 );
endfunction // is_enabled
function void set_enable ( );
this.enabled = 1;
endfunction // set_enable
function void set_disable ( );
this.enabled = 0;
endfunction // set_disable
pure virtual function repcap_data data_pack ( );
pure virtual function void data_unpack ( repcap_data data );
endclass //WrtdRepCap
virtual class WrtdRepCapCollection;
protected string name;
protected WrtdRepCap collection[];
function new ( int size, string name );
this.name = name;
this.collection = new[size];
endfunction // new
task mdisplay ( string str );
string tmp;
if (this.name == "")
tmp = $sformatf("<%t> %s", $realtime, str);
else
tmp = $sformatf("[%s] <%t> %s", this.name, $realtime, str);
$display (tmp);
endtask // mdisplay
function void validate_id ( string rep_cap_id );
if ( rep_cap_id.len > `WRTD_ID_LEN )
$error ( "repeated capability name '%s' is too long", rep_cap_id );
if ( rep_cap_id.len == 0 )
$error ( "repeated capability name is null" );
endfunction // validate_id
function void init_element ( int idx, int core, int rule );
this.collection[idx] = new ( core, rule, this.name );
endfunction // init_element
function int collection_size( );
return this.collection.size();
endfunction // collection_size
function int is_free ( int idx );
return ( this.collection[idx].is_free() );
endfunction // is_free
function int get_core ( int idx );
return this.collection[idx].get_core();
endfunction // get_core
function int get_index ( int idx );
return this.collection[idx].get_index();
endfunction // get_index
function void set_enable ( int idx );
this.collection[idx].set_enable();
endfunction // set_enable
function void set_disable (int idx );
this.collection[idx].set_disable();
endfunction // set_disable
function repcap_data data_pack ( int idx );
return this.collection[idx].data_pack();
endfunction // data_pack
function void data_unpack ( int idx, repcap_data data );
this.collection[idx].data_unpack ( data );
endfunction // data_unpack
function int add ( string rep_cap_id );
int i, idx;
validate_id ( rep_cap_id );
idx = -1;
for ( i = 0; i < collection_size(); i++ )
begin
if ( this.collection[i].match ( rep_cap_id ) )
$error ( "%s repeated capability ID already exists", rep_cap_id );
if ( idx == -1 && this.collection[i].is_free() )
idx = i;
end
if ( idx == -1 )
$error ( "cannot add %s repeated capability, no space available", rep_cap_id );
this.collection[idx].set_rep_cap_id ( rep_cap_id );
return idx;
endfunction // add
function int find ( string rep_cap_id );
int i;
validate_id ( rep_cap_id );
for ( i = 0; i < collection_size(); i++ )
if ( this.collection[i].match ( rep_cap_id ) )
return i;
return -1;
endfunction // find
function int remove ( string rep_cap_id );
int idx;
idx = find ( rep_cap_id );
if ( idx == -1 )
$error ( "%s repeated capability ID cannot be removed because it does not exist", rep_cap_id );
if ( this.collection[idx].is_enabled() )
$error ( "%s repeated capability ID cannot be removed because it is enabled", rep_cap_id );
this.collection[idx].clear();
return idx;
endfunction // remove
endclass // WrtdRepCapCollection
`endif // `ifndef __WRTD_REPCAP_INCLUDED
//------------------------------------------------------------------------------
// CERN BE-CO-HT
// White Rabbit Trigger Distribution (WRTD)
// https://ohwr.org/projects/wrtd
//------------------------------------------------------------------------------
//
// unit name: WrtdRule, WrtdRuleCollection
//
// description: A SystemVerilog Class for a WRTD "rule" repeated capability
//
//------------------------------------------------------------------------------
// 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.
//------------------------------------------------------------------------------
`ifndef __WRTD_RULE_INCLUDED
`define __WRTD_RULE_INCLUDED
`include "wrtd_rep_cap.svh"
class WrtdRule extends WrtdRepCap;
protected string src;
protected string dst;
protected WrtdTstamp delay;
protected int send_late;
function new ( int core, int index, string name = "" );
super.new ( core, index, name );
this.delay = new ();
clear();
endfunction // new
function void clear ( );
super.clear();
this.delay.zero();
this.src = "";
this.dst = "";
this.send_late = 1;
endfunction // clear
function repcap_data data_pack ( );
endfunction // data_pack
function void data_unpack ( repcap_data data );
endfunction // data_unpack
function string get_src ( );
return this.src;
endfunction // get_src
function void set ( WrtdTstamp delay, string src, string dst );
if ( delay != null )
this.delay = delay;
else
this.delay.zero();
this.src = src;
this.dst = dst;
endfunction // set
endclass //WrtdRule
class WrtdRuleCollection extends WrtdRepCapCollection;
protected WrtdRule collection[];
function new ( int size, string name );
super.new ( size, name );
endfunction // new
function int set ( string rep_cap_id, WrtdTstamp delay,
string src, string dst );
int idx;
idx = find ( rep_cap_id );
if ( idx == -1 )
$error ( "%s repeated capability ID cannot be set because it does not exist", rep_cap_id );
if ( this.collection[idx].is_enabled() )
$error ( "%s repeated capability ID cannot be set because it is enabled", rep_cap_id );
this.collection[idx].set ( delay, src, dst );
return idx;
endfunction // set
function string get_src ( int idx );
return this.collection[idx].get_src();
endfunction // get_src
endclass // WrtdRuleCollection
`endif // `ifndef __WRTD_RULE_INCLUDED
work/
NullFile
Makefile
modelsim.ini
transcript*
*.wlf
board = "spec"
sim_tool = "modelsim"
top_module = "main"
action = "simulation"
target = "xilinx"
syn_device = "xc6slx150t"
vcom_opt = "-93 -mixedsvvh"
fetchto = "../../../dependencies"
ctrls = ["bank3_64b_32b"]
include_dirs = [
"../include",
fetchto + "/gn4124-core/hdl/gn4124core/sim/gn4124_bfm",
fetchto + "/general-cores/sim",
fetchto + "/mock-turtle/hdl/testbench/include",
fetchto + "/fmc-adc-100m14b4cha-gw/hdl/testbench/include",
]
files = [
"main.sv",
"dut_env.sv",
"synthesis_descriptor.vhd",
]
modules = {
"local" : [
"../../top/wrtd_ref_spec150t_adc",
],
}
Introduction
============
This is a testbench for the SPEC150T-based FMC ADC WRTD reference design.
Dependencies
============
To build this, you will need [hdl-make][1], using commit `968fa87` (or newer), as well as GNU Make.
To run it, you will need Modelsim/Questa. It has been tested with Questa 10.5c on Linux.
Build/Run Instrunctions
=======================
1. If not already done, pull all dependencies using `git submodule update --init` from within the
WRTD repository.
2. Run `hdlmake` from this directory.
3. Run `make` on the hdlmake-generated Makefile.
4. Run `vsim -c -do run.do`.
[1]: https://www.ohwr.org/projects/hdl-make/wiki
This diff is collapsed.
//------------------------------------------------------------------------------
// CERN BE-CO-HT
// White Rabbit Trigger Distribution (WRTD)
// https://ohwr.org/projects/wrtd
//------------------------------------------------------------------------------
//
// unit name: main
//
// description: Testbench for the SPEC150T-based FMC ADC WRTD reference design.
//
//------------------------------------------------------------------------------
// 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 "gn4124_bfm.svh"
`include "wrtd_dev.svh"
`include "fmc_adc_100Ms_csr.v"
`define ADC_CSR_BASE 'h5000
module main;
IGN4124PCIMaster hostA ();
//IGN4124PCIMaster hostB ();
reg duta_ext_trig, dutb_ext_trig;
wire[2:0] duta_acq_state, dutb_acq_state;
dut_env DUTA (hostA, duta_acq_state, a2b_txp, a2b_txn, a2b_rxp, a2b_rxn, duta_ext_trig);
//dut_env DUTB (hostB, dutb_acq_state, a2b_rxp, a2b_rxn, a2b_txp, a2b_txn, dutb_ext_trig);
IMockTurtleIRQ MtIrqMonitorA (`MT_ATTACH_IRQ(DUTA.DUT.cmp_mock_turtle));
//IMockTurtleIRQ MtIrqMonitorB (`MT_ATTACH_IRQ(DUTB.DUT.cmp_mock_turtle));
CBusAccessor accA, accB;
WrtdDev devA, devB;
const uint64_t MT_BASE = 'h0002_0000;
initial begin
uint64_t val, expected;
$timeformat (-6, 3, "us", 10);
duta_ext_trig <= 1'b0;
wait (hostA.ready == 1'b1);// && (hostB.ready == 1'b1));
accA = hostA.get_accessor();
//accB = hostB.get_accessor();
accA.set_default_xfer_size(4);
//accB.set_default_xfer_size(4);
devA = new (accA, MT_BASE, MtIrqMonitorA, "DUT:A");
//devB = new (accB, MT_BASE, MtIrqMonitorB, "DUT:B");
// Config DUTA to trigger on external trigger get 64 samples
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_PRE_SAMPLES, 'h00);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_POST_SAMPLES, 'h40);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_SHOTS, 'h01);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH1_GAIN, 'h8000);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH2_GAIN, 'h8000);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH3_GAIN, 'h8000);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH4_GAIN, 'h8000);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH1_SAT, 'h7fff);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH2_SAT, 'h7fff);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH3_SAT, 'h7fff);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CH4_SAT, 'h7fff);
val = (1'b1 << `FMC_ADC_100MS_CSR_TRIG_EN_EXT_OFFSET);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_TRIG_EN, val);
expected = 'h39;
accA.read(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_STA, val);
if (val != expected)
$fatal (1, "ADC status error (got 0x%8x, expected 0x%8x).", val, expected);
$display ("<%t> DUTA ADC configured and armed", $realtime);
wait (duta_acq_state == 1);
#500us;
$display("<%t> START ACQ 1", $realtime);
accA.write(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_CTL, 'h00000001); // FSM start
#5us;
duta_ext_trig <= 1'b1;
#10ns;
duta_ext_trig <= 1'b0;
wait (duta_acq_state == 1);
$display("<%t> END ACQ 1", $realtime);
accA.read(`ADC_CSR_BASE + `ADDR_FMC_ADC_100MS_CSR_TRIG_POS, val);
$display ("<%t> TRIG POSITION %.8x", $realtime, val);
// DMA transfer
accA.write('h2008, val); // dma start addr
accA.write('h200C, 'h00001000); // host addr
accA.write('h2010, 'h00000000);
accA.write('h2014, 'h00000100); // len << 2
accA.write('h2018, 'h00000000); // next
accA.write('h201C, 'h00000000);
accA.write('h2020, 'h00000000); // attrib: pcie -> host
accA.write('h2000, 'h00000001); // xfer start
wait (DUTA.DUT.dma_irq[0] == 1);
$display("<%t> END DMA 1", $realtime);
fork
devA.init();
//devB.init();
join
forever begin
devA.update();
//devB.update();
#1us;
end
end
initial begin
$display();
$display("Start of simulation");
$display("-------------------");
$display();
#5000us;
$display();
$display("Simulation PASSED");
$finish;
end
endmodule // main
vsim -quiet -t 10fs -L unisim work.main -suppress 1270,8617,8683,8684
set StdArithNoWarnings 1
set NumericStdNoWarnings 1
radix -hexadecimal
run -all
--------------------------------------------------------------------------------
-- SDB meta information for wrtd_ref_spec150t_adc.xise.
--
-- This file was automatically generated by ../../../dependencies/general-cores/tools/sdb_desc_gen.tcl on:
-- Wednesday, January 30 2019
--
-- ../../../dependencies/general-cores/tools/sdb_desc_gen.tcl is part of OHWR general-cores:
-- https://www.ohwr.org/projects/general-cores/wiki
--
-- For more information on SDB meta information, see also:
-- https://www.ohwr.org/projects/sdb/wiki
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.wishbone_pkg.all;
package synthesis_descriptor is
constant c_sdb_synthesis_info : t_sdb_synthesis := (
syn_module_name => "wrtd_ref_spec150",
syn_commit_id => "eaa378a35717954407166b2e80e34c2*",
syn_tool_name => "ISE ",
syn_tool_version => x"00000147",
syn_date => x"20190130",
syn_username => "Dimitris Lampri");
constant c_sdb_repo_url : t_sdb_repo_url := (
repo_url => "git@ohwr-gitlab.cern.ch:project/wrtd.git ");
end package synthesis_descriptor;
......@@ -111,7 +111,7 @@ class ListDriver;
protected int hmq_log_slot;
protected MockTurtleDriver mt;
function new ( CWishboneAccessor acc, uint64_t base,
function new ( CBusAccessor acc, uint64_t base,
vIMockTurtleIRQ irq, string name = "" );
this.name = name;
this.mt = new (acc, base, irq, name);
......@@ -126,10 +126,9 @@ class ListDriver;
$display (tmp);
endtask // mdisplay
task init ( wb_cycle_type_t mode = PIPELINED,
string cpu0_fw = "",
task init ( string cpu0_fw = "",
string cpu1_fw = "");
mt.init ( mode );
mt.init ( );
mt.enable_console_irq ( 0, 1 );
mt.enable_console_irq ( 1, 1 );
mt.enable_hmqi_irq ( 0, 0, 1 );
......
......@@ -656,6 +656,7 @@ begin -- architecture arch
cmp_sdb_crossbar : xwb_sdb_crossbar
generic map (
g_VERBOSE => FALSE,
g_NUM_MASTERS => c_NUM_WB_MASTERS,
g_NUM_SLAVES => c_NUM_WB_SLAVES,
g_REGISTERED => TRUE,
......@@ -771,6 +772,7 @@ begin -- architecture arch
cmp_xwrc_board_spec : xwrc_board_spec
generic map (
g_SIMULATION => g_SIMULATION,
g_VERBOSE => FALSE,
g_WITH_EXTERNAL_CLOCK_INPUT => FALSE,
g_DPRAM_INITF => g_WRPC_INITF,
g_AUX_PLL_CONFIG => c_WRPC_PLL_CONFIG,
......@@ -1107,6 +1109,7 @@ begin -- architecture arch
-- Note: g_address/g_mask index direction is to, master_i/master_o is downto
cpu0_crossbar : xwb_crossbar
generic map (
g_VERBOSE => FALSE,
g_num_masters => 1,
g_num_slaves => 2,
g_registered => False,
......
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