`timescale 1ns / 1ps

`include "src/eth/eth_mac.v"
`include "src/del_meas/del_meas_cdc.v"

module jitmeas_top(
	input clk50, clk200, rst, clear,
	
	input [2:0] btn,
	output [7:0] leds,
	input [7:0] sw,
	
	//input [1:0] RXD,
	//input CRS_DV,
	output [1:0] TXD,
	output TXEN,
	
	input sig, ref
);

/* configuration */
localparam MEM_DATA_WIDTH = 8;	// Memory word size
localparam MEM_ADDR_WIDTH = 12;	// Memory address size
localparam DM_WIDTH = 7;        	// Width of the delay measurement counter 
localparam FRAME_LENGTH = 2;		// Frame payload size

/* LEDs and switches */
assign leds = {sig_synced, ref_synced, pckt_full, pckt_empty, dm_state, dm_enable};

/* SIG and REF signals synchronized to the default domain */
wire sig_synced, ref_synced;

cdc sig_jm_cdc (
	.tclk(clk50),
	.rst(rst),
	.sin(sig),
	.tout(sig_synced)
);

cdc ref_jm_cdc (
	.tclk(clk50),
	.rst(rst),
	.sin(ref),
	.tout(ref_synced)
);

/* Data stream memory */
wire [MEM_DATA_WIDTH-1:0] stream_mem_data;
wire [MEM_ADDR_WIDTH-1:0] stream_mem_addr;
wire stream_mem_wea;
wire [MEM_ADDR_WIDTH-1:0] stream_mem_addra;
wire [MEM_DATA_WIDTH-1:0] stream_mem_dina;

StreamMemory stream_mem (
	/* PORT A */
  .clka(clk50), 					// input clka
  
  .wea(stream_mem_wea), 		// input [0 : 0] wea
  .addra(stream_mem_addra), 	// input [10 : 0] addra
  .dina(stream_mem_dina), 		// input [15 : 0] dina

	/* PORT B */
  .clkb(clk50), 					// input clkb
  .rstb(rst), 						// input rstb
  .addrb(stream_mem_addr), 	// input [11 : 0] addrb
  .doutb(stream_mem_data) 		// output [7 : 0] doutb
);

/* Ethernet MAC */
wire [31:0] mac_ctrl_word;

eth_mac #(
	.MEM_DATA_WIDTH(MEM_DATA_WIDTH),
	.MEM_ADDR_WIDTH(MEM_ADDR_WIDTH)
) eth_mac_inst (
    .clk(clk50), 
    .rst(rst),
	 .clear(1'b0),
	 
	 .mem_data(stream_mem_data),
	 .mem_addr(stream_mem_addr),
	 
	 .ctrl_word(mac_ctrl_word),
	 
	 .TXEN(TXEN),
	 .TXD(TXD)
);

/* transmission scheduler and packetizer */ 
reg [MEM_DATA_WIDTH-1:0] pckt_data_in;
wire pckt_wrt;
wire pckt_immtx;
wire pckt_empty;
wire pckt_full;

packetizer #(
	.MEM_WRITE_WIDTH(MEM_DATA_WIDTH),
	.MEM_DEPTH_BYTE(2**MEM_ADDR_WIDTH)
) tx_packetizer (
	.clk(clk50),
	.rst(rst),
	.clear(clear),
	
	.mac_ctrl_word(mac_ctrl_word),
	
	.data_in(pckt_data_in),
	.wrt(pckt_wrt),
	
	.mem_wea(stream_mem_wea),
	.mem_data(stream_mem_dina),
	.mem_addr(stream_mem_addra),
	
	.immtx(pckt_immtx),
	.empty(pckt_empty),
	.full(pckt_full)
);

clkdiv #(
	.DIV(25000000)
) pckt_tx_sched (
	.clk(clk50),
	.rst(rst),
	.clear(clear),
	
	.sclk(),
	.pos(pckt_immtx),
	.neg()
);

/* button handling */
reg [2:0] btn_prev;
always @(posedge clk50)
begin
	if (rst | clear)
	begin
		btn_prev <= 0;
	end
	else
	begin
		btn_prev <= btn;
	end
end

//reg mac_transmit;
//assign mac_ctrl_word[30:0] = 31'b0 | (FRAME_LENGTH << MEM_ADDR_WIDTH) | (0);
//assign mac_ctrl_word[31] = (~btn_prev[0] && btn[0]) | mac_transmit;

/* measurement handling */
wire dm_start = ~btn_prev[1] && btn[1];
wire dm_enable = sw[0];

reg dm_arm;
wire dm_done;
reg dm_ack;
wire [2:0] dm_state;
wire dm_negative;
wire [DM_WIDTH-1:0] dm_delay;

del_meas_cdc #(
	.WIDTH(DM_WIDTH)
) del_meas_inst (
	.clkMeas(clk200),
	.clkIntf(clk50),
	.rst(rst),
	.clear(clear),
	
	.ref(ref),
	.sig(sig),
	
	.arm(dm_arm),
	.listening(),
	.done(dm_done),
	.ack(dm_ack),
	
	.negative(dm_negative),
	.delay(dm_delay),
	
	.state_dbg(dm_state)
);

/* measurement data handling */

// convert delay to a signed value
wire [DM_WIDTH:0] signed_delay = dm_negative ? (~({1'b0, dm_delay} + 1'b1)) : {1'b0, dm_delay};

reg dm_done_prev;
assign pckt_wrt = dm_done && !dm_done_prev;

always @(posedge clk50)
begin
	if (rst)
	begin
		pckt_data_in <= 0;

		dm_done_prev <= 0;
		dm_ack <= 0;
		dm_arm <= 0;
	end
	else
	begin
		// retain states
		dm_done_prev <= dm_done;
	
		// measurement done
		if (dm_done)
		begin
			pckt_data_in <= signed_delay;
			
			dm_ack <= 1;
		end
		else
		begin
			dm_ack <= 0;
			dm_arm <= 0;
		end
		
		// start button is pressed
		if (dm_start)
		begin
			dm_arm <= 1;
		end
		
		// -----------------
		
		// data is written to the memory
		if (pckt_wrt)
		begin
			if (dm_enable)
			begin
				dm_arm <= 1;
			end
		end
	end
end




endmodule
