Commit 9ed14e39 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

added SV simulation models

parents
`timescale 1ps/1ps
// R-Mode only!
module acam_model
(
input PuResN,
input Alutrigger,
input RefClk,
input WRN,
input RDN,
input CSN,
input OEN,
input [3:0] Adr,
input DStart,
input DStop1,
input DStop2,
input TStart,
input[8:1] TStop,
input StartDis,
input[4:1] StopDis,
output IrFlag,
output ErrFlag,
output reg EF1,
output LF1,
inout[27:0] D
/* sim-only */
);
parameter real g_rmode_resolution = 80.9553ps / 3.0;
parameter int g_verbose = 1;
const real c_empty_flag_delay = 75ns;
wire start_masked;
wire stop1_masked;
wire r_MasterAluTrig;
wire r_StartDisStart;
reg[27:0] RB[0:14];
reg[27:0] DQ = 0;
reg EF1_int = 1'b1;
reg start_disabled_int;
int rmode_start_offset;
mailbox q_start, q_stop1;
mailbox q_hit;
int t = 0;
assign rmode_start_offset = RB[5][17:0];
always #(g_rmode_resolution) t <= t + 1;
assign r_MasterAluTrig = RB[5][23];
assign r_StartDisStart = RB[5][22];
task master_reset;
int i;
q_start = new(32);
q_stop1 = new(32);
q_hit = new(32);
EF1 <= 1;
start_disabled_int <= 0;
for(i=0;i<15;i++)
RB[i] = 0;
endtask // master_reset
initial master_reset();
always@(negedge PuResN) begin
master_reset();
end
always@(posedge Alutrigger) begin
if(r_MasterAluTrig)
begin
int dummy;
while(q_hit.num() > 0) q_hit.get(dummy);
start_disabled_int <= 0;
// EF1 <= 0;
end
// master_reset();
end
always@(negedge Alutrigger) begin
if(r_MasterAluTrig)
begin
// EF1 <= 1;
end
end
//
always@(posedge DStart)
if(PuResN && !StartDis && !start_disabled_int) begin
if(g_verbose)$display("acam::start %d", t);
q_start.put(t);
start_disabled_int <= r_StartDisStart;
end
always@(posedge DStop1)
if(PuResN && !StopDis[1]) begin
if(g_verbose)$display("acam::stop1 %d", t);
q_stop1.put(t);
end
always@(negedge WRN) if (!CSN && RDN)
begin
RB[Adr] <= D;
if(g_verbose)$display("acam::write reg %x val %x\n", Adr, D);
end
always@(negedge RDN) if (!CSN && WRN)
begin
if(g_verbose)$display("acam::read reg %x val %x\n", Adr, RB[Adr]);
if(Adr == 8) begin
int hit;
q_hit.try_get(hit);
DQ <= hit;
end else
DQ <= RB[Adr];
end
always@(negedge PuResN) begin
int i;
for (i=0;i<14;i++) RB[i] <= 0;
end
assign D = (!OEN)?DQ:28'bz;
initial forever
begin
int t_start, t_stop1, n_starts, tmp, hit;
#1;
q_stop1.get(t_stop1);
while(q_start.num() > 0) begin
q_start.peek(t_start);
if(t_start < t_stop1)
begin
q_start.get(tmp);
end
else
break;
end
if(t_stop1 - t_start > 3780)
hit = (t_stop1 - t_start) - (128ns/g_rmode_resolution) + rmode_start_offset * 3;
else
hit = t_stop1 - t_start + rmode_start_offset * 3;
if(g_verbose)$display("acam::hit1 %d", hit);
if(q_hit.num() == 0) begin
#(c_empty_flag_delay);
end
q_hit.put(hit);
end
reg fifo_empty =1;
reg fifo_notempty = 0;
initial forever begin
#1;
if(q_hit.num() > 0)
EF1 = #(12ns) 0;
else
EF1 = 1;
end
endmodule // acam_model
`define ADDR_FD_RSTR 7'h0
`define ADDR_FD_GCR 7'h4
`define FD_GCR_BYPASS_OFFSET 0
`define FD_GCR_BYPASS 32'h00000001
`define FD_GCR_INPUT_EN_OFFSET 1
`define FD_GCR_INPUT_EN 32'h00000002
`define FD_GCR_CLR_STAT_OFFSET 2
`define FD_GCR_CLR_STAT 32'h00000004
`define ADDR_FD_TAR 7'h8
`define FD_TAR_DATA_OFFSET 0
`define FD_TAR_DATA 32'h0fffffff
`define FD_TAR_ADDR_OFFSET 28
`define FD_TAR_ADDR 32'hf0000000
`define ADDR_FD_TDCSR 7'hc
`define FD_TDCSR_WRITE_OFFSET 0
`define FD_TDCSR_WRITE 32'h00000001
`define FD_TDCSR_READ_OFFSET 1
`define FD_TDCSR_READ 32'h00000002
`define FD_TDCSR_ERR_OFFSET 2
`define FD_TDCSR_ERR 32'h00000004
`define FD_TDCSR_INT_OFFSET 3
`define FD_TDCSR_INT 32'h00000008
`define FD_TDCSR_LOAD_OFFSET 4
`define FD_TDCSR_LOAD 32'h00000010
`define FD_TDCSR_EMPTY_OFFSET 5
`define FD_TDCSR_EMPTY 32'h00000020
`define FD_TDCSR_START_DIS_OFFSET 6
`define FD_TDCSR_START_DIS 32'h00000040
`define FD_TDCSR_START_EN_OFFSET 7
`define FD_TDCSR_START_EN 32'h00000080
`define FD_TDCSR_STOP_DIS_OFFSET 8
`define FD_TDCSR_STOP_DIS 32'h00000100
`define FD_TDCSR_STOP_EN_OFFSET 9
`define FD_TDCSR_STOP_EN 32'h00000200
`define ADDR_FD_DCR 7'h10
`define FD_DCR_DLY_SEL_OFFSET 0
`define FD_DCR_DLY_SEL 32'h0000000f
`define FD_DCR_DLY_VAL_OFFSET 4
`define FD_DCR_DLY_VAL 32'h00003ff0
`define ADDR_FD_GPSR 7'h14
`define FD_GPSR_CS_PLL_OFFSET 0
`define FD_GPSR_CS_PLL 32'h00000001
`define FD_GPSR_CS_GPIO_OFFSET 1
`define FD_GPSR_CS_GPIO 32'h00000002
`define FD_GPSR_SCLK_OFFSET 2
`define FD_GPSR_SCLK 32'h00000004
`define FD_GPSR_MOSI_OFFSET 3
`define FD_GPSR_MOSI 32'h00000008
`define ADDR_FD_GPCR 7'h18
`define FD_GPCR_CS_PLL_OFFSET 0
`define FD_GPCR_CS_PLL 32'h00000001
`define FD_GPCR_CS_GPIO_OFFSET 1
`define FD_GPCR_CS_GPIO 32'h00000002
`define FD_GPCR_SCLK_OFFSET 2
`define FD_GPCR_SCLK 32'h00000004
`define FD_GPCR_MOSI_OFFSET 3
`define FD_GPCR_MOSI 32'h00000008
`define ADDR_FD_GPRR 7'h1c
`define FD_GPRR_MISO_OFFSET 0
`define FD_GPRR_MISO 32'h00000001
`define ADDR_FD_IECRAW 7'h20
`define ADDR_FD_IECTAG 7'h24
`define ADDR_FD_IEPD 7'h28
`define ADDR_FD_PGCR 7'h2c
`define FD_PGCR_PERIOD_OFFSET 0
`define FD_PGCR_PERIOD 32'h7fffffff
`define FD_PGCR_ENABLE_OFFSET 31
`define FD_PGCR_ENABLE 32'h80000000
`define ADDR_FD_TSFIFO_R0 7'h30
`define FD_TSFIFO_R0_UTC_OFFSET 0
`define FD_TSFIFO_R0_UTC 32'hffffffff
`define ADDR_FD_TSFIFO_R1 7'h34
`define FD_TSFIFO_R1_COARSE_OFFSET 0
`define FD_TSFIFO_R1_COARSE 32'h0fffffff
`define ADDR_FD_TSFIFO_R2 7'h38
`define FD_TSFIFO_R2_FRAC_OFFSET 0
`define FD_TSFIFO_R2_FRAC 32'h007fffff
`define ADDR_FD_TSFIFO_R3 7'h3c
`define FD_TSFIFO_R3_FRAC_RAW_OFFSET 0
`define FD_TSFIFO_R3_FRAC_RAW 32'h007fffff
`define ADDR_FD_TSFIFO_CSR 7'h40
`define FD_TSFIFO_CSR_FULL_OFFSET 16
`define FD_TSFIFO_CSR_FULL 32'h00010000
`define FD_TSFIFO_CSR_EMPTY_OFFSET 17
`define FD_TSFIFO_CSR_EMPTY 32'h00020000
module ideal_timestamper
(
input clk_ref_i,
input rst_n_i,
input enable_i,
input trig_a_i,
output reg [22:0] tag_frac_o,
output reg [27:0] tag_coarse_o,
output reg [31:0] tag_utc_o,
output tag_valid_p1_o,
output [27:0] cntr_coarse_o,
output [31:0] cntr_utc_o
);
parameter real g_frac_resolution = 80.9553ps/3.0;
reg [27:0] cntr_coarse;
reg [31:0] cntr_utc;
reg [22:0] cntr_frac;
reg tag_valid_p1;
typedef struct {
reg [27:0] coarse;
reg [31:0] utc;
reg [22:0] frac;
} timestamp_t;
timestamp_t ts_queue[$] = '{};
always@(posedge clk_ref_i)
if(!rst_n_i)
begin
cntr_coarse <= 0;
cntr_utc <= 0;
cntr_frac <= 0;
tag_valid_p1 <= 0;
ts_queue = '{};
end
always@(posedge clk_ref_i)
cntr_frac <= 0;
always@(posedge clk_ref_i)
if(rst_n_i)
begin
if(cntr_coarse == 125000000 - 1) begin
cntr_coarse <= 0;
cntr_utc <= cntr_utc + 1;
end else
cntr_coarse <= cntr_coarse + 1;
end
initial forever begin
#(g_frac_resolution) cntr_frac <= cntr_frac + 1;
end
always@(posedge trig_a_i) begin
if(enable_i)
begin
timestamp_t ts;
ts.frac = cntr_frac;
ts.coarse = cntr_coarse;
ts.utc = cntr_utc;
ts_queue.push_back(ts);
end
end
always@(posedge clk_ref_i)
if(tag_valid_p1)
tag_valid_p1 <= 0;
else if(ts_queue.size() > 0)
begin
timestamp_t ts;
ts = ts_queue.pop_front();
tag_frac_o <= ts.frac;
tag_utc_o <= ts.utc;
tag_coarse_o <= ts.coarse;
tag_valid_p1 <= 1'b1;
end
assign tag_valid_p1_o = tag_valid_p1;
assign cntr_coarse_o = cntr_coarse;
assign cntr_utc_o = cntr_utc;
endmodule // ideal_timestamper
//
// Title : Software Wishbone master unit for testbenches
//
// File : if_wishbone.sv
// Author : Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
// Created : Tue Mar 23 12:19:36 2010
// Standard : SystemVerilog
//
// Default values of certain WB parameters.
`include "simdrv_defs.sv"
interface IWishbone
(
input clk_i,
input rst_n_i
);
parameter g_data_width = 32;
parameter g_addr_width = 32;
/* Interface signals */
logic [g_addr_width - 1 : 0] adr;
logic [g_data_width - 1 : 0] dat_o;
logic [3 : 0] sel; // FIXME: 32-bit only
wire [g_data_width - 1 : 0] dat_i;
wire ack;
logic cyc;
logic stb;
logic we;
wire stall;
initial begin
adr = 0;
dat_o = 0;
sel = 0;
cyc = 0;
stb = 0;
we = 0;
end
time last_access_t = 0;
reg [g_data_width-1:0] dummy;
// enables/disables displaying information about each read/write operation.
int tb_verbose = 0;
task verbose(int onoff);
tb_verbose = onoff;
endtask // wb_verbose
task classic_single_rw_generic;
input [g_addr_width - 1 : 0] trans_addr;
input [g_data_width - 1 : 0] trans_wdata;
output [g_data_width - 1 : 0] trans_rdata;
input rw;
input [3:0] size;
begin : rw_generic_main
if(tb_verbose && rw)
$display("WB write %s: addr %x, data %x",
(size==1?"byte":((size==2)?"short":"int")),
trans_addr, trans_wdata);
if($time != last_access_t) begin
@(posedge clk_i);
end
stb<=1;
cyc<=1;
adr <= {2'b00, trans_addr[31:2]};
we <= rw;
if(rw) begin
case(size)
4: begin dat_o<=trans_wdata; sel <= 4'b1111; end
2: begin
if(adr[1]) begin
dat_o[31:16] <= trans_wdata[15:0];
sel <= 4'b1100;
end else begin
dat_o[15:0] <= trans_wdata[15:0];
sel <= 4'b0011;
end
end
1: begin
case(adr[1:0])
0: begin dat_o[31:24] <= trans_wdata[7:0]; sel <= 4'b1000; end
1: begin dat_o[23:16] <= trans_wdata[7:0]; sel <= 4'b0100; end
2: begin dat_o[15:8] <= trans_wdata[7:0]; sel <= 4'b0010; end
3: begin dat_o[7:0] <= trans_wdata[7:0]; sel <= 4'b0001; end
endcase // case(addr[1:0])
end
endcase // case(size)
end // if (rw)
@(posedge clk_i);
if(ack == 0) begin
while(ack == 0) begin @(posedge clk_i); end
end
trans_rdata = dat_i;
cyc <= 0;
we<=0;
stb<=0;
if(tb_verbose && !rw)
$display("WB read %s: addr %x, data %x",
(size==1?"byte":((size==2)?"short":"int")),
trans_addr, trans_rdata);
last_access_t = $time;
end
endtask // rw_generic
task write32;
input [g_addr_width - 1 : 0] addr;
input [31 : 0] data_i;
begin
classic_single_rw_generic(addr, data_i, dummy, 1, 4);
end
endtask // write32
task read32;
input [g_addr_width - 1 : 0] addr;
output [31 : 0] data_o;
begin : read32_body
reg [g_data_width - 1 : 0] rval;
classic_single_rw_generic(addr, 0, rval, 0, 4);
data_o = rval[31:0];
end
endtask // write32
modport master
(
output adr,
output dat_o,
output sel,
output cyc,
output stb,
output we,
input ack,
input dat_i,
input stall);
endinterface // IWishbone
module jittery_delay
(
input in_i,
output reg out_o
);
parameter g_delay = 10ns;
parameter g_jitter = 10ps;
int seed = 1;
always@(in_i)
begin
real delta;
seed = $urandom(seed);
delta = $dist_normal(seed, g_delay, g_jitter);
out_o <= #(delta) in_i;
end
endmodule // jittery_delay
\ No newline at end of file
`timescale 1ps/1ps
module mc100ep195
(
input len,
input i,
input [9:0] delay,
output o
);
const int c_min_delay = 2ns;
const int c_time_per_tap = 10ps;
reg [9:0] cur_dly = 0;
reg o_reg = 0;
assign o = o_reg;
always@(len)
if(len)
cur_dly <= delay;
always@(i)
o_reg <= #(c_min_delay + cur_dly * c_time_per_tap) i;
endmodule // mc100ep195
module random_pulse_gen
(
input enable_i,
output reg pulse_o
);
parameter real g_pulse_width = 30ns;
parameter real g_min_spacing = 300ns;
parameter real g_max_spacing = 600ns;
int seed = 1;
initial forever
if(enable_i)
begin
real delta;
seed = $urandom(seed);
delta = $dist_uniform(seed, g_min_spacing + g_pulse_width, g_max_spacing + g_pulse_width);
pulse_o = 1;
#(g_pulse_width);
pulse_o = 0;
#(delta);
end else begin
pulse_o <= 1'b0;
#1;
end
endmodule // random_pulse_gen
`ifndef SIMDRV_DEFS_SV
`define SIMDRV_DEFS_SV 1
virtual class CBusAccessor;
pure virtual task write32(int addr, bit[31:0] data);
pure virtual task read32(int addr, output bit[31:0] rdata);
endclass // CBusAccessor
`endif
\ No newline at end of file
`timescale 10fs/10fs
module tunable_clock_gen
(
input real vtune_i,
input enable_i,
output clk_o);
parameter g_tunable = 0;
parameter g_tuning_range = 20e-6; // 20 ppm
parameter g_tuning_voltage = 1.0;
parameter real g_period = 8ns;
parameter real g_jitter = 10ps;
reg clk = 1'b1;
real cur_offset = 0;
real prev_err = 0;
real next_offset;
real cur_err;
real cur_period;
int seed = 1;
real max_range;
initial begin
cur_offset = 0;
prev_err = 0;
end
initial forever
if(enable_i)
begin
seed = $urandom(seed);
cur_err = (real'($urandom_range(0, 1000)) -500.0)/ 1000.0 * g_jitter;
// $display("%.15f %.15f", cur_err, g_jitter);
if(g_tunable)
begin
realtime period_tune;
period_tune = realtime'(real'(g_period/2) * (vtune_i-(real'(g_tuning_voltage/2)))/(real'(g_tuning_voltage/2)) * real'(g_tuning_range));
cur_period = g_period/2 + period_tune ;
end else
cur_period = g_period/2;
next_offset = -prev_err + cur_period + cur_err;
prev_err = cur_err;
// $display("NextOffs: %.15f", next_offset);
#(integer'(next_offset)) clk = ~clk;
end else begin // if (enable)
cur_offset = 0;
cur_period = 0;
clk = 1;
#1;
end // else: !if(enable)
assign clk_o = clk;
endmodule // tunable_clock_gen
\ No newline at end of file