module ericsmi_speed_test(
  input [7:0] io_in,
  output [7:0] io_out
);

parameter WIDTH=24;
localparam COUNTER_WIDTH = 23; // TinyTapeout is small, so find a value that fits by trial and error

wire force_trig, fired, count_en;
wire [2:0] sel;
wire [2:0] trig_q;
wire [1:0] ring_en;
wire [WIDTH-1:0] value0,value1;
wire [COUNTER_WIDTH-1:0] count0,count1;

wire clk  = io_in[0];
wire nrst = io_in[1];
wire trig = io_in[2];

assign sel[2:0]     = io_in[5:3];
assign ring_en[1:0] = io_in[7:6];

assign force_trig = &sel; // force the oscillators and counters to run to test their operation
                          // not really a controlled measurement.  Only for debug. 

inv_with_delay inv_r(.A(nrst),.Y(rst));

// Enable the counters for one clk period upon trig rising edge. 
// Asserting nrst arms the measurements.  Clear nrst before fire. 

rdffe dt0(.clk(clk),.rst(rst),.en(1'b1), .d(trig ),     .q(trig_q[0]));
rdffe dt1(.clk(clk),.rst(rst),.en(1'b1), .d(trig_q[0]), .q(trig_q[1]));

rdffe dt2(
    .clk(clk),
    .rst(rst),
    .en(1'b1),
    .d((trig_q[0] & ~trig_q[1])),
    .q(trig_q[2])
);

rdffe dt3(
    .clk(clk),
    .rst(rst),
    .en(1'b1),
    .d(trig_q[2] | fired),
    .q(fired)
);

assign count_en = force_trig | trig_q[2];

ring_with_counter #(.WIDTH(COUNTER_WIDTH)) ring0(
    .nrst(nrst),
    .ring_en(ring_en[0]),
    .count_en(count_en),
    .count(count0[COUNTER_WIDTH-1:0])
);

assign value0[WIDTH-1:0] = {{WIDTH-COUNTER_WIDTH{count0[COUNTER_WIDTH-1]}},count0[COUNTER_WIDTH-1:0]};

ring_with_counter #(.WIDTH(COUNTER_WIDTH)) ring1(
    .nrst(nrst),
    .ring_en(ring_en[1]),
    .count_en(count_en),
    .count(count1[COUNTER_WIDTH-1:0])
);

assign value1[WIDTH-1:0] = {{WIDTH-COUNTER_WIDTH{count1[COUNTER_WIDTH-1]}},count1[COUNTER_WIDTH-1:0]};

wire [7:0] status;

// when force_trigger is asserted put the status byte on the output, everything is free running. 
assign status[7:0] = {1'b1, 
                      fired, 
                      value1[COUNTER_WIDTH-1], // overflow
                      value0[COUNTER_WIDTH-1], // overflow
                      value1[COUNTER_WIDTH-2],
                      value0[COUNTER_WIDTH-2],
                      value1[16], // 16=Ceiling@Log2[166*166]+1
                      value0[16]};

assign io_out[7:0] = sel[2:0] == 3'b000 ? 8'd0 : 
                     sel[2:0] == 3'b001 ? {value0[7:0]} :
                     sel[2:0] == 3'b010 ? {value0[15:8]} :
                     sel[2:0] == 3'b011 ? {value0[23:16]} : 
                     sel[2:0] == 3'b100 ? {value1[7:0]} :
                     sel[2:0] == 3'b101 ? {value1[15:8]} :
                     sel[2:0] == 3'b110 ? {value1[23:16]} :
                                          status[7:0] ;

endmodule