diff --git a/basil/HL/pulse_gen640.py b/basil/HL/pulse_gen640.py new file mode 100644 index 000000000..0b189ead0 --- /dev/null +++ b/basil/HL/pulse_gen640.py @@ -0,0 +1,98 @@ +# +# ------------------------------------------------------------ +# Copyright (c) All rights reserved +# SiLab, Institute of Physics, University of Bonn +# ------------------------------------------------------------ +# + +from basil.HL.RegisterHardwareLayer import RegisterHardwareLayer + + +class pulse_gen640(RegisterHardwareLayer): + '''Pulser generator + ''' + + _registers = {'RESET': {'descr': {'addr': 0, 'size': 8, 'properties': ['writeonly']}}, + 'VERSION': {'descr': {'addr': 0, 'size': 8, 'properties': ['ro']}}, + 'READY': {'descr': {'addr': 1, 'size': 1, 'properties': ['ro']}}, + 'START': {'descr': {'addr': 1, 'size': 8, 'properties': ['writeonly']}}, + 'EN': {'descr': {'addr': 2, 'size': 1}}, + 'DELAY': {'descr': {'addr': 3, 'size': 32}}, + 'WIDTH': {'descr': {'addr': 7, 'size': 32}}, + 'REPEAT': {'descr': {'addr': 11, 'size': 32}}, + 'PHASE_DES': {'descr': {'addr': 15, 'size': 16}}, + 'DEBUG': {'descr': {'addr': 17, 'size': 64}}, + } + _require_version = "==1" + + def __init__(self, intf, conf): + super(pulse_gen640, self).__init__(intf, conf) + + def start(self): + ''' + Software start of pulse at random time + ''' + self.START = 0 + + def reset(self): + self.RESET = 0 + + def set_delay(self, value): + ''' + Pulse delay w.r.t. shift register finish signal [in clock cycles(?)] + ''' + self.DELAY = value + + def get_delay(self): + return self.DELAY + + def set_phase(self, value): + ''' + Pulse phase in 640MHz from 0 to 16 + ''' + self.PHASE_DES = (0xFFFF << (value % 16)) & 0xFFFF + + def get_phase(self): + # print("=====sim=====", self.PHASE_DES, self.DELAY) + for i in range(16): + if ((0xFFFF0000 | self.PHASE_DES) >> i) & 0xFFFF == 0xFFFF: + break + return i + + def set_width(self, value): + ''' + Pulse width in terms of clock cycles + ''' + self.WIDTH = value + + def get_width(self): + return self.WIDTH + + def set_repeat(self, value): + ''' + Pulse repetition in range of 0-255 + ''' + self.REPEAT = value + + def get_repeat(self): + return self.REPEAT + + def is_done(self): + return self.is_ready + + @property + def is_ready(self): + return self.READY + + def set_en(self, value): + ''' + If true: The pulse comes with a fixed delay with respect to the external trigger (EXT_START). + If false: The pulse comes only at software start. + ''' + self.EN = value + + def get_en(self): + ''' + Return info if pulse starts with a fixed delay w.r.t. shift register finish signal (true) or if it only starts with .start() (false) + ''' + return self.EN diff --git a/basil/HL/timestamp640.py b/basil/HL/timestamp640.py new file mode 100644 index 000000000..3b8b6d99f --- /dev/null +++ b/basil/HL/timestamp640.py @@ -0,0 +1,34 @@ +# +# ------------------------------------------------------------ +# Copyright (c) All rights reserved +# SiLab, Institute of Physics, University of Bonn +# ------------------------------------------------------------ +# + +from basil.HL.RegisterHardwareLayer import RegisterHardwareLayer + + +class timestamp640(RegisterHardwareLayer): + '''Implement timestamp driver. + ''' + + def __init__(self, intf, conf): + self._registers = {'RESET': {'descr': {'addr': 0, 'size': 8, 'properties': ['writeonly']}}, + 'VERSION': {'descr': {'addr': 0, 'size': 8, 'properties': ['ro']}}, + 'ENABLE': {'descr': {'addr': 2, 'size': 1, 'offset': 0}}, + 'EXT_TIMESTAMP': {'descr': {'addr': 2, 'size': 1, 'offset': 1}}, + 'ENABLE_EXTERN': {'descr': {'addr': 2, 'size': 1, 'offset': 2}}, + 'ENABLE_TRAILING': {'descr': {'addr': 2, 'size': 1, 'offset': 3}}, + 'INVERT': {'descr': {'addr': 2, 'size': 1, 'offset': 4}}, + 'LOST_COUNT': {'descr': {'addr': 3, 'size': 8}}, + } + self._require_version = "==3" + + super(timestamp640, self).__init__(intf, conf) + + def init(self): + super(timestamp640, self).init() + + def reset(self): + '''Soft reset the module.''' + self.RESET = 0 diff --git a/basil/firmware/modules/pulse_gen640/README.rst b/basil/firmware/modules/pulse_gen640/README.rst new file mode 100644 index 000000000..35bb1c44c --- /dev/null +++ b/basil/firmware/modules/pulse_gen640/README.rst @@ -0,0 +1,45 @@ + +=============================== +**pulse_gen** - pulse generator +=============================== + +Simple pulse generator with configurable delay and width. + +**Unit test/Example:** +`test_SimTimestamp640.v `_ +`test_SimTimestamp40.py `_ + +Pins + +---------------+---------------------+-----------------------+------------------------------------------------------+ + | Name | Size | Direction | Description | + +===============+=====================+=======================+======================================================+ + | EXT_START | 1 | input | active high start signal (synchronous to PULSE_CLK) | + +---------------+---------------------+-----------------------+------------------------------------------------------+ + | PULSE_CLK | 1 | input | module clock | + +---------------+---------------------+-----------------------+------------------------------------------------------+ + | PULSE_CLK160 | 1 | input | module clock (4xPULSE_CLK) | + +---------------+---------------------+-----------------------+------------------------------------------------------+ + | PULSE_CLK320 | 1 | input | module clock (8xPULSE_CLK) | + +---------------+---------------------+-----------------------+------------------------------------------------------+ + | PULSE | 1 | output | output pulse | + +---------------+---------------------+-----------------------+------------------------------------------------------+ + +Registers + +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ + | Name | Address | Bits | r/w | Default | Description | + +===============+==================================+========+=======+=============+============================================================================================+ + | START | 1 | | wo | | software start on write to address | + +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ + | READY | 1 | [0] | ro | 0 | indicate finish | + +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ + | EN | 2 | [0] | r/w | 0 | enable external start | + +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ + | DELAY | 6 - 3 | [31:0] | r/w | 0 | pulse delay from start | + +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ + | WIDTH | 10 - 7 | [31:0] | r/w | 0 | pulse width | + +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ + | REPEAT | 11 - 14 | [31:0] | r/w | 1 | repeat count (0 ->forever) | + +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ + | PHASE_DES | 15 - 16 | [15:0] | r/w | 0 | phase delay (0x0->0, 0x1->1, 0x8000->15) | + +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ + diff --git a/basil/firmware/modules/pulse_gen640/pulse_gen640.v b/basil/firmware/modules/pulse_gen640/pulse_gen640.v new file mode 100644 index 000000000..91d27e82e --- /dev/null +++ b/basil/firmware/modules/pulse_gen640/pulse_gen640.v @@ -0,0 +1,74 @@ +/** + * ------------------------------------------------------------ + * Copyright (c) All rights reserved + * SiLab, Institute of Physics, University of Bonn + * ------------------------------------------------------------ + */ +`timescale 1ps/1ps +`default_nettype none + +module pulse_gen640 +#( + parameter BASEADDR = 16'h0000, + parameter HIGHADDR = 16'h0000, + parameter ABUSWIDTH = 16, + parameter CLKDV = 4, + parameter OUTPUT_SIZE =2 +)( + input wire BUS_CLK, + input wire [ABUSWIDTH-1:0] BUS_ADD, + inout wire [7:0] BUS_DATA, + input wire BUS_RST, + input wire BUS_WR, + input wire BUS_RD, + + input wire PULSE_CLK, + input wire PULSE_CLK160, + input wire PULSE_CLK320, + input wire EXT_START, + output wire [OUTPUT_SIZE-1:0] PULSE, + output wire DEBUG +); + +wire IP_RD, IP_WR; +wire [ABUSWIDTH-1:0] IP_ADD; +wire [7:0] IP_DATA_IN; +wire [7:0] IP_DATA_OUT; + +bus_to_ip #( .BASEADDR(BASEADDR), .HIGHADDR(HIGHADDR), .ABUSWIDTH(ABUSWIDTH) ) i_bus_to_ip +( + .BUS_RD(BUS_RD), + .BUS_WR(BUS_WR), + .BUS_ADD(BUS_ADD), + .BUS_DATA(BUS_DATA), + + .IP_RD(IP_RD), + .IP_WR(IP_WR), + .IP_ADD(IP_ADD), + .IP_DATA_IN(IP_DATA_IN), + .IP_DATA_OUT(IP_DATA_OUT) +); + +pulse_gen640_core #( + .ABUSWIDTH(ABUSWIDTH), + .CLKDV(CLKDV), + .OUTPUT_SIZE(OUTPUT_SIZE) +) i_pulse_gen640_core ( + + .BUS_CLK(BUS_CLK), + .BUS_RST(BUS_RST), + .BUS_ADD(IP_ADD), + .BUS_DATA_IN(IP_DATA_IN), + .BUS_RD(IP_RD), + .BUS_WR(IP_WR), + .BUS_DATA_OUT(IP_DATA_OUT), + + .PULSE_CLK(PULSE_CLK), + .PULSE_CLK160(PULSE_CLK160), + .PULSE_CLK320(PULSE_CLK320), + .EXT_START(EXT_START), + .PULSE(PULSE), + .DEBUG(DEBUG) +); + +endmodule diff --git a/basil/firmware/modules/pulse_gen640/pulse_gen640_core.v b/basil/firmware/modules/pulse_gen640/pulse_gen640_core.v new file mode 100644 index 000000000..89997a57c --- /dev/null +++ b/basil/firmware/modules/pulse_gen640/pulse_gen640_core.v @@ -0,0 +1,291 @@ +/** + * ------------------------------------------------------------ + * Copyright (c) All rights reserved + * SiLab, Institute of Physics, University of Bonn + * ------------------------------------------------------------ + */ +`timescale 1ps/1ps +`default_nettype none + +module pulse_gen640_core +#( + parameter ABUSWIDTH = 16, + parameter CLKDV = 4, //only 4 will work for now + parameter OUTPUT_SIZE =2 +) +( + input wire BUS_CLK, + input wire [ABUSWIDTH-1:0] BUS_ADD, + input wire [7:0] BUS_DATA_IN, + output reg [7:0] BUS_DATA_OUT, + input wire BUS_RST, + input wire BUS_WR, + input wire BUS_RD, + + + input wire PULSE_CLK, + input wire PULSE_CLK160, + input wire PULSE_CLK320, + input wire EXT_START, + output wire [OUTPUT_SIZE-1:0] PULSE, + output wire DEBUG +); + +localparam VERSION = 1; + +wire SOFT_RST; +wire START; +reg CONF_EN; +reg [31:0] CONF_DELAY; +reg [31:0] CONF_WIDTH; +reg [31:0] CONF_REPEAT; +//reg [CLKDV*4-1:0] CONF_PHASE; +reg [15:0] CONF_PHASE; +reg CONF_DONE; + +always@(posedge BUS_CLK) begin + if(BUS_RD) begin + if(BUS_ADD == 0) + BUS_DATA_OUT <= VERSION; + else if(BUS_ADD == 1) + BUS_DATA_OUT <= {7'b0, CONF_DONE}; + else if(BUS_ADD == 2) + BUS_DATA_OUT <= {7'b0, CONF_EN}; + else if(BUS_ADD == 3) + BUS_DATA_OUT <= CONF_DELAY[7:0]; + else if(BUS_ADD == 4) + BUS_DATA_OUT <= CONF_DELAY[15:8]; + else if(BUS_ADD == 5) + BUS_DATA_OUT <= CONF_DELAY[23:16]; + else if(BUS_ADD == 6) + BUS_DATA_OUT <= CONF_DELAY[31:24]; + else if(BUS_ADD == 7) + BUS_DATA_OUT <= CONF_WIDTH[7:0]; + else if(BUS_ADD == 8) + BUS_DATA_OUT <= CONF_WIDTH[15:8]; + else if(BUS_ADD == 9) + BUS_DATA_OUT <= CONF_WIDTH[23:16]; + else if(BUS_ADD == 10) + BUS_DATA_OUT <= CONF_WIDTH[31:24]; + else if(BUS_ADD == 11) + BUS_DATA_OUT <= CONF_REPEAT[7:0]; + else if(BUS_ADD == 12) + BUS_DATA_OUT <= CONF_REPEAT[15:8]; + else if(BUS_ADD == 13) + BUS_DATA_OUT <= CONF_REPEAT[23:16]; + else if(BUS_ADD == 14) + BUS_DATA_OUT <= CONF_REPEAT[31:24]; + else if(BUS_ADD == 15) + BUS_DATA_OUT <= CONF_PHASE[7:0]; + else if(BUS_ADD == 16) + BUS_DATA_OUT <= CONF_PHASE[15:8]; + // debug + else if(BUS_ADD == 17) + BUS_DATA_OUT <= CNT[7:0]; + else if(BUS_ADD == 18) + BUS_DATA_OUT <= CNT[15:8]; + else if(BUS_ADD == 19) + BUS_DATA_OUT <= CNT[23:16]; + else if(BUS_ADD == 20) + BUS_DATA_OUT <= CNT[31:24]; + else if(BUS_ADD == 21) + BUS_DATA_OUT <= {6'b0, PULSE_REF, CNT[32]}; + else + BUS_DATA_OUT <= 8'b0; + end +end + +assign SOFT_RST = (BUS_ADD==0 && BUS_WR); +assign START = (BUS_ADD==1 && BUS_WR); + +wire RST; +assign RST = BUS_RST | SOFT_RST; + +always @(posedge BUS_CLK) begin + if(RST) begin + CONF_EN <= 0; + CONF_DELAY <= 0; + CONF_WIDTH <= 0; + CONF_REPEAT <= 1; + CONF_PHASE <=0; + end + else if(BUS_WR) begin + if(BUS_ADD == 2) + CONF_EN <= BUS_DATA_IN[0]; + else if(BUS_ADD == 3) + CONF_DELAY[7:0] <= BUS_DATA_IN; + else if(BUS_ADD == 4) + CONF_DELAY[15:8] <= BUS_DATA_IN; + else if(BUS_ADD == 5) + CONF_DELAY[23:16] <= BUS_DATA_IN; + else if(BUS_ADD == 6) + CONF_DELAY[31:24] <= BUS_DATA_IN; + else if(BUS_ADD == 7) + CONF_WIDTH[7:0] <= BUS_DATA_IN; + else if(BUS_ADD == 8) + CONF_WIDTH[15:8] <= BUS_DATA_IN; + else if(BUS_ADD == 9) + CONF_WIDTH[23:16] <= BUS_DATA_IN; + else if(BUS_ADD == 10) + CONF_WIDTH[31:24] <= BUS_DATA_IN; + else if(BUS_ADD == 11) + CONF_REPEAT[7:0] <= BUS_DATA_IN; + else if(BUS_ADD == 12) + CONF_REPEAT[15:8] <= BUS_DATA_IN; + else if(BUS_ADD == 13) + CONF_REPEAT[23:16] <= BUS_DATA_IN; + else if(BUS_ADD == 14) + CONF_REPEAT[31:24] <= BUS_DATA_IN; + else if(BUS_ADD == 15) + CONF_PHASE[7:0] <= BUS_DATA_IN; + else if(BUS_ADD == 16) + CONF_PHASE[15:8] <= BUS_DATA_IN; + end +end + +wire RST_SYNC; +wire RST_SOFT_SYNC; +cdc_pulse_sync rst_pulse_sync (.clk_in(BUS_CLK), .pulse_in(RST), .clk_out(PULSE_CLK), .pulse_out(RST_SOFT_SYNC)); +assign RST_SYNC = RST_SOFT_SYNC || BUS_RST; + + +wire START_SYNC; +cdc_pulse_sync start_pulse_sync (.clk_in(BUS_CLK), .pulse_in(START), .clk_out(PULSE_CLK), .pulse_out(START_SYNC)); + +wire EXT_START_SYNC; +reg [2:0] EXT_START_FF; +always @(posedge PULSE_CLK) // first stage +begin + EXT_START_FF[0] <= EXT_START; + EXT_START_FF[1] <= EXT_START_FF[0]; + EXT_START_FF[2] <= EXT_START_FF[1]; +end + +assign EXT_START_SYNC = !EXT_START_FF[2] & EXT_START_FF[1]; + +reg [31:0] CNT; +wire [32:0] LAST_CNT; +assign LAST_CNT = CONF_DELAY + CONF_WIDTH; + +reg [31:0] REAPAT_CNT; + +always @ (posedge PULSE_CLK) begin + if (RST_SYNC) + REAPAT_CNT <= 0; + else if(START_SYNC || (EXT_START_SYNC && CONF_EN)) + REAPAT_CNT <= CONF_REPEAT; + else if(REAPAT_CNT != 0 && CNT == 1) + REAPAT_CNT <= REAPAT_CNT - 1; +end + +always @ (posedge PULSE_CLK) begin + if (RST_SYNC) + CNT <= 0; //IS THIS RIGHT? + else if(START_SYNC || (EXT_START_SYNC && CONF_EN)) + CNT <= 1; + else if(CNT == LAST_CNT && REAPAT_CNT != 0) + CNT <= 1; + else if(CNT == LAST_CNT && CONF_REPEAT==0) + CNT <= 1; + else if(CNT == LAST_CNT && REAPAT_CNT == 0) + CNT <= 0; + else if(CNT != 0) + CNT <= CNT + 1; +end + +reg [CLKDV*4-1:0] PULSE_DES; +reg PULSE_REF; +always @ (posedge PULSE_CLK) begin + if(RST_SYNC || START_SYNC || (EXT_START_SYNC && CONF_EN)) begin + PULSE_DES <= 0; + PULSE_REF<=0; + end + else if(CNT == CONF_DELAY && CNT > 0) begin + PULSE_REF<=1; + PULSE_DES <= CONF_PHASE; + end + else if(CNT == CONF_DELAY+1) begin + PULSE_DES <= 16'b1111111111111111; + PULSE_REF<=1; + end + else if(CNT == LAST_CNT) begin + PULSE_DES <= 0; + PULSE_REF<=0; + end +end +assign DEBUG = PULSE_REF; +wire PULSE_CLK_PULSE; +reg [1:0] PULSE_CLK_FF; + +always @ (posedge PULSE_CLK160) + PULSE_CLK_FF[1:0] <= {PULSE_CLK_FF[0],PULSE_CLK}; +assign PULSE_CLK_PULSE = PULSE_CLK & ~PULSE_CLK_FF[0]; + +reg [CLKDV*4-1:0] PULSE_DES_DIV; +always @ (negedge PULSE_CLK160) begin + if(RST_SYNC || START_SYNC || (EXT_START_SYNC && CONF_EN)) + PULSE_DES_DIV <= 0; + else if (PULSE_CLK_PULSE==1) + PULSE_DES_DIV <= PULSE_DES; + else + PULSE_DES_DIV[CLKDV*4-2:0] <= {PULSE_DES_DIV[CLKDV*4-1],PULSE_DES_DIV[CLKDV*4-1], + PULSE_DES_DIV[CLKDV*4-1],PULSE_DES_DIV[CLKDV*4-1:4]}; +end + +genvar i; +generate +for (i=0; i`_ +`test_Timestamp640.py `_ +Pins + +---------------+---------------------+-----------------------+------------------------------------------------------+ + | Name | Size | Direction | Description | + +===============+=====================+=======================+======================================================+ + | EXT_ENABLE | 1 | input | active high accept DI signal (synchronous to PULSE_CLK) | + +---------------+---------------------+-----------------------+----------------------------------------------------------+ + | CLK | 1 | input | module clock | + +---------------+---------------------+-----------------------+----------------------------------------------------------+ + | CLK160 | 1 | input | module clock (CLK x 4) | + +---------------+---------------------+-----------------------+----------------------------------------------------------+ + | CLK320 | 1 | input | module clock (CLK x 8) | + +---------------+---------------------+-----------------------+----------------------------------------------------------+ + | DI | 1 | input | input signal | + +---------------+---------------------+-----------------------+----------------------------------------------------------+ + | EXT_TIMESTMP | 1 | input | external timestamp timestamp pulse | | + +---------------+---------------------+-----------------------+----------------------------------------------------------+ + +Registers + +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ + | Name | Address | Bits | r/w | Default | Description | + +===============+==================================+========+=======+=============+============================================================================================+ + | EN | 2 | [0] | r/w | | enable module | + +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ + | EXT_TIMESTMP | 2 | [1] | r/w | 0 | use external timestamp | + +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ + | EXT_ENABLE | 2 | [2] | r/w | 0 | enable external start | + +---------------+----------------------------------+--------+-------+-------------+--------------------------------------------------------------------------------------------+ diff --git a/basil/firmware/modules/timestamp640/timestamp640.v b/basil/firmware/modules/timestamp640/timestamp640.v new file mode 100644 index 000000000..5f8864735 --- /dev/null +++ b/basil/firmware/modules/timestamp640/timestamp640.v @@ -0,0 +1,94 @@ +/** + * ------------------------------------------------------------ + * Copyright (c) All rights reserved + * SiLab, Institute of Physics, University of Bonn + * ------------------------------------------------------------ + */ +`timescale 1ps/1ps +`default_nettype none + +module timestamp640 +#( + parameter BASEADDR = 16'h0000, + parameter HIGHADDR = 16'h0000, + parameter ABUSWIDTH = 16, + parameter IDENTIFIER = 4'b0001, + parameter CLKDV = 4 +)( + input wire BUS_CLK, + input wire [ABUSWIDTH-1:0] BUS_ADD, + inout wire [7:0] BUS_DATA, + input wire BUS_RST, + input wire BUS_WR, + input wire BUS_RD, + + input wire CLK320, + input wire CLK160, + input wire CLK40, + input wire DI, + input wire [63:0] EXT_TIMESTAMP, + output wire [63:0] TIMESTAMP_OUT, + input wire EXT_ENABLE, + + input wire FIFO_READ, + output wire FIFO_EMPTY, + output wire [31:0] FIFO_DATA, + + input wire FIFO_READ_TRAILING, + output wire FIFO_EMPTY_TRAILING, + output wire [31:0] FIFO_DATA_TRAILING + +); + +wire IP_RD, IP_WR; +wire [ABUSWIDTH-1:0] IP_ADD; +wire [7:0] IP_DATA_IN; +wire [7:0] IP_DATA_OUT; + +bus_to_ip #( .BASEADDR(BASEADDR), .HIGHADDR(HIGHADDR), .ABUSWIDTH(ABUSWIDTH) ) i_bus_to_ip +( + .BUS_RD(BUS_RD), + .BUS_WR(BUS_WR), + .BUS_ADD(BUS_ADD), + .BUS_DATA(BUS_DATA), + + .IP_RD(IP_RD), + .IP_WR(IP_WR), + .IP_ADD(IP_ADD), + .IP_DATA_IN(IP_DATA_IN), + .IP_DATA_OUT(IP_DATA_OUT) +); + +timestamp640_core +#( + .ABUSWIDTH(ABUSWIDTH), + .IDENTIFIER(IDENTIFIER), + .CLKDV(4) +) i_timestamp640_core +( + .BUS_CLK(BUS_CLK), + .BUS_RST(BUS_RST), + .BUS_ADD(IP_ADD), + .BUS_DATA_IN(IP_DATA_IN), + .BUS_RD(IP_RD), + .BUS_WR(IP_WR), + .BUS_DATA_OUT(IP_DATA_OUT), + + .CLK320(CLK320), + .CLK160(CLK160), + .CLK40(CLK40), + .DI(DI), + .TIMESTAMP_OUT(TIMESTAMP_OUT), + .EXT_TIMESTAMP(EXT_TIMESTAMP), + .EXT_ENABLE(EXT_ENABLE), + + .FIFO_READ(FIFO_READ), + .FIFO_EMPTY(FIFO_EMPTY), + .FIFO_DATA(FIFO_DATA), + + .FIFO_READ_TRAILING(FIFO_READ_TRAILING), + .FIFO_EMPTY_TRAILING(FIFO_EMPTY_TRAILING), + .FIFO_DATA_TRAILING(FIFO_DATA_TRAILING) +); + +endmodule diff --git a/basil/firmware/modules/timestamp640/timestamp640_core.v b/basil/firmware/modules/timestamp640/timestamp640_core.v new file mode 100644 index 000000000..0a7f3bf87 --- /dev/null +++ b/basil/firmware/modules/timestamp640/timestamp640_core.v @@ -0,0 +1,328 @@ +/** + * ------------------------------------------------------------ + * Copyright (c) All rights reserved + * SiLab, Institute of Physics, University of Bonn + * ------------------------------------------------------------ + */ +`timescale 1ps/1ps +`default_nettype none + +module timestamp640_core +#( + parameter ABUSWIDTH = 16, + parameter IDENTIFIER = 4'b0001, + parameter CLKDV = 4 +)( + input wire BUS_CLK, + input wire [ABUSWIDTH-1:0] BUS_ADD, + input wire [7:0] BUS_DATA_IN, + output reg [7:0] BUS_DATA_OUT, + input wire BUS_RST, + input wire BUS_WR, + input wire BUS_RD, + + input wire CLK320, + input wire CLK160, + input wire CLK40, + input wire DI, + input wire EXT_ENABLE, + input wire [63:0] EXT_TIMESTAMP, + output wire [63:0] TIMESTAMP_OUT, + + input wire FIFO_READ, + output wire FIFO_EMPTY, + output wire [31:0] FIFO_DATA, + + input wire FIFO_READ_TRAILING, + output wire FIFO_EMPTY_TRAILING, + output wire [31:0] FIFO_DATA_TRAILING +); + +localparam VERSION = 3; + +//output format: +//31-28: ID, 27-24: 0x1, 23-0: 23-0th bit of timestamp data +//31-28: ID, 27-24: 0x2, 23-0: 47-24th bit of timestamp data +//31-28: ID, 27-24: 0x3, 23-8: tot 7-0: 55-48th bit of timestamp data + +wire SOFT_RST; +assign SOFT_RST = (BUS_ADD==0 && BUS_WR); + +wire RST; +assign RST = BUS_RST | SOFT_RST; + +reg CONF_EN, CONF_EXT_ENABLE; +reg CONF_EXT_TIMESTAMP,CONF_EN_TRAILING,CONF_EN_INVERT; +reg [7:0] LOST_DATA_CNT; + +always @(posedge BUS_CLK) begin + if(RST) begin + CONF_EN <= 0; + CONF_EXT_TIMESTAMP <=0; + CONF_EXT_ENABLE <= 0; + CONF_EN_TRAILING <=0; + CONF_EN_INVERT <=0; + end + else if(BUS_WR) begin + if(BUS_ADD == 2) + CONF_EN <= BUS_DATA_IN[0]; + CONF_EXT_TIMESTAMP <=BUS_DATA_IN[1]; + CONF_EXT_ENABLE <=BUS_DATA_IN[2]; + CONF_EN_TRAILING <=BUS_DATA_IN[3]; + CONF_EN_INVERT <=BUS_DATA_IN[4]; + end +end + +always @(posedge BUS_CLK) begin + if(BUS_RD) begin + if(BUS_ADD == 0) + BUS_DATA_OUT <= VERSION; + else if(BUS_ADD == 2) + BUS_DATA_OUT <= {3'b0,CONF_EN_INVERT, + CONF_EN_TRAILING,CONF_EXT_ENABLE,CONF_EXT_TIMESTAMP,CONF_EN}; + else if(BUS_ADD == 3) + BUS_DATA_OUT <= LOST_DATA_CNT; + else + BUS_DATA_OUT <= 8'b0; + end +end + +wire RST_SYNC; +wire RST_SOFT_SYNC; +cdc_pulse_sync rst_pulse_sync (.clk_in(BUS_CLK), .pulse_in(RST), .clk_out(CLK40), .pulse_out(RST_SOFT_SYNC)); +assign RST_SYNC = RST_SOFT_SYNC || BUS_RST; +wire EN_SYNC; +assign EN_SYNC= CONF_EN | ( EXT_ENABLE & CONF_EXT_ENABLE); + + +reg [7:0] sync_cnt; +always@(posedge BUS_CLK) begin + if(RST) + sync_cnt <= 120; + else if(sync_cnt != 100) + sync_cnt <= sync_cnt +1; +end +wire RST_LONG; +assign RST_LONG = sync_cnt[7]; + +reg [63:0] INT_TIMESTAMP; +wire [63:0] TIMESTAMP; +always@(posedge CLK40) begin + if(RST_SYNC) + INT_TIMESTAMP <= 0; + else + INT_TIMESTAMP <= INT_TIMESTAMP + 1; +end +assign TIMESTAMP = CONF_EXT_TIMESTAMP ? EXT_TIMESTAMP: INT_TIMESTAMP; + +// de-serialize +wire [CLKDV*4-1:0] TDC, TDC_DES; +reg [CLKDV*4-1:0] TDC_DES_PREV; + +ddr_des #(.CLKDV(CLKDV)) iddr_des_tdc(.CLK2X(CLK320), .CLK(CLK160), .WCLK(CLK40), .IN(DI), .OUT(TDC), .OUT_FAST()); + +assign TDC_DES = CONF_EN_INVERT ? ~TDC : TDC; + +always @ (posedge CLK40) + TDC_DES_PREV <= TDC_DES; + +wire [CLKDV*4:0] TDC_TO_COUNT; +assign TDC_TO_COUNT[CLKDV*4] = TDC_DES_PREV[0]; +assign TDC_TO_COUNT[CLKDV*4-1:0] = TDC_DES; + +reg [3:0] RISING_EDGES_CNT, FALLING_EDGES_CNT; +reg [3:0] RISING_POS, FALLING_POS; + +integer i; +always @ (*) begin + FALLING_EDGES_CNT = 0; + RISING_EDGES_CNT = 0; + RISING_POS = 0; + FALLING_POS = 0; + for (i=0; i<16; i=i+1) begin + if ((TDC_TO_COUNT[16-i-1] == 1) && (TDC_TO_COUNT[16-i]==0)) begin + if (RISING_EDGES_CNT == 0) + RISING_POS = i; + + RISING_EDGES_CNT = RISING_EDGES_CNT + 1; + end + + if ((TDC_TO_COUNT[i] == 0) && (TDC_TO_COUNT[i+1]==1)) begin + if (FALLING_EDGES_CNT == 0) + FALLING_POS = 15 - i; + + FALLING_EDGES_CNT = FALLING_EDGES_CNT + 1; + end + end +end + +reg WAITING_FOR_TRAILING; +always@(posedge CLK40) + if(RST) + WAITING_FOR_TRAILING <= 0; + else if(RISING_EDGES_CNT < FALLING_EDGES_CNT) + WAITING_FOR_TRAILING <= 0; + else if( (RISING_EDGES_CNT > FALLING_EDGES_CNT) & EN_SYNC) + WAITING_FOR_TRAILING <= 1; + +reg [67:0] LAST_RISING; +always@(posedge CLK40) + if(RST) + LAST_RISING <= 0; + else if (RISING_EDGES_CNT > 0 ) + LAST_RISING <= {TIMESTAMP, RISING_POS}; + +reg [67:0] LAST_FALLING; +always@(posedge CLK40) + if(RST) + LAST_FALLING <= 0; + else if (FALLING_EDGES_CNT > 0) + LAST_FALLING <= {TIMESTAMP, FALLING_POS}; + +wire RISING; +assign RISING = (RISING_EDGES_CNT > 0 & EN_SYNC ); + +wire FALLING; +assign FALLING = (FALLING_EDGES_CNT > 0 & CONF_EN_TRAILING & EN_SYNC ); + +reg [2:0] FALLING_FF; +reg [2:0] RISING_FF; +wire FALLING_SYNC; +wire RISING_SYNC; +always@(posedge CLK40) + if(RST) begin + FALLING_FF <= 3'b0; + RISING_FF <= 3'b0; + end + else begin + FALLING_FF <= {FALLING_FF[1:0], FALLING}; + RISING_FF <= {RISING_FF[1:0], RISING}; + end +assign RISING_SYNC = RISING_FF[0] & ~RISING_FF[1]; +assign FALLING_SYNC = FALLING_FF[0] & ~FALLING_FF[1]; + +wire [71:0] cdc_data_in; +assign cdc_data_in = {4'b0,LAST_RISING} ; +wire [71:0] cdc_data_in_f; +assign cdc_data_in_f = {4'b0,LAST_FALLING} ; + +wire cdc_fifo_write; +assign cdc_fifo_write = RISING_SYNC ; +wire cdc_fifo_write_f; +assign cdc_fifo_write_f = CONF_EN_TRAILING ? FALLING_SYNC: 1'b0; + +wire fifo_full,fifo_write,cdc_fifo_empty; +wire fifo_full_f,fifo_write_f,cdc_fifo_empty_f; +wire wfull,wfull_f; +always@(posedge CLK40) begin + if(RST_SYNC) + LOST_DATA_CNT <= 0; + else if (wfull && cdc_fifo_write && LOST_DATA_CNT != -1) + LOST_DATA_CNT <= LOST_DATA_CNT +1; + else if (wfull_f && cdc_fifo_write_f && LOST_DATA_CNT != -1) + LOST_DATA_CNT <= LOST_DATA_CNT +1; +end + +////////////// write fifo (rising) +wire [71:0] cdc_data_out; +wire cdc_fifo_read; +cdc_syncfifo +#(.DSIZE(72), .ASIZE(8)) + cdc_syncfifo_i +( + .rdata(cdc_data_out), + .wfull(wfull), + .rempty(cdc_fifo_empty), + .wdata(cdc_data_in), + .winc(cdc_fifo_write), .wclk(CLK40), .wrst(RST_LONG), + .rinc(cdc_fifo_read), .rclk(BUS_CLK), .rrst(RST_LONG) +); + +reg [1:0] byte2_cnt, byte2_cnt_prev; +always@(posedge BUS_CLK) + byte2_cnt_prev <= byte2_cnt; +assign cdc_fifo_read = (byte2_cnt_prev==0 & byte2_cnt!=0); +assign fifo_write = byte2_cnt_prev != 0; + +always@(posedge BUS_CLK) + if(RST) + byte2_cnt <= 0; + else if(!cdc_fifo_empty && !fifo_full && byte2_cnt == 0 ) + byte2_cnt <= 3; + else if (!fifo_full & byte2_cnt != 0) + byte2_cnt <= byte2_cnt - 1; + +reg [71:0] data_buf; +always@(posedge BUS_CLK) + if(cdc_fifo_read) + data_buf <= cdc_data_out; + +wire [31:0] fifo_write_data_byte [3:0]; +assign fifo_write_data_byte[0]={IDENTIFIER,4'b0001,data_buf[23:0]}; +assign fifo_write_data_byte[1]={IDENTIFIER,4'b0010,data_buf[47:24]}; +assign fifo_write_data_byte[2]={IDENTIFIER,4'b0011,data_buf[71:48]}; +wire [31:0] fifo_data_in; +assign fifo_data_in = fifo_write_data_byte[byte2_cnt]; + +gerneric_fifo #(.DATA_SIZE(32), .DEPTH(1024)) fifo_i +( .clk(BUS_CLK), .reset(RST_LONG | BUS_RST), + .write(fifo_write), + .read(FIFO_READ), + .data_in(fifo_data_in), + .full(fifo_full), + .empty(FIFO_EMPTY), + .data_out(FIFO_DATA[31:0]), .size() +); + +////////////// write fifo (falling) +wire [71:0] cdc_data_out_f; +wire cdc_fifo_read_f; +cdc_syncfifo +#(.DSIZE(72), .ASIZE(8)) + cdc_syncfifo_i_f +( + .rdata(cdc_data_out_f), + .wfull(wfull_f), + .rempty(cdc_fifo_empty_f), + .wdata(cdc_data_in_f), + .winc(cdc_fifo_write_f), .wclk(CLK40), .wrst(RST_LONG), + .rinc(cdc_fifo_read_f), .rclk(BUS_CLK), .rrst(RST_LONG) +); + +reg [1:0] byte2_cnt_f, byte2_cnt_prev_f; +always@(posedge BUS_CLK) + byte2_cnt_prev_f <= byte2_cnt_f; +assign cdc_fifo_read_f = (byte2_cnt_prev_f==0 & byte2_cnt_f!=0); +assign fifo_write_f = byte2_cnt_prev_f != 0; + +always@(posedge BUS_CLK) + if(RST) + byte2_cnt_f <= 0; + else if(!cdc_fifo_empty_f && !fifo_full_f && byte2_cnt_f == 0 ) + byte2_cnt_f <= 3; + else if (!fifo_full_f & byte2_cnt_f != 0) + byte2_cnt_f <= byte2_cnt_f - 1; + +reg [71:0] data_buf_f; +always@(posedge BUS_CLK) + if(cdc_fifo_read_f) + data_buf_f <= cdc_data_out_f; + +wire [31:0] fifo_write_data_byte_f [3:0]; +assign fifo_write_data_byte_f[0]={IDENTIFIER,4'b0101,data_buf_f[23:0]}; +assign fifo_write_data_byte_f[1]={IDENTIFIER,4'b0110,data_buf_f[47:24]}; +assign fifo_write_data_byte_f[2]={IDENTIFIER,4'b0111,data_buf_f[71:48]}; +wire [31:0] fifo_data_in_f; +assign fifo_data_in_f = fifo_write_data_byte_f[byte2_cnt_f]; + +gerneric_fifo #(.DATA_SIZE(32), .DEPTH(1024)) fifo_i_f +( .clk(BUS_CLK), .reset(RST_LONG | BUS_RST), + .write(fifo_write_f), + .read(FIFO_READ_TRAILING), + .data_in(fifo_data_in_f), + .full(fifo_full_f), + .empty(FIFO_EMPTY_TRAILING), + .data_out(FIFO_DATA_TRAILING[31:0]), .size() +); + +endmodule diff --git a/basil/firmware/modules/utils/OSERDESE2_sim.v b/basil/firmware/modules/utils/OSERDESE2_sim.v new file mode 100644 index 000000000..574c82b57 --- /dev/null +++ b/basil/firmware/modules/utils/OSERDESE2_sim.v @@ -0,0 +1,54 @@ +/** + * ------------------------------------------------------------ + * Copyright (c) All rights reserved + * SiLab, Institute of Physics, University of Bonn + * ------------------------------------------------------------ + */ +`timescale 1ps/1ps +`default_nettype none + +module OSERDESE2 +#( + parameter DATA_RATE_OQ = "DDR", + parameter DATA_WIDTH = 4, + parameter SERDES_MODE = "MASTER" +)( + output wire OQ, + output wire OFB, + input wire TQ, + input wire TFB, + input wire SHIFTOUT1, + input wire SHIFTOUT2, + input wire CLK, + input wire CLKDIV, + input wire D1, + input wire D2, + input wire D3, + input wire D4, + input wire D5, + input wire D6, + input wire D7, + input wire D8, + input wire TCE, + input wire OCE, + input wire TBYTEIN, + input wire TBYTEOUT, + input wire RST, + input wire SHIFTIN1, + input wire SHIFTIN2, + input wire T1, + input wire T2, + input wire T3, + input wire T4 +); +reg OQ_reg; +always@(posedge CLKDIV) begin + if (RST) + OQ_reg <= 1'b0; + else + OQ_reg <= 1'b1; //TODO implement phase +end +assign OFB = 1'b0; +assign OQ = OQ_reg; + +endmodule \ No newline at end of file diff --git a/tests/test_SimTimestamp640.py b/tests/test_SimTimestamp640.py new file mode 100644 index 000000000..15dd173d7 --- /dev/null +++ b/tests/test_SimTimestamp640.py @@ -0,0 +1,122 @@ +# +# ------------------------------------------------------------ +# Copyright (c) All rights reserved +# SiLab, Institute of Physics, University of Bonn +# ------------------------------------------------------------ +# + +import unittest +import os + +from basil.dut import Dut +from basil.utils.sim.utils import cocotb_compile_and_run, cocotb_compile_clean + + +cnfg_yaml = """ +transfer_layer: + - name : intf + type : SiSim + init: + host : localhost + port : 12345 + +hw_drivers: + - name : gpio + type : gpio + interface : intf + base_addr : 0x0000 + size : 64 + + - name : timestamp640 + type : timestamp640 + interface : intf + base_addr : 0x1000 + + + - name : pulse_gen640 + type : pulse_gen640 + interface : intf + base_addr : 0x3000 + + - name : fifo + type : sram_fifo + interface : intf + base_addr : 0x8000 + base_data_addr: 0x80000000 + +registers: + - name : timestamp_value + type : StdRegister + hw_driver : gpio + size : 64 + fields: + - name : OUT3 + size : 16 + offset : 63 + - name : OUT2 + size : 24 + offset : 47 + - name : OUT1 + size : 24 + offset : 23 +""" + + +class TestSimTimestamp(unittest.TestCase): + def setUp(self): + cocotb_compile_and_run([os.path.join(os.path.dirname(__file__), 'test_SimTimestamp640.v')]) + + self.chip = Dut(cnfg_yaml) + self.chip.init() + + def test_io(self): + self.chip['timestamp640'].reset() + self.chip['timestamp640']["ENABLE"] = 1 + self.chip['gpio'].reset() + + self.chip['fifo'].reset() + ret = self.chip['fifo'].get_fifo_size() + self.assertEqual(ret, 0) + + # trigger timestamp + self.chip['pulse_gen640'].set_delay(0x105) + self.chip['pulse_gen640'].set_width(10) + self.chip['pulse_gen640'].set_repeat(1) + self.chip['pulse_gen640'].set_phase(0) + self.assertEqual(self.chip['pulse_gen640'].get_delay(), 0x105) + self.assertEqual(self.chip['pulse_gen640'].get_width(), 10) + self.assertEqual(self.chip['pulse_gen640'].get_repeat(), 1) + # self.assertEqual(self.chip['pulse_gen640'].get_phase(), 0) + + # self.chip['pulse_gen640'].start() + # while(not self.chip['pulse_gen640'].is_done()): + # pass + + # # get data from fifo + # ret = self.chip['fifo'].get_fifo_size() + # self.assertEqual(ret, 3 * 4) + + # ret = self.chip['fifo'].get_data() + # self.assertEqual(len(ret), 3) + + # # check with gpio + # ret2 = self.chip['gpio'].get_data() + # self.assertEqual(len(ret2), 8) + + # for i, r in enumerate(ret): + # self.assertEqual(r & 0xF0000000, 0x50000000) + # self.assertEqual(r & 0xF000000, 0x1000000 * (3 - i)) + + # self.assertEqual(ret[2] & 0xFFFFFF, 0x10000 * + # ret2[5] + 0x100 * ret2[6] + ret2[7]) + # self.assertEqual(ret[1] & 0xFFFFFF, 0x10000 * + # ret2[2] + 0x100 * ret2[3] + ret2[4]) + # self.assertEqual(ret[1] & 0xFFFFFF, 0x100 * ret2[0] + ret2[1]) + + def tearDown(self): + self.chip.close() # let it close connection and stop simulator + cocotb_compile_clean() + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_SimTimestamp640.v b/tests/test_SimTimestamp640.v new file mode 100644 index 000000000..139451485 --- /dev/null +++ b/tests/test_SimTimestamp640.v @@ -0,0 +1,189 @@ +/** + * ------------------------------------------------------------ + * Copyright (c) All rights reserved + * SiLab, Institute of Physics, University of Bonn + * ------------------------------------------------------------ + */ + +`timescale 1ps / 1ps + +`include "utils/bus_to_ip.v" +`include "gpio/gpio_core.v" +`include "gpio/gpio.v" + +`include "pulse_gen640/pulse_gen640.v" +`include "pulse_gen640/pulse_gen640_core.v" +`include "utils/clock_multiplier.v" +`include "utils/DCM_sim.v" + +`include "bram_fifo/bram_fifo_core.v" +`include "bram_fifo/bram_fifo.v" + +`include "timestamp640/timestamp640.v" +`include "timestamp640/timestamp640_core.v" + +`include "utils/cdc_syncfifo.v" +`include "utils/generic_fifo.v" +`include "utils/cdc_pulse_sync.v" +`include "utils/CG_MOD_pos.v" +`include "utils/clock_divider.v" +`include "utils/3_stage_synchronizer.v" +`include "utils/RAMB16_S1_S9_sim.v" +`include "utils/ddr_des.v" +`include "utils/IDDR_sim.v" +`include "utils/OSERDESE2_sim.v" + +module tb ( + input wire BUS_CLK, + input wire BUS_RST, + input wire [31:0] BUS_ADD, + inout wire [31:0] BUS_DATA, + input wire BUS_RD, + input wire BUS_WR, + output wire BUS_BYTE_ACCESS +); + +// MODULE ADREESSES // +localparam GPIO_BASEADDR = 32'h0000; +localparam GPIO_HIGHADDR = 32'h1000-1; + +localparam TIMESTAMP_BASEADDR = 32'h1000; //0x1000 +localparam TIMESTAMP_HIGHADDR = 32'h2000-1; //0x300f + + +localparam PULSE_BASEADDR = 32'h3000; +localparam PULSE_HIGHADDR = PULSE_BASEADDR + 15; + +localparam FIFO_BASEADDR = 32'h8000; +localparam FIFO_HIGHADDR = 32'h9000-1; + +localparam FIFO_BASEADDR_DATA = 32'h8000_0000; +localparam FIFO_HIGHADDR_DATA = 32'h9000_0000; + +localparam ABUSWIDTH = 32; +assign BUS_BYTE_ACCESS = BUS_ADD < 32'h8000_0000 ? 1'b1 : 1'b0; + +// MODULES // +wire CLK640,CLK320,CLK160,CLK40,CLK320_TO_DCM; + +DCM #( + .CLKFX_MULTIPLY(40), + .CLKFX_DIVIDE(3) +) i_dcm_1 ( + .CLK0(), .CLK180(), .CLK270(), .CLK2X(), .CLK2X180(), .CLK90(), + .CLKDV(), .CLKFX(CLK320_TO_DCM), .CLKFX180(), .LOCKED(), .PSDONE(), .STATUS(), + .CLKFB(1'b0), .CLKIN(BUS_CLK), .DSSEN(1'b0), .PSCLK(1'b0), .PSEN(1'b0), .PSINCDEC(1'b0), .RST(1'b0) +); + +DCM #( + .CLKFX_MULTIPLY(1), + .CLKFX_DIVIDE(2), + .CLKDV_DIVIDE(8) +) i_dcm_2 ( + .CLK0(CLK320), .CLK180(), .CLK270(), .CLK2X(CLK640), .CLK2X180(), .CLK90(), + .CLKDV(CLK40), .CLKFX(CLK160), .CLKFX180(), .LOCKED(), .PSDONE(), .STATUS(), + .CLKFB(1'b0), .CLKIN(CLK320_TO_DCM), .DSSEN(1'b0), .PSCLK(1'b0), .PSEN(1'b0), .PSINCDEC(1'b0), .RST(1'b0) +); + +reg [63:0] TIMESTAMP; +wire [63:0] TIMESTAMP_OUT; +gpio #( + .BASEADDR(GPIO_BASEADDR), + .HIGHADDR(GPIO_HIGHADDR), + .ABUSWIDTH(ABUSWIDTH), + .IO_WIDTH(64), + .IO_DIRECTION(64'h0) +) i_gpio ( + .BUS_CLK(BUS_CLK), + .BUS_RST(BUS_RST), + .BUS_ADD(BUS_ADD), + .BUS_DATA(BUS_DATA[7:0]), + .BUS_RD(BUS_RD), + .BUS_WR(BUS_WR), + .IO(TIMESTAMP_OUT) +); + +wire PULSE; +pulse_gen640 #( + .BASEADDR(PULSE_BASEADDR), + .HIGHADDR(PULSE_HIGHADDR), + .ABUSWIDTH(ABUSWIDTH), + .OUTPUT_SIZE(1) +) i_pulse_gen ( + .BUS_CLK(BUS_CLK), + .BUS_RST(BUS_RST), + .BUS_ADD(BUS_ADD), + .BUS_DATA(BUS_DATA[7:0]), + .BUS_RD(BUS_RD), + .BUS_WR(BUS_WR), + + .PULSE_CLK(CLK40), + .PULSE_CLK160(CLK160), + .PULSE_CLK320(CLK320), + .EXT_START(1'b0), + .PULSE(PULSE) +); + +always @(posedge CLK40) + TIMESTAMP <= TIMESTAMP + 1; + +wire FIFO_READ, FIFO_EMPTY; +wire [31:0] FIFO_DATA; +wire EXT_ENABLE; +assign EXT_ENABLE = 1'b0; +timestamp640 #( + .BASEADDR(TIMESTAMP_BASEADDR), + .HIGHADDR(TIMESTAMP_HIGHADDR), + .ABUSWIDTH(ABUSWIDTH), + .IDENTIFIER(4'b0101) +) i_timestamp ( + .BUS_CLK(BUS_CLK), + .BUS_RST(BUS_RST), + .BUS_ADD(BUS_ADD), + .BUS_DATA(BUS_DATA[7:0]), + .BUS_RD(BUS_RD), + .BUS_WR(BUS_WR), + + .CLK320(CLK320), + .CLK160(CLK160), + .CLK40(CLK40), + .DI(PULSE), + .EXT_TIMESTAMP(TIMESTAMP), + .TIMESTAMP_OUT(TIMESTAMP_OUT), + .EXT_ENABLE(EXT_ENABLE), + + .FIFO_READ(FIFO_READ), + .FIFO_EMPTY(FIFO_EMPTY), + .FIFO_DATA(FIFO_DATA) +); + +bram_fifo #( + .BASEADDR(FIFO_BASEADDR), + .HIGHADDR(FIFO_HIGHADDR), + .BASEADDR_DATA(FIFO_BASEADDR_DATA), + .HIGHADDR_DATA(FIFO_HIGHADDR_DATA), + .ABUSWIDTH(ABUSWIDTH) +) i_out_fifo ( + .BUS_CLK(BUS_CLK), + .BUS_RST(BUS_RST), + .BUS_ADD(BUS_ADD), + .BUS_DATA(BUS_DATA), + .BUS_RD(BUS_RD), + .BUS_WR(BUS_WR), + + .FIFO_READ_NEXT_OUT(FIFO_READ), + .FIFO_EMPTY_IN(FIFO_EMPTY), + .FIFO_DATA(FIFO_DATA), + + .FIFO_NOT_EMPTY(), + .FIFO_FULL(), + .FIFO_NEAR_FULL(), + .FIFO_READ_ERROR() +); + +initial begin + $dumpfile("timestamp640.vcd"); + $dumpvars(0); +end + +endmodule