

module new_tx_control
  #(parameter BASE=0)
   (input clk, input reset, input clear,
    input set_stb, input [7:0] set_addr, input [31:0] set_data,

    input [63:0] vita_time,
    output reg ack_or_error,
    output packet_consumed,
    output [11:0] seqnum,
    output reg [63:0] error_code,
    output [31:0] sid,

    // From tx_deframer
    input [175:0] sample_tdata,
    input sample_tvalid,
    output sample_tready,

    // To DSP Core
    output [31:0] sample,
    output run,    input strobe,

    output [31:0] debug
    );

   wire [31:0] 	  sample1 = sample_tdata[31:0];
   wire [31:0] 	  sample0 = sample_tdata[63:32];
   wire [63:0] 	  send_time = sample_tdata[127:64];
   assign         sid = sample_tdata[159:128];
   assign 	  seqnum = sample_tdata[171:160];
   wire 	  eop = sample_tdata[172];
   wire 	  eob = sample_tdata[173];
   wire 	  send_at = sample_tdata[174];
   wire 	  odd = sample_tdata[175];

   wire 	  now, early, late, too_early;
   wire 	  policy_next_burst, policy_next_packet, policy_wait;
   wire 	  clear_seqnum;

   setting_reg #(.my_addr(BASE), .width(3)) sr_error_policy
     (.clk(clk),.rst(reset),.strobe(set_stb),.addr(set_addr),
      .in(set_data),.out({policy_next_burst,policy_next_packet,policy_wait}),.changed(clear_seqnum));

   time_compare
     time_compare (.clk(clk), .reset(reset), .time_now(vita_time), .trigger_time(send_time),
		   .now(now), .early(early), .late(late), .too_early(too_early));

   assign run = (state == ST_SAMP0) | (state == ST_SAMP1);

   assign sample = (state == ST_SAMP0) ? sample0 : sample1;

   reg [2:0] 	 state;

   localparam ST_IDLE  = 0;
   localparam ST_SAMP0 = 1;
   localparam ST_SAMP1 = 2;
   localparam ST_ERROR = 3;
   localparam ST_WAIT  = 4;

   reg [11:0]  expected_seqnum;

   wire [63:0] CODE_EOB_ACK            = {32'd1,20'd0,seqnum};
   wire [63:0] CODE_UNDERRUN           = {32'd2,20'd0,seqnum};
   wire [63:0] CODE_SEQ_ERROR          = {32'd4,4'd0,expected_seqnum,4'd0,seqnum};
   wire [63:0] CODE_TIME_ERROR         = {32'd8,20'd0,seqnum};
   wire [63:0] CODE_UNDERRUN_MIDPKT    = {32'd16,20'd0,seqnum};
   wire [63:0] CODE_SEQ_ERROR_MIDBURST = {32'd32,4'd0,expected_seqnum,4'd0,seqnum};

   always @(posedge clk)
     if(reset | clear | clear_seqnum)
       expected_seqnum <= 12'd0;
     else
       if(sample_tvalid & sample_tready & eop)
	 expected_seqnum <= seqnum + 12'd1;

   always @(posedge clk)
     if(reset | clear)
       begin
	  state <= ST_IDLE;
	  ack_or_error <= 1'b0;
	  error_code <= 64'd0;
       end
     else
       case(state)
	 ST_IDLE :
	   begin
	      ack_or_error <= 1'b0;
	      if(sample_tvalid)
		if(~send_at | now)
		  if(expected_seqnum != seqnum)
		    begin
		       state <= ST_ERROR;
		       ack_or_error <= 1'b1;
		       error_code <= CODE_SEQ_ERROR;
		    end
		  else
		    state <= ST_SAMP0;
		else if(late)
		  begin
		     state <= ST_ERROR;
		     ack_or_error <= 1'b1;
		     error_code <= CODE_TIME_ERROR;
		  end
	   end // case: ST_IDLE
	 ST_SAMP0 :
	   if(strobe)
	     if(~sample_tvalid)
	       begin
		  state <= ST_ERROR;
		  ack_or_error <= 1'b1;
		  error_code <= CODE_UNDERRUN;
	       end
	     else if(eop & odd & eob)
	       begin
		  state <= ST_IDLE;
		  ack_or_error <= 1'b1;
		  error_code <= CODE_EOB_ACK;
	       end
	     else if(eop & odd)
	       state <= ST_SAMP0;
	     else if(expected_seqnum != seqnum)
	       begin
		  state <= ST_ERROR;
		  ack_or_error <= 1'b1;
		  error_code <= CODE_SEQ_ERROR_MIDBURST;
	       end
	     else
	       state <= ST_SAMP1;
	 ST_SAMP1 :
	   if(strobe)
	     if(eop & eob)
	       begin
		  state <= ST_IDLE;
		  ack_or_error <= 1'b1;
		  error_code <= CODE_EOB_ACK;
	       end
	     else
	       state <= ST_SAMP0;
	 ST_ERROR :
	   begin
	      ack_or_error <= 1'b0;
	      if(sample_tvalid & eop)
		if(policy_next_packet | (policy_next_burst & eob))
		  state <= ST_IDLE;
		else if(policy_wait)
		  state <= ST_WAIT;
	   end
       endcase // case (state)

   assign sample_tready = (state == ST_ERROR) | (strobe & ( (state == ST_SAMP1) | ((state == ST_SAMP0) & eop & odd) ) );

   assign packet_consumed = eop & sample_tvalid & sample_tready;

   assign debug = {
		   error_code[37:32], // [30:25]
		   error_code[11:0], // [24:13]
		   sample_tvalid, //[12]
		   now, // [11]
		   early, // [10]
		   late, // [9]
		   too_early, // [8]
		   strobe,  // [7]
		   eop, // [6]
		   eob, // [5]
		   send_at, // [4]
		   odd,  // [3]
		   state[2:0] //  [2:0]
		   };


endmodule // new_tx_control
