/*
 * Copyright (c) 2024 Adonai Cruz
 * SPDX-License-Identifier: Apache-2.0
 */

`default_nettype none

module tt_um_adonairc_dda (
    input  wire [7:0] ui_in,    // Dedicated inputs
    output wire [7:0] uo_out,   // Dedicated outputs
    input  wire [7:0] uio_in,   // IOs: Input path
    output wire [7:0] uio_out,  // IOs: Output path
    output wire [7:0] uio_oe,   // IOs: Enable path (active high: 0=input, 1=output)
    input  wire       ena,      // always 1 when the design is powered, so you can ignore it
    input  wire       clk,      // clock
    input  wire       rst_n     // reset_n - low to reset
);
	parameter N = 16; // Posit word size
	parameter ES = 1; // Posit ES

	// All output pins must be assigned. If not used, assign to 0.
	assign uo_out  = 0;
	assign uio_out[7:3] = 0;
	assign uio_out[1:0] = 0;
	assign uio_oe[7:4]  = 0;

	// SPI pins
	wire sclk, cs, mosi, miso;

	// Output port (MISO)
	assign uio_oe[2] = 1;

	// Input ports
	assign cs  = uio_in[0];
	assign uio_oe[0] = 0;
	assign mosi  = uio_in[1];
	assign uio_oe[1] = 0;
	assign sclk  = uio_in[3];
	assign uio_oe[3] = 0;

	// Dynamical system parameters
	reg [N-1:0] icx, icy; // Initial conditions for variables x and y

	wire [N-1:0] mu; // Van-der-Pol parameter
	reg [N-1:0] r_mu;

	// DDA
	reg clk_dda; // DDA clock

	assign mu = r_mu;

	// SPI
	reg [2:0] r_SCK;
	reg [2:0] r_CS;
	reg [1:0] r_MOSI;
	reg [4:0] bitcnt; // bit counter
	reg is_data_received; // high when a byte has been received
	reg [31:0] data_received;
	reg [31:0] data_sent;
	reg [31:0] cnt;

	// state variables
	wire [N-1:0] x,y;

	// Van-Der-Pol DDA instance
	dda #(.N(N), .ES(ES)) van_der_pol(
		.clk(clk_dda),
		.rst_n(rst_n),
		.x(x),
		.y(y),
		.icx(icx),
		.icy(icy),
		.mu(mu)
	);

	// Reset to enable DDA and set initial conditions
	always @(posedge clk)  begin
		if (!rst_n) begin
			icx <= 16'h3000;
			icy <= 16'h3000;
		end
	end

	//
	// SPI interface
	//

	// Sync SCK to FPGA clock using a 3-bits shift register;
	always @(posedge clk) r_SCK <= {r_SCK[1:0], sclk};
	wire SCK_risingedge = (r_SCK[2:1]==2'b01); // detect SCK rising edge
	wire SCK_fallingedge = (r_SCK[2:1]==2'b10); // SCK falling edge

	// Sync CS
	always @(posedge clk) r_CS <= {r_CS[1:0], cs};
	wire CS_active = ~r_CS[1]; // CS is active low
	wire CS_startmessage = (r_CS[2:1]==2'b10); // message starts at falling edge
	wire CS_endmessage = (r_CS[2:1]==2'b01); // message stops at rising edge

	// Sync MOSI
	always @(posedge clk) r_MOSI <= {r_MOSI[0], mosi};
	wire MOSI_data = r_MOSI[1];

	// Handle SPI data in 32-bits word format
	always @(posedge clk)
	begin
		if (~CS_active)
			bitcnt <= 0;
		else
		if (SCK_risingedge)
		begin
			bitcnt <= bitcnt + 1;
			// implement a shift-left register (since we receive the data MSB first)
			data_received <= {data_received[30:0], MOSI_data};
		end
	end

	always @(posedge clk) is_data_received <= CS_active &&  SCK_risingedge && (bitcnt == 5'b11111);

	// Updates system parameter mu
	always @(posedge clk) if(is_data_received) r_mu <= data_received[15:0];

	// Data write
	always @(posedge clk) begin
		if(!rst_n) begin
			clk_dda <= 0;
		end
		if (CS_startmessage) begin
			clk_dda <= !clk_dda; // clock the DDA
		end
	end

	always @(posedge clk)
	if (CS_active)
	begin
		if (CS_startmessage) data_sent <= {x,y};
		else
		if (SCK_fallingedge) data_sent <= (bitcnt == 5'b00000)? x : {data_sent[30:0], 1'b0};
	end

	assign uio_out[2] = data_sent[31]; // send MSB first (MISO)

endmodule

/*
 * Copyright (c) 2024 Adonai Cruz
 * SPDX-License-Identifier: Apache-2.0
 */

module dda (
    input clk, // Clock
    input rst_n, // Reset (active low)
    output [N-1:0] x,y, // Dynamical system state variables
    input [N-1:0] icx, icy, // Initial conditions
    input [N-1:0] mu // Van-der-Pol parameter
);

// Posit parameters
parameter N = 16;
parameter ES = 1;

// Multiplications
wire [N-1:0] w_mult1, w_mult2, w_mult3;

posit_mult #(.N(N),.ES(ES)) mult1(.in1(x), .in2(x), .out(w_mult1)); // Multiply x*x
posit_mult #(.N(N),.ES(ES)) mult2(.in1(mu), .in2(w_sub1), .out(w_mult2)); // Multiply mu*(1-x*x)
posit_mult #(.N(N),.ES(ES)) mult3(.in1(w_mult2), .in2(y), .out(w_mult3)); // Multiply mu*(1-x*x)*y

// Subtraction
wire [N-1:0] w_sub1, w_sub2;

wire [N-1:0] w_neg_mult1;
assign w_neg_mult1 = {~w_mult1[N-1], ~w_mult1[N-2:0]+1'b1};

wire [N-1:0] w_neg_x;
assign w_neg_x = {~x[N-1], ~x[N-2:0]+1'b1};

posit_add #(.N(N),.ES(ES)) sub_1_mult_x_x(.in1(16'b0100000000000000), .in2(w_neg_mult1), .out(w_sub1)); // Subtract 1 - x*x
posit_add #(.N(N),.ES(ES)) sub_rho_z(.in1(w_mult3), .in2(w_neg_x), .out(w_sub2)); // Subtract mu*(1-x*x)y - x

// Van der Pol oscillator
// dx/dt = y
// dy/dt = mu*(1 - x*x) - x

euler_integrator  #(.N(N),.ES(ES)) int1(.out(x), .funct(y), .ic(icx), .clk(clk), .rst_n(rst_n));
euler_integrator  #(.N(N),.ES(ES)) int2(.out(y), .funct(w_sub2), .ic(icy), .clk(clk), .rst_n(rst_n));

endmodule

/// Euler integrator
module euler_integrator(out, funct, clk, rst_n, ic);
	parameter N = 16;
	parameter ES = 1;

	input clk, rst_n;
	output [N-1:0] out; // state variable
	input [N-1:0] funct; // the dV/dt function
	input [N-1:0] ic; // initial condition

	wire [N-1:0] out, v1new;
	reg [N-1:0] v1;

	wire [N-1:0] out_mult;

	// compute new state variable with dt
	// v1(n+1) = v1(n) + dt*funct(n)

    // Multiply funct(n) by constant dt
	posit_dt_mult  #(
		.N(N),
		.ES(ES)
	) mult (
		.in1(funct),
		.out(out_mult)
	);

	posit_add #(
		.N(N),
		.ES(ES)
	)
	add(
		.in1(out_mult),
		.in2(v1),
		.out(v1new)
	);

	always @(posedge clk)
	begin
		if (!rst_n)
			v1 <= ic;
		else
			v1 <= v1new;
	end
	assign out = v1;

endmodule

/*
 * Copyright (c) 2024 Adonai Cruz
 * SPDX-License-Identifier: Apache-2.0
 */

///////////
// Adder //
///////////
module posit_add (in1, in2, out);

function [31:0] log2;
input reg [31:0] value;
	begin
	value = value-1;
	for (log2=0; value>0; log2=log2+1)
        	value = value>>1;
      	end
endfunction

parameter N = 16;
parameter Bs = log2(N);
parameter ES = 1;

input [N-1:0] in1, in2;
output [N-1:0] out;
wire inf, zero;

wire s1 = in1[N-1];
wire s2 = in2[N-1];
wire zero_tmp1 = |in1[N-2:0];
wire zero_tmp2 = |in2[N-2:0];
wire inf1 = in1[N-1] & (~zero_tmp1),
	inf2 = in2[N-1] & (~zero_tmp2);
wire zero1 = ~(in1[N-1] | zero_tmp1),
	zero2 = ~(in2[N-1] | zero_tmp2);
assign inf = inf1 | inf2,
	zero = zero1 & zero2;

//Data Extraction
wire rc1, rc2;
wire [Bs-1:0] regime1, regime2;
wire [ES-1:0] e1, e2;
wire [N-ES-1:0] mant1, mant2;
wire [N-1:0] xin1 = s1 ? -in1 : in1;
wire [N-1:0] xin2 = s2 ? -in2 : in2;
data_extract_v1 #(.N(N),.ES(ES)) uut_de1(.in(xin1), .rc(rc1), .regime(regime1), .exp(e1), .mant(mant1));
data_extract_v1 #(.N(N),.ES(ES)) uut_de2(.in(xin2), .rc(rc2), .regime(regime2), .exp(e2), .mant(mant2));

wire [N-ES:0] m1 = {zero_tmp1,mant1},
	m2 = {zero_tmp2,mant2};

//Large Checking and Assignment
wire in1_gt_in2 = (xin1[N-2:0] >= xin2[N-2:0]) ? 1'b1 : 1'b0;

wire ls = in1_gt_in2 ? s1 : s2;
wire op = s1 ~^ s2;

wire lrc = in1_gt_in2 ? rc1 : rc2;
wire src = in1_gt_in2 ? rc2 : rc1;

wire [Bs-1:0] lr = in1_gt_in2 ? regime1 : regime2;
wire [Bs-1:0] sr = in1_gt_in2 ? regime2 : regime1;

wire [ES-1:0] le = in1_gt_in2 ? e1 : e2;
wire [ES-1:0] se = in1_gt_in2 ? e2 : e1;

wire [N-ES:0] lm = in1_gt_in2 ? m1 : m2;
wire [N-ES:0] sm = in1_gt_in2 ? m2 : m1;

//Exponent Difference: Lower Mantissa Right Shift Amount
wire [ES+Bs+1:0] diff;
wire [Bs:0] lr_N;
wire [Bs:0] sr_N;
a_abs_regime #(.N(Bs)) uut_abs_regime1 (lrc, lr, lr_N);
a_abs_regime #(.N(Bs)) uut_abs_regime2 (src, sr, sr_N);
a_sub_N #(.N(ES+Bs+1)) uut_ediff ({lr_N,le}, {sr_N, se}, diff);
wire [Bs-1:0] exp_diff = (|diff[ES+Bs:Bs]) ? {Bs{1'b1}} : diff[Bs-1:0];

//DSR Right Shifting
wire [N-1:0] DSR_right_in;
generate
	if (ES >= 2)
	assign DSR_right_in = {sm,{ES-1{1'b0}}};
	else
	assign DSR_right_in = sm;
endgenerate

wire [N-1:0] DSR_right_out;
wire [Bs-1:0] DSR_e_diff  = exp_diff;
DSR_right_N_S #(.N(N), .S(Bs))  dsr1(.a(DSR_right_in), .b(DSR_e_diff), .c(DSR_right_out));

//Mantissa Addition
wire [N-1:0] add_m_in1;
generate
	if (ES >= 2)
	assign add_m_in1 = {lm,{ES-1{1'b0}}};
	else
	assign add_m_in1 = lm;
endgenerate

wire [N:0] add_m;
a_add_sub_N #(.N(N)) uut_add_sub_N (op, add_m_in1, DSR_right_out, add_m);
wire [1:0] mant_ovf = add_m[N:N-1];

//LOD
wire [N-1:0] LOD_in = {(add_m[N] | add_m[N-1]), add_m[N-2:0]};
wire [Bs-1:0] left_shift;
LOD_N #(.N(N)) l2(.in(LOD_in), .out(left_shift));

//DSR Left Shifting
wire [N-1:0] DSR_left_out_t;
DSR_left_N_S #(.N(N), .S(Bs)) dsl1(.a(add_m[N:1]), .b(left_shift), .c(DSR_left_out_t));
wire [N-1:0] DSR_left_out = DSR_left_out_t[N-1] ? DSR_left_out_t[N-1:0] : {DSR_left_out_t[N-2:0],1'b0};

//Exponent and Regime Computation
wire [ES+Bs+1:0] le_o_tmp, le_o;
a_sub_N #(.N(ES+Bs+1)) sub3 ({lr_N,le}, {{ES+1{1'b0}},left_shift}, le_o_tmp);
add_1 #(.N(ES+Bs+1)) uut_add_mantovf (le_o_tmp, mant_ovf[1], le_o);

wire [ES-1:0] e_o;
wire [Bs-1:0] r_o;
a_reg_exp_op #(.ES(ES), .Bs(Bs)) uut_reg_ro (le_o[ES+Bs:0], e_o, r_o);

//Exponent and Mantissa Packing
wire [2*N-1+3:0] tmp_o;
generate
	if(ES > 2)
		assign tmp_o = { {N{~le_o[ES+Bs]}}, le_o[ES+Bs], e_o, DSR_left_out[N-2:ES-2], |DSR_left_out[ES-3:0]};
	else
		assign tmp_o = { {N{~le_o[ES+Bs]}}, le_o[ES+Bs], e_o, DSR_left_out[N-2:0], {3-ES{1'b0}} };

endgenerate

//Including/Pushing Regime bits in Exponent-Mantissa Packing
wire [3*N-1+3:0] tmp1_o;
DSR_right_N_S #(.N(3*N+3), .S(Bs)) dsr2 (.a({tmp_o,{N{1'b0}}}), .b(r_o), .c(tmp1_o));

//Rounding RNE : ulp_add = G.(R + S) + L.G.(~(R+S))
wire L = tmp1_o[N+4], G = tmp1_o[N+3], R = tmp1_o[N+2], St = |tmp1_o[N+1:0],
     ulp = ((G & (R | St)) | (L & G & ~(R | St)));
wire [N-1:0] rnd_ulp = {{N-1{1'b0}},ulp};

wire [N:0] tmp1_o_rnd_ulp;
a_add_N #(.N(N)) uut_add_ulp (tmp1_o[2*N-1+3:N+3], rnd_ulp, tmp1_o_rnd_ulp);
wire [N-1:0] tmp1_o_rnd = (r_o < N-ES-2) ? tmp1_o_rnd_ulp[N-1:0] : tmp1_o[2*N-1+3:N+3];

//Final Output
wire [N-1:0] tmp1_oN = ls ? -tmp1_o_rnd : tmp1_o_rnd;
assign out = inf|zero|(~DSR_left_out[N-1]) ? {inf,{N-1{1'b0}}} : {ls, tmp1_oN[N-1:1]};

endmodule

////////////////
// Multiplier //
////////////////
module posit_mult(in1, in2, out);

function [31:0] log2;
input reg [31:0] value;
	begin
	value = value-1;
	for (log2=0; value>0; log2=log2+1)
        	value = value>>1;
      	end
endfunction

parameter N = 16;
parameter Bs = log2(N);
parameter ES = 1;

input [N-1:0] in1, in2;
output [N-1:0] out;
wire inf, zero;

wire s1 = in1[N-1];
wire s2 = in2[N-1];
wire zero_tmp1 = |in1[N-2:0];
wire zero_tmp2 = |in2[N-2:0];
wire inf1 = in1[N-1] & (~zero_tmp1),
	inf2 = in2[N-1] & (~zero_tmp2);
wire zero1 = ~(in1[N-1] | zero_tmp1),
	zero2 = ~(in2[N-1] | zero_tmp2);
assign inf = inf1 | inf2,
	zero = zero1 & zero2;

//Data Extraction
wire rc1, rc2;
wire [Bs-1:0] regime1, regime2;
wire [ES-1:0] e1, e2;
wire [N-ES-1:0] mant1, mant2;
wire [N-1:0] xin1 = s1 ? -in1 : in1;
wire [N-1:0] xin2 = s2 ? -in2 : in2;
data_extract_v1 #(.N(N),.ES(ES)) uut_de1(.in(xin1), .rc(rc1), .regime(regime1), .exp(e1), .mant(mant1));
data_extract_v1 #(.N(N),.ES(ES)) uut_de2(.in(xin2), .rc(rc2), .regime(regime2), .exp(e2), .mant(mant2));

wire [N-ES:0] m1 = {zero_tmp1,mant1},
	m2 = {zero_tmp2,mant2};

//Sign, Exponent and Mantissa Computation
wire mult_s = s1 ^ s2;

wire [2*(N-ES)+1:0] mult_m = m1*m2;
wire mult_m_ovf = mult_m[2*(N-ES)+1];
wire [2*(N-ES)+1:0] mult_mN = ~mult_m_ovf ? mult_m << 1'b1 : mult_m;

wire [Bs+1:0] r1 = rc1 ? {2'b0,regime1} : -regime1;
wire [Bs+1:0] r2 = rc2 ? {2'b0,regime2} : -regime2;
wire [Bs+ES+1:0] mult_e;
m_add_N_Cin #(.N(Bs+ES+1)) uut_add_exp ({r1,e1}, {r2,e2}, mult_m_ovf, mult_e);

//Exponent and Regime Computation
wire [ES-1:0] e_o;
wire [Bs:0] r_o;
m_reg_exp_op #(.ES(ES), .Bs(Bs)) uut_reg_ro (mult_e[ES+Bs+1:0], e_o, r_o);

//Exponent, Mantissa and GRS Packing
wire [2*N-1+3:0]tmp_o = {{N{~mult_e[ES+Bs+1]}},mult_e[ES+Bs+1],e_o,mult_mN[2*(N-ES):2*(N-ES)-(N-ES-1)+1], mult_mN[2*(N-ES)-(N-ES-1):2*(N-ES)-(N-ES-1)-1], |mult_mN[2*(N-ES)-(N-ES-1)-2:0] };

//Including Regime bits in Exponent-Mantissa Packing
wire [3*N-1+3:0] tmp1_o;
DSR_right_N_S #(.N(3*N+3), .S(Bs+1)) dsr2 (.a({tmp_o,{N{1'b0}}}), .b(r_o[Bs] ? {Bs{1'b1}} : r_o), .c(tmp1_o));

//Rounding RNE : ulp_add = G.(R + S) + L.G.(~(R+S))
wire L = tmp1_o[N+4], G = tmp1_o[N+3], R = tmp1_o[N+2], St = |tmp1_o[N+1:0],
     ulp = ((G & (R | St)) | (L & G & ~(R | St)));
wire [N-1:0] rnd_ulp = {{N-1{1'b0}},ulp};

wire [N:0] tmp1_o_rnd_ulp;
m_add_N #(.N(N)) uut_add_ulp (tmp1_o[2*N-1+3:N+3], rnd_ulp, tmp1_o_rnd_ulp);
wire [N-1:0] tmp1_o_rnd = (r_o < N-ES-2) ? tmp1_o_rnd_ulp[N-1:0] : tmp1_o[2*N-1+3:N+3];

//Final Output
wire [N-1:0] tmp1_oN = mult_s ? -tmp1_o_rnd : tmp1_o_rnd;
assign out = inf|zero|(~mult_mN[2*(N-ES)+1]) ? {inf,{N-1{1'b0}}} : {mult_s, tmp1_oN[N-1:1]};
endmodule

///////////////////////////////////////////////
// Multiply by hard-coded constant in (16,1) //
/// dt = 0x8000 					         //
///////////////////////////////////////////////
module posit_dt_mult(in1, out);

function [31:0] log2;
input reg [31:0] value;
	begin
	value = value-1;
	for (log2=0; value>0; log2=log2+1)
        	value = value>>1;
      	end
endfunction

parameter N = 16;
parameter Bs = log2(N);
parameter ES = 1;

input [N-1:0] in1;
output [N-1:0] out;

wire s1 = in1[N-1];
wire s2; //

assign s2 = 0;

wire zero_tmp1 = |in1[N-2:0];
wire inf = in1[N-1] & (~zero_tmp1);
wire zero = ~(in1[N-1] | zero_tmp1);

//Data Extraction
wire rc1, rc2;
wire [Bs-1:0] regime1, regime2;
wire [ES-1:0] e1, e2;
wire [N-ES-1:0] mant1, mant2;
wire [N-1:0] xin1 = s1 ? -in1 : in1;
wire [N-1:0] xin2;

data_extract_v1 #(.N(N),.ES(ES)) uut_de1(.in(xin1), .rc(rc1), .regime(regime1), .exp(e1), .mant(mant1));

// data_extract_v1 #(.N(N),.ES(ES)) uut_de2(.in(xin2), .rc(rc2), .regime(regime2), .exp(e2), .mant(mant2));
assign regime2 = 4;
assign xin2 = 16'h0400;
assign rc2 = 0;
assign e2 = 0;
assign mant2 = 0;

wire [N-ES:0] m1 = {zero_tmp1,mant1};
wire [N-ES:0] m2;

assign m2 = 16'h8000;

//Sign, Exponent and Mantissa Computation
wire mult_s = s1;

wire [2*(N-ES)+1:0] mult_m = m1*m2;
wire mult_m_ovf = mult_m[2*(N-ES)+1];
wire [2*(N-ES)+1:0] mult_mN = ~mult_m_ovf ? mult_m << 1'b1 : mult_m;

wire [Bs+1:0] r1 = rc1 ? {2'b0,regime1} : -regime1;
wire [Bs+1:0] r2 = rc2 ? {2'b0,regime2} : -regime2;
wire [Bs+ES+1:0] mult_e;
m_add_N_Cin #(.N(Bs+ES+1)) uut_add_exp ({r1,e1}, {r2,e2}, mult_m_ovf, mult_e);

//Exponent and Regime Computation
wire [ES-1:0] e_o;
wire [Bs:0] r_o;
m_reg_exp_op #(.ES(ES), .Bs(Bs)) uut_reg_ro (mult_e[ES+Bs+1:0], e_o, r_o);

//Exponent, Mantissa and GRS Packing
wire [2*N-1+3:0]tmp_o = {{N{~mult_e[ES+Bs+1]}},mult_e[ES+Bs+1],e_o,mult_mN[2*(N-ES):2*(N-ES)-(N-ES-1)+1], mult_mN[2*(N-ES)-(N-ES-1):2*(N-ES)-(N-ES-1)-1], |mult_mN[2*(N-ES)-(N-ES-1)-2:0] };

//Including Regime bits in Exponent-Mantissa Packing
wire [3*N-1+3:0] tmp1_o;
DSR_right_N_S #(.N(3*N+3), .S(Bs+1)) dsr2 (.a({tmp_o,{N{1'b0}}}), .b(r_o[Bs] ? {Bs{1'b1}} : r_o), .c(tmp1_o));

//Rounding RNE : ulp_add = G.(R + S) + L.G.(~(R+S))
wire L = tmp1_o[N+4], G = tmp1_o[N+3], R = tmp1_o[N+2], St = |tmp1_o[N+1:0],
     ulp = ((G & (R | St)) | (L & G & ~(R | St)));
wire [N-1:0] rnd_ulp = {{N-1{1'b0}},ulp};

wire [N:0] tmp1_o_rnd_ulp;
m_add_N #(.N(N)) uut_add_ulp (tmp1_o[2*N-1+3:N+3], rnd_ulp, tmp1_o_rnd_ulp);
wire [N-1:0] tmp1_o_rnd = (r_o < N-ES-2) ? tmp1_o_rnd_ulp[N-1:0] : tmp1_o[2*N-1+3:N+3];

//Final Output
wire [N-1:0] tmp1_oN = mult_s ? -tmp1_o_rnd : tmp1_o_rnd;
assign out = inf|zero|(~mult_mN[2*(N-ES)+1]) ? {inf,{N-1{1'b0}}} : {mult_s, tmp1_oN[N-1:1]};
endmodule

/////////////////////////////
// Adder auxiliary modules //
////////////////////////////

/////////////////
module a_sub_N (a,b,c);
parameter N=10;
input [N-1:0] a,b;
output [N:0] c;
wire [N:0] ain = {1'b0,a};
wire [N:0] bin = {1'b0,b};
a_sub_N_in #(.N(N)) s1 (ain,bin,c);
endmodule

/////////////////////////
module a_add_N (a,b,c);
parameter N=10;
input [N-1:0] a,b;
output [N:0] c;
wire [N:0] ain = {1'b0,a};
wire [N:0] bin = {1'b0,b};
a_add_N_in #(.N(N)) a1 (ain,bin,c);
endmodule

/////////////////////////
module a_sub_N_in (a,b,c);
parameter N=10;
input [N:0] a,b;
output [N:0] c;
assign c = a - b;
endmodule

/////////////////////////
module a_add_N_in (a,b,c);
parameter N=10;
input [N:0] a,b;
output [N:0] c;
assign c = a + b;
endmodule

/////////////////////////
module a_add_sub_N (op,a,b,c);
parameter N=10;
input op;
input [N-1:0] a,b;
output [N:0] c;
wire [N:0] c_add, c_sub;

a_add_N #(.N(N)) a11 (a,b,c_add);
a_sub_N #(.N(N)) s11 (a,b,c_sub);
assign c = op ? c_add : c_sub;
endmodule

/////////////////////////
module a_abs_regime (rc, regime, regime_N);
parameter N = 10;
input rc;
input [N-1:0] regime;
output [N:0] regime_N;

assign regime_N = rc ? {1'b0,regime} : -{1'b0,regime};
endmodule

/////////////////////////
module a_reg_exp_op (exp_o, e_o, r_o);
parameter ES=3;
parameter Bs=5;
input [ES+Bs:0] exp_o;
output [ES-1:0] e_o;
output [Bs-1:0] r_o;

assign e_o = exp_o[ES-1:0];

wire [ES+Bs:0] exp_oN_tmp;
conv_2c #(.N(ES+Bs)) uut_conv_2c1 (~exp_o[ES+Bs:0],exp_oN_tmp);
wire [ES+Bs:0] exp_oN = exp_o[ES+Bs] ? exp_oN_tmp[ES+Bs:0] : exp_o[ES+Bs:0];
assign r_o = (~exp_o[ES+Bs] || |(exp_oN[ES-1:0])) ? exp_oN[ES+Bs-1:ES] + 1 : exp_oN[ES+Bs-1:ES];
endmodule

///////////////////////////////////
// Multiplier auxiliary modules //
/////////////////////////////////
module m_add_N (a,b,c);
parameter N=10;
input [N-1:0] a,b;
output [N:0] c;
assign c = {1'b0,a} + {1'b0,b};
endmodule

/////////////////////////
module m_add_N_Cin (a,b,cin,c);
parameter N=10;
input [N:0] a,b;
input cin;
output [N:0] c;
assign c = a + b + cin;
endmodule

/////////////////////////
module m_reg_exp_op (exp_o, e_o, r_o);
parameter ES=3;
parameter Bs=5;
input [ES+Bs+1:0] exp_o;
output [ES-1:0] e_o;
output [Bs:0] r_o;

assign e_o = exp_o[ES-1:0];

wire [ES+Bs:0] exp_oN_tmp;
conv_2c #(.N(ES+Bs)) uut_conv_2c1 (~exp_o[ES+Bs:0],exp_oN_tmp);
wire [ES+Bs:0] exp_oN = exp_o[ES+Bs+1] ? exp_oN_tmp[ES+Bs:0] : exp_o[ES+Bs:0];

assign r_o = (~exp_o[ES+Bs+1] || |(exp_oN[ES-1:0])) ? exp_oN[ES+Bs:ES] + 1 : exp_oN[ES+Bs:ES];
endmodule

//////////////////////
// General modules //
////////////////////
module data_extract_v1(in, rc, regime, exp, mant);
function [31:0] log2;
input reg [31:0] value;
	begin
	value = value-1;
	for (log2=0; value>0; log2=log2+1)
        	value = value>>1;
      	end
endfunction

parameter N=16;
parameter Bs=log2(N);
parameter ES = 2;

input [N-1:0] in;
output rc;
output [Bs-1:0] regime;
output [ES-1:0] exp;
output [N-ES-1:0] mant;

wire [N-1:0] xin = in;
assign rc = xin[N-2];

wire [N-1:0] xin_r = rc ? ~xin : xin;

wire [Bs-1:0] k;
LOD_N #(.N(N)) xinst_k(.in({xin_r[N-2:0],rc^1'b0}), .out(k));

assign regime = rc ? k-1 : k;

wire [N-1:0] xin_tmp;
DSR_left_N_S #(.N(N), .S(Bs)) ls (.a({xin[N-3:0],2'b0}),.b(k),.c(xin_tmp));

assign exp= xin_tmp[N-1:N-ES];
assign mant= xin_tmp[N-ES-1:0];

endmodule

/////////////////////////
module add_1 (a,mant_ovf,c);
parameter N=10;
input [N:0] a;
input mant_ovf;
output [N:0] c;
assign c = a + mant_ovf;
endmodule

/////////////////////////
module conv_2c (a,c);
parameter N=10;
input [N:0] a;
output [N:0] c;
assign c = a + 1'b1;
endmodule

/////////////////////////
module DSR_left_N_S(a,b,c);
        parameter N=16;
        parameter S=4;
        input [N-1:0] a;
        input [S-1:0] b;
        output [N-1:0] c;

wire [N-1:0] tmp [S-1:0];
assign tmp[0]  = b[0] ? a << 7'd1  : a;
genvar i;
generate
	for (i=1; i<S; i=i+1)begin:loop_blk
		assign tmp[i] = b[i] ? tmp[i-1] << 2**i : tmp[i-1];
	end
endgenerate
assign c = tmp[S-1];

endmodule

/////////////////////////
module DSR_right_N_S(a,b,c);
        parameter N=16;
        parameter S=4;
        input [N-1:0] a;
        input [S-1:0] b;
        output [N-1:0] c;

wire [N-1:0] tmp [S-1:0];
assign tmp[0]  = b[0] ? a >> 7'd1  : a;
genvar i;
generate
	for (i=1; i<S; i=i+1)begin:loop_blk
		assign tmp[i] = b[i] ? tmp[i-1] >> 2**i : tmp[i-1];
	end
endgenerate
assign c = tmp[S-1];

endmodule

/////////////////////////
module LOD_N (in, out);

  function [31:0] log2;
    input reg [31:0] value;
    begin
      value = value-1;
      for (log2=0; value>0; log2=log2+1)
	value = value>>1;
    end
  endfunction

parameter N = 64;
parameter S = log2(N);
input [N-1:0] in;
output [S-1:0] out;

wire vld;
LOD #(.N(N)) l1 (in, out, vld);
endmodule

/////////////////////////
module LOD (in, out, vld);

  function [31:0] log2;
    input reg [31:0] value;
    begin
      value = value-1;
      for (log2=0; value>0; log2=log2+1)
	value = value>>1;
    end
  endfunction

parameter N = 64;
parameter S = log2(N);

   input [N-1:0] in;
   output [S-1:0] out;
   output vld;

  generate
    if (N == 2)
      begin
	assign vld = |in;
	assign out = ~in[1] & in[0];
      end
    else if (N & (N-1))
      //LOD #(1<<S) LOD ({1<<S {1'b0}} | in,out,vld);
      LOD #(1<<S) LOD ({in,{((1<<S) - N) {1'b0}}},out,vld);
    else
      begin
	wire [S-2:0] out_l, out_h;
	wire out_vl, out_vh;
	LOD #(N>>1) l(in[(N>>1)-1:0],out_l,out_vl);
	LOD #(N>>1) h(in[N-1:N>>1],out_h,out_vh);
	assign vld = out_vl | out_vh;
	assign out = out_vh ? {1'b0,out_h} : {out_vl,out_l};
      end
  endgenerate
endmodule


/*
Based on paper:
R. Murillo, A. A. Del Barrio and G. Botella, "Customized Posit Adders and Multipliers using the FloPoCo Core Generator," 2020 IEEE International Symposium on Circuits and Systems (ISCAS), 2020, pp. 1-5,
doi: 10.1109/ISCAS45731.2020.9180771.
*/
module add #(parameter N=16) (
   input wire  i_s_1,
   input wire [N-11:0]  i_sf_1,
   input wire [N-5:0] i_mant_1,
   input wire  i_nzn_1,
   input wire  i_s_2,
   input wire [N-11:0]  i_sf_2,
   input wire [N-5:0] i_mant_2,
   input wire  i_nzn_2,
   output wire o_s,
   output wire [N-10:0]o_sf,
   output wire [N-5:0] o_mant,
   output wire o_guard,
   output wire o_sticky,
   output wire o_nzn
);

  wire X_not_zero ;
  wire X_nar ;
  wire Y_not_zero ;
  wire Y_nar ;
  wire check_larger ;
  wire [$clog2(N)+1:0] larger_number ;
  wire [$clog2(N)+1:0] smallest_number ;
  wire [N-3:0] larger_mant ;
  wire [N-3:0] smaller_mant ;
  wire [$clog2(N)+1:0] offset;
  wire shift_saturate;
  wire [$clog2(N):0]mant_offset ;
  wire [N-1:0]input_shifter ;
  wire pad_bit;
  wire [N-1:0] shifted_mant ;
  wire stk_tmp ;
  wire [N-3:0] smaller_mant_sh;
  wire grd_tmp ;
  wire rnd_tmp ;
  wire [N-2:0]add_mant;
  wire grd_bit;
  wire rnd_bit;
  wire stk_bit;
  wire count_type;
  wire [N:0]add_mant_shift ;
  wire [$clog2(N):0]count ;
  wire [(N):0]norm_mant_tmp;
  wire [N-10:0]add_sf ;
  wire is_not_zero ;
  wire is_nar;
  wire Xi_nzn_2;

  assign X_not_zero = i_s_1 | i_nzn_1;
  assign X_nar      = i_s_1 & ~(i_nzn_1);
  assign Y_not_zero = i_s_2 | i_nzn_2;
  assign Y_nar      = i_s_2 & ~(i_nzn_2);

  assign check_larger    = (($signed(i_sf_1))>($signed(i_sf_2))) ?  1 : 0;
  assign larger_number    = (check_larger) ? i_sf_1 : i_sf_2;
  assign smallest_number   = (check_larger) ? i_sf_2 : i_sf_1;
  assign larger_mant  = (check_larger) ? {i_s_1 , (~i_s_1 & X_not_zero) ,i_mant_1} : {i_s_2,(~i_s_2 & Y_not_zero),i_mant_2};
  assign smaller_mant = (check_larger) ? {i_s_2,(~i_s_2 & Y_not_zero),i_mant_2} :{i_s_1 , (~i_s_1 & X_not_zero) ,i_mant_1};

  assign offset         = larger_number - smallest_number;
  assign shift_saturate = (!offset[5]) ? 0 : 1;
  assign mant_offset    = (shift_saturate) ? 16 : offset[4:0];

  assign input_shifter = {smaller_mant, 2'b00};

  assign pad_bit = smaller_mant[N-3];
  right_shifter_sticky_16 #(.N(N)) inst_right_shifter_sticky_16_2
    (  .i_s     (mant_offset),
      .i_in    (input_shifter),
      .i_padbit(pad_bit),
      .o_r     (shifted_mant),
      .o_sticky(stk_tmp)
    );
  assign smaller_mant_sh = shifted_mant[15:2];
  assign grd_tmp         = shifted_mant[1];
  assign rnd_tmp         = shifted_mant[0];

  assign add_mant = {larger_mant[13], larger_mant} + {smaller_mant_sh[13], smaller_mant_sh};
  assign grd_bit  = grd_tmp;
  assign rnd_bit  = rnd_tmp;
  assign stk_bit  = stk_tmp;

  assign count_type     = add_mant[14];
  assign add_mant_shift = {add_mant[13:0], grd_bit , rnd_bit , stk_bit};

  normalizer_16 #(.N(N)) inst_normalizer_16
    ( .i_ozb  (count_type),
      .i_in   (add_mant_shift),
      .o_count(count),
      .o_r  (norm_mant_tmp)
    );

  assign add_sf = {larger_number[5] , larger_number} - ({2'b00 , count}) + 1;

  assign is_not_zero = (count==5'b11111) ? count_type : 1;
  assign is_nar      = X_nar | Y_nar;
  assign Xi_nzn_2      = is_not_zero & ~(is_nar);
  assign o_s        = is_nar | (is_not_zero & add_mant[14]);
  assign o_mant   = norm_mant_tmp[N-1:4];
  assign o_guard         = norm_mant_tmp[3];
  assign o_sticky         = norm_mant_tmp[2] | norm_mant_tmp[1] | norm_mant_tmp[0];
  assign o_sf =  add_sf;
  assign o_nzn = Xi_nzn_2;

endmodule

/*
Based on paper:
R. Murillo, A. A. Del Barrio and G. Botella, "Customized Posit Adders and Multipliers using the FloPoCo Core Generator," 2020 IEEE International Symposium on Circuits and Systems (ISCAS), 2020, pp. 1-5,
doi: 10.1109/ISCAS45731.2020.9180771.
*/

module data_posit_encoder #( parameter N=16) (
  input wire i_s ,
  input wire [N-10:0]i_sf ,
  input wire [N-5:0]i_mant ,
  input wire i_guard ,
  input wire i_sticky ,
  input wire i_nzn ,
  output wire [N-1:0] o_r
);

  wire rc ;
  wire [$clog2(N):0]rcVect;
  wire [$clog2(N):0] k ;
  wire sgnVect ;
  wire exp ;
  wire ovf ;
  wire [$clog2(N)-1:0] regValue;
  wire regNeg ;
  wire padBit ;
  wire [N-2:0]inputShifter ;
  wire [N-2:0]shiftedPosit ;
  wire stkBit ;
  wire [N-2:0] unroundedPosit ;
  wire lsb ;
  wire rnd ;
  wire stk ;
  wire round;
  wire [N-2:0]roundedPosit ;
  wire [N-2:0]unsignedPosit ;

  assign rc      = i_sf[N-10];
  assign rcVect  = {5{rc}};
  assign k       =  i_sf[5:1] ^ rcVect;
  assign sgnVect = i_s;
  assign exp = i_sf[0] ^ sgnVect;

  assign ovf      = (k>13) ? 1 :0;
  assign regValue = (!ovf) ? k[3:0] : 4'b1110;

  assign regNeg       = i_s ^ rc;
  assign padBit       = ~(regNeg);
  assign inputShifter = {regNeg, exp , i_mant, i_guard};
  right_shifter_sticky_18 #(.N(N))  inst_right_shifter_sticky_18
    ( .i_s(regValue),
      .i_in(inputShifter),
      .i_padbit(padBit),
      .o_r     (shiftedPosit),
      .o_sticky(stkBit)
    );

  assign unroundedPosit = {padBit, shiftedPosit[N-2:1]};

  assign lsb = shiftedPosit[1];
  assign rnd = shiftedPosit[0];
  assign stk = stkBit | i_sticky;
  assign round = rnd & (lsb | stk | ovf);
  assign roundedPosit = unroundedPosit + {14'd0,round};

  assign unsignedPosit = (i_nzn) ? roundedPosit : 0;
  assign o_r = { i_s  ,unsignedPosit};

endmodule

module Fixed16toPosit16(
    input [15:0]    fixed_number_input,
    output [3:0]    regime_value,
    output          exponent,
    output wire [11:0]   mantissa,
    output          Q,
    output          sign
    );
wire [15:0] fixed_number,fixed_numberaux, fixed_number_neg;

// 2's complement to extract value and sign of the fixed point input
assign fixed_numberaux = {(16){fixed_number_input[15]}} ;
assign fixed_number_neg = fixed_number_input ^ fixed_numberaux ;
assign fixed_number = fixed_number_neg + {15'b000000000000000, fixed_number_input[15]};
assign sign =  fixed_number_input[15];
reg [11:0] mantissa_compl;
wire [3:0] xaux,x;
wire [2:0] xaux2;
wire first_regime_bit;
//
//  zlc value       regime value
//      1,2     ->      2
//      3,4     ->      3
//      5,6     ->      4
//      7,8     ->      5
//      9,10    ->      6
//      11,12   ->      7
//      13,14   ->      8
//      15      ->      9
//
//  regime value -  2   =   {y2,y1,y0}
//
//  x3  x2  x1  x0  |   y2  y1  y0
//  0   0   0   0   |   0   0   0
//  0   0   0   1   |   0   0   0
//  0   0   1   0   |   0   0   1
//  0   0   1   1   |   0   0   1
//  0   1   0   0   |   0   1   0
//  0   1   0   1   |   0   1   0
//  0   1   1   0   |   0   1   1
//  0   1   1   1   |   0   1   1
//  1   0   0   0   |   1   0   0
//  1   0   0   1   |   1   0   0
//  1   0   1   0   |   1   0   1
//  1   0   1   1   |   1   0   1
//  1   1   0   0   |   1   1   0
//  1   1   0   1   |   1   1   0
//  1   1   1   0   |   1   1   1
//  1   1   1   1   |   1   1   1
//

LeadingZeroCounter_16b LeadingZeroCounter_16b(
    .x(fixed_number),
    .count(x),
    .Q(Q)
    );

assign xaux = (sign & first_regime_bit)? x : x-1;
assign xaux2 = ~(xaux[3:1]);
assign regime_value = {1'b1,xaux2};
assign exponent = (first_regime_bit ) ? ~x[0]:x[0];
assign first_regime_bit = (fixed_number_input[14]==0 && sign==1) ? 1 : 0;
assign mantissa = (first_regime_bit) ? -mantissa_compl : mantissa_compl;
always @(*)
case (x)
      4'b0001: begin
                  mantissa_compl = fixed_number [13:2];  //
               end
      4'b0010: begin
                  mantissa_compl = fixed_number [12:1];  //
               end
      4'b0011: begin
                  mantissa_compl = fixed_number [11:0];  //
               end
      4'b0100: begin
                  mantissa_compl = {fixed_number [10:0],1'b0};  //
               end
      4'b0101: begin
                  mantissa_compl = {fixed_number [9:0],2'b00};  //
               end
      4'b0110: begin
                  mantissa_compl = {fixed_number [8:0],3'b000};  //
               end
      4'b0111: begin
                  mantissa_compl = {fixed_number [7:0],4'b0000};  //
               end
      4'b1000: begin
                  mantissa_compl = {fixed_number [6:0],5'b00000};  //
               end
      4'b1001: begin
                  mantissa_compl = {fixed_number [5:0],6'b000000};  //
               end
      4'b1010: begin
                  mantissa_compl = {fixed_number [4:0],7'b0000000};  //
               end
      4'b1011: begin
                  mantissa_compl = {fixed_number [3:0],8'b00000000};  //
               end
      4'b1100: begin
                  mantissa_compl = {fixed_number [2:0],9'b000000000};  //
               end
      4'b1101: begin
                  mantissa_compl = {fixed_number [1:0],10'b0000000000};  //
               end
      4'b1110: begin
                  mantissa_compl = {fixed_number [0],11'b00000000000};  //
                end
      default: begin
                  mantissa_compl = {12'b00000000000};  //
                end
   endcase

endmodule

module LeadingZeroCounter_16b(
    input  wire [15:0] x,
    output wire [3:0] count,
    output wire Q
    );

wire [3:0] auxa;
wire [7:0] auxz;
wire [1:0] auxcount;

genvar k;
generate
  for (k=0; k < 4; k=k+1)
  begin: NLC_generation
     NLC_16b NLC (.x(x[15-4*k : 12-4*k]),
              .a(auxa[k]),
              .z(auxz[2*k+1 : 2*k])
              );
  end
endgenerate

BNE_16b BNEncoder (.a(auxa),
               .Q(Q),
               .y(auxcount[1 : 0]));

assign count[3 : 2] = auxcount;

Mux_LZC_16b Mux (.i0(auxz[1:0]),
             .i1(auxz[3:2]),
             .i2(auxz[5:4]),
             .i3(auxz[7:6]),
             .s(auxcount),
             .o(count[1 : 0])
             );

endmodule

module BNE_16b(
    input  wire [3:0] a,
    output  wire  Q,
    output  wire [1:0] y
    );

 assign Q = a[0] & a[1] & a[2] & a[3];
 assign y[1] = a[0] & a[1];
 assign y[0] = a[0] & (!a[1] | a[2] );
endmodule

module NLC_16b (
    input  wire [3:0] x,    // Dedicated inputs
    output  wire  a,    // Dedicated inputs
    output  wire [1:0] z    // Dedicated inputs
    );

wire aprimo,z1,z0,aux1;
assign aprimo = x[3] | x[2] | x[1] | x[0];
assign a = ! aprimo;
assign z1 = x[3] | x[2];
assign z[1] = ! z1;
assign z0 = aux1 | x[3];
assign aux1 = x[1] & ! (x[2]);
assign z[0] = ! z0;

endmodule

module Mux_LZC_16b(
    input wire [1:0] i0 ,
    input wire [1:0] i1  ,
    input wire [1:0] i2  ,
    input wire [1:0] i3  ,
    input wire [1:0]  s  ,
    output reg [1:0] o
    );

always @(*)
  case (s)
     2'b00: o = i0;
     2'b01: o = i1;
     2'b10: o = i2;
     2'b11: o = i3;

  endcase

endmodule

/*
Based on paper:
R. Murillo, A. A. Del Barrio and G. Botella, "Customized Posit Adders and Multipliers using the FloPoCo Core Generator," 2020 IEEE International Symposium on Circuits and Systems (ISCAS), 2020, pp. 1-5,
doi: 10.1109/ISCAS45731.2020.9180771.
*/

module normalizer_16 #(parameter N=16) (
	input wire [N:0] i_in,
	input wire i_ozb,
	output wire [$clog2(N):0]o_count,
	output wire [N:0] o_r
);

	wire [N:0] level5 ;
	wire [N:0] level4 ;
	wire count4;
	wire sozb ;
	wire count3 ;
	wire [N:0] level3 ;
	wire count2 ;
	wire [N:0]level2 ;
	wire count1;
	wire [N:0]level1 ;
	wire count0;
	wire [N:0]level0;
	wire [$clog2(N):0]sCount ;

	assign level5 = i_in;
	assign sozb = i_ozb;

	assign count4 = (level5[N:1] == {16{sozb}}) ? 1: 0;
	assign level4 =(!count4) ? level5 : {level5[0],{16{1'b0}}};

	assign count3 = (level4[N:N-7] == {8{sozb}}) ? 1: 0;
	assign level3 = (!count3) ? level4 : {level4[8:0],{8{1'b0}}};

	assign count2 = (level3[N : N-3] == {4{sozb}})? 1 : 0;

	assign level2 = (!count2) ? level3  : {level3[12:0],{4{1'b0}}};
	assign count1 = level2[N:N-1]=={sozb,sozb} ?  1 : 0;

	assign level1 = (!count1) ? level2 : {level2[14:0], 2'b00};

	assign count0 = (level1[N]==sozb) ? 1 : 0;
	assign level0 = (!count0) ? level1 : {level1[15:0],1'b0};

	assign o_r    = level0;
	assign sCount = {count4,count3,count2,count1,count0};
	assign o_count  = sCount;

endmodule

module posit_top_open_hw #(parameter  N=16) (
  input wire [N-1:0] i_in_1,
  input wire [N-1:0] i_in_2,
  output wire [5:0] o_sign_regime_exp_1,
  output wire [5:0] o_sign_regime_exp_2,
  output wire [N-5:0] o_mantissa_1,
  output wire [N-5:0] o_mantissa_2,
  output wire [N-1:0] o_res
);

  wire [$clog2(N)+1:0]w_sf_1;
  wire [N-5:0] w_mant_1;

  wire [$clog2(N)+1:0]w_sf_2;
  wire [N-5:0] w_mant_2;

  wire [N-10:0]w_sf_res_add;
  wire [N-5:0]w_mant_res_add;
  wire w_guard_res_add;
  wire w_sticky_res_add;
  wire w_nzn_res_add;
  wire w_Q_1;
  wire w_sign_1;
  wire w_exponent_1;
  wire [3:0]w_regime_value_1;
  wire w_Q_2;
  wire w_s_res_add;
  wire w_sign_2;
  wire w_exponent_2;
  wire [3:0]w_regime_value_2;

Fixed16toPosit16 instFixed16toPosit16_1(
  .fixed_number_input(i_in_1),
  .Q                 (w_Q_1),
  .sign              (w_sign_1),
  .exponent          (w_exponent_1),
  .mantissa          (w_mant_1),
  .regime_value      (w_regime_value_1)
  );

Fixed16toPosit16 instFixed16toPosit16_2(
  .fixed_number_input(i_in_2),
  .Q                 (w_Q_2),
  .sign              (w_sign_2),
  .exponent          (w_exponent_2),
  .mantissa          (w_mant_2),
  .regime_value      (w_regime_value_2)
  );

assign w_sf_1 =(!w_sign_1) ? {1'b1, w_regime_value_1,w_exponent_1}: {1'b1, w_regime_value_1,~w_exponent_1} ;
assign w_sf_2 =(!w_sign_2) ? {1'b1, w_regime_value_2,w_exponent_2}:  {1'b1, w_regime_value_2,~w_exponent_2};
assign o_sign_regime_exp_1 = (!w_sign_1) ?  {w_sign_1,w_regime_value_1,w_exponent_1} : {w_sign_1,w_regime_value_1,~w_exponent_1};
assign o_sign_regime_exp_2 = (!w_sign_2) ?  {w_sign_2,w_regime_value_2,w_exponent_2} : {w_sign_2,w_regime_value_2,~w_exponent_2};
assign o_mantissa_1 = w_mant_1;
assign o_mantissa_2 = w_mant_2;

  add #(.N(N)) inst_add(
    .i_s_1   (w_sign_1),
    .i_sf_1  (w_sf_1),
    .i_mant_1(w_mant_1),
    .i_nzn_1 (~w_Q_1),
    .i_sf_2  (w_sf_2),
    .i_mant_2(w_mant_2),
    .i_nzn_2 (~w_Q_2),
    .i_s_2   (w_sign_2),
    .o_nzn   (w_nzn_res_add),
    .o_s     (w_s_res_add),
    .o_sticky(w_sticky_res_add),
    .o_guard (w_guard_res_add),
    .o_sf    (w_sf_res_add),
    .o_mant  (w_mant_res_add)
  );

  data_posit_encoder #(.N(N)) inst_data_posit_encoder
    (  .i_mant  (w_mant_res_add),
      .i_guard (w_guard_res_add),

      .i_nzn   (w_nzn_res_add),
      .i_sf(w_sf_res_add),
      .i_s     (w_s_res_add),
      .i_sticky(w_sticky_res_add),
      .o_r     (o_res)
    );

endmodule

/*
Based on paper:
R. Murillo, A. A. Del Barrio and G. Botella, "Customized Posit Adders and Multipliers using the FloPoCo Core Generator," 2020 IEEE International Symposium on Circuits and Systems (ISCAS), 2020, pp. 1-5,
doi: 10.1109/ISCAS45731.2020.9180771.
*/

module right_shifter_sticky_16 #(parameter N=16) (
  input wire [N-1:0] i_in,
  input wire [$clog2(N):0] i_s,
  input wire i_padbit,
  output wire [N-1:0] o_r,
  output wire o_sticky
);

  wire [$clog2(N):0] ps;
  wire [N-1:0] Xpadded;
  wire [N-1:0] level5;
  wire stk4 ;
  wire [N-1:0] level4 ;
  wire stk3 ;
  wire [N-1:0] level3 ;
  wire stk2 ;
  wire [N-1:0] level2 ;
  wire stk1 ;
  wire [N-1:0] level1 ;
  wire stk0 ;
  wire [N-1:0] level0 ;

  assign ps      = i_s;
  assign Xpadded = i_in;
  assign level5  = Xpadded;
  assign stk4    = (level5!=0 && ps[4]==1) ?  1 : 0;
  assign level4  = (ps[4]==0) ?  level5 : {16{i_padbit}} ;
  assign stk3    = ((level4[7:0]!=0 && ps[3]==1)|| stk4==1) ? 1 : 0;
  assign level3 =  ps[3]==0 ?  level4 : {{8{i_padbit}},level4[15 : 8]};
  assign stk2 = ((level3[3:0]!=0 && ps[2]==1)|| stk3==1) ? 1 : 0;
  assign level2 =  ps[2]==0 ?  level3 : {{4{i_padbit}},level3[15 : 4]};
  assign stk1 = ((level2[1:0]!=0 && ps[1]==1)|| stk2==1) ? 1 : 0;
  assign level1 =  ps[1]==0 ?  level2 : {{2{i_padbit}},level2[15 : 2]};
  assign stk0 = ((level1[0]!=0 && ps[0]==1)|| stk1==1) ? 1 : 0;
  assign level0 =   ps[0]==0 ?  level1 : {i_padbit,level1[15 : 1]};
  assign o_r = level0;
  assign o_sticky = stk0;

endmodule

/*
Based on paper:
R. Murillo, A. A. Del Barrio and G. Botella, "Customized Posit Adders and Multipliers using the FloPoCo Core Generator," 2020 IEEE International Symposium on Circuits and Systems (ISCAS), 2020, pp. 1-5,
doi: 10.1109/ISCAS45731.2020.9180771.
*/

module right_shifter_sticky_18 #(parameter N=16) (
  input wire [N-2:0] i_in,
  input wire [$clog2(N)-1:0] i_s,
  input wire i_padbit,
  output wire [N-2:0] o_r,
  output wire o_sticky
);

  wire [$clog2(N)-1:0] ps;
  wire [N-2:0] Xpadded;
  wire [N-2:0] level4 ;
  wire stk3 ;
  wire [N-2:0] level3 ;
  wire stk2 ;
  wire [N-2:0] level2 ;
  wire stk1 ;
  wire [N-2:0] level1 ;
  wire stk0 ;
  wire [N-2:0] level0 ;

  assign ps      = i_s;
  assign Xpadded = i_in;
  assign level4  = Xpadded ;
  assign stk3    = ((level4[7:0]!=0 && ps[3]==1)) ? 1 : 0;
  assign level3 =  ps[3]==0 ?  level4 : {{8{i_padbit}},level4[14 : 8]};
  assign stk2 = ((level3[3:0]!=0 && ps[2]==1)|| stk3==1) ? 1 : 0;
  assign level2 =  ps[2]==0 ?  level3 : {{4{i_padbit}},level3[14 : 4]};
  assign stk1 = ((level2[1:0]!=0 && ps[1]==1)|| stk2==1) ? 1 : 0;
  assign level1 =  ps[1]==0 ?  level2 : {{2{i_padbit}},level2[14 : 2]};
  assign stk0 = ((level1[0]!=0 && ps[0]==1)|| stk1==1) ? 1 : 0;
  assign level0 =   ps[0]==0 ?  level1 : {i_padbit,level1[14 : 1]};
  assign o_r = level0;
  assign o_sticky = stk0;

endmodule

/*
* Copyright (c) 2024 Your Name
* SPDX-License-Identifier: Apache-2.0
*/
//////////////////////////////////////////////////////////////////////////////////
// Companies: (a) University of Salerno, Fisciano (SA), Italy;
//            (b) STMicroelectronics, Napoli, Italy.
// Engineer: Andrea Fasolino (a), Gian Domenico Licciardo (a), Aldo Torino (b), Francesco Del Prete (b), Claudio Parrella (b).
//
// Module Name: tt_um_afasolino
//
//
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////

`default_nettype none

module tt_um_afasolino (
  input  wire [7:0] ui_in,    // Dedicated inputs
  output wire [7:0] uo_out,   // Dedicated outputs
  input  wire [7:0] uio_in,   // IOs: Input path
  output wire [7:0] uio_out,  // IOs: Output path
  output wire [7:0] uio_oe,   // IOs: Enable path (active high: 0=input, 1=output)
  input  wire       ena,      // always 1 when the design is powered, so you can ignore it
  input  wire       clk,      // clock
  input  wire       rst_n     // reset_n - low to reset
);

// All output pins must be assigned. If not used, assign to 0.
//  assign uo_out  = ui_in + uio_in;  // Example: ou_out is the sum of ui_in and uio_in
//  assign uio_out = 0;
//  assign uio_oe  = 0;
  localparam  data_buffer_size_bit=8;
  localparam  data_posit_size_bit=16;
  localparam  buffer_size = 4;
  localparam  buffer_size_read = 12;
  reg alu_ready;
  reg [clog2(buffer_size+1)-1:0] wr_data_pointer;
  reg [clog2(buffer_size_read+1)-1:0] rd_data_pointer;
  wire data_input_valid;
  wire [data_posit_size_bit-1:0]data_input_1;
  wire [data_posit_size_bit-1:0]data_input_2;
  wire [data_posit_size_bit-1:0]o_result;
  reg [data_buffer_size_bit-1:0] input_buffer_data_1;
  reg [data_buffer_size_bit-1:0] input_buffer_data_2;
  reg [data_buffer_size_bit-1:0] input_buffer_data_3;
  reg [data_buffer_size_bit-1:0] input_buffer_data_4;
  reg data_valid_sync1;
  reg data_valid_sync2;
  reg read_data_valid_sync1;
  reg read_data_valid_sync2;
  reg read_data;
  wire read_data_valid;
  wire [5:0]w_sign_regime_exp_1;
  wire [5:0]w_sign_regime_exp_2;
  wire [11:0]w_mantissa_1;
  wire [11:0]w_mantissa_2;

  reg read_data_ready;
  reg [7:0]out_reg;
  assign data_input_valid = uio_in[0]; //Data valid on IO in 0
  assign uio_oe[0]        = 0;
  assign uio_oe[1]        = 1;
  assign data_input_1     = {input_buffer_data_2,input_buffer_data_1};
  assign data_input_2     = {input_buffer_data_4,input_buffer_data_3};
  assign uio_out[1]       = alu_ready;//alu ready on Output 1

  assign read_data_valid = uio_in[2];// Read Data valid on IO in 0
  assign uio_oe[2]       = 0;
  assign uio_out[3]      = read_data_ready;
  assign uio_oe[3]       = 1;
  assign uo_out     = out_reg;
  assign uio_oe[7:4] = 0;
  assign uio_out[7:4]=0;
  assign uio_out[0]=0;
  assign uio_out[2]=0;
  always@(posedge clk, negedge rst_n)begin
    if(rst_n==0)begin
      data_valid_sync1<=0;
      data_valid_sync2<=0;
      read_data_valid_sync1<=0;
      read_data_valid_sync2<=0;
    end
    else begin
      data_valid_sync1<=data_input_valid;
      data_valid_sync2<=data_valid_sync1;
      read_data_valid_sync1<=read_data_valid;
      read_data_valid_sync2<=read_data_valid_sync1;
    end
  end

  always@(posedge clk, negedge rst_n)begin
    if(rst_n==0)begin
      input_buffer_data_1<=0;
      input_buffer_data_2<=0;
      input_buffer_data_3<=0;
      input_buffer_data_4<=0;
      wr_data_pointer<=0;
      rd_data_pointer<=0;
      alu_ready<=1;
      read_data<=0;
      out_reg<=0;
      read_data_ready<=0;
    end
    else begin
      if(data_valid_sync2==1 && alu_ready==1) begin
        case(wr_data_pointer)
          'd0: begin
            input_buffer_data_1<=ui_in;
            wr_data_pointer<=wr_data_pointer+1;
            alu_ready<=0;
          end
          'd1: begin
            input_buffer_data_2<=ui_in;
            wr_data_pointer<=wr_data_pointer+1;
            alu_ready<=0;
          end
          'd2: begin
            input_buffer_data_3<=ui_in;
            wr_data_pointer<=wr_data_pointer+1;
            alu_ready<=0;
          end
          'd3: begin
            input_buffer_data_4<=ui_in;
            alu_ready<=0;
            read_data<=1;
            read_data_ready<=1;
            rd_data_pointer<=0;
          end

          default:begin
            input_buffer_data_1<=0;
            input_buffer_data_2<=0;
            input_buffer_data_3<=0;
            input_buffer_data_4<=0;
            wr_data_pointer<=0;
            alu_ready<=1;
            read_data_ready<=0;
          end
        endcase
      end
      if(read_data==0)begin
        if(data_valid_sync2==0)begin
          alu_ready<=1;
        end
      end
      else begin
        if(read_data_ready)begin
          case(rd_data_pointer)
            'd0: begin
              out_reg<=data_input_1[7:0];
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end
            'd1: begin
              out_reg<=data_input_1[15:8];
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end
            'd2: begin
              out_reg<=data_input_2[7:0];
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end
            'd3: begin
              out_reg<=data_input_2[15:8];
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end
            'd4: begin
              out_reg<={2'b00,w_sign_regime_exp_1};
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end
            'd5: begin
              out_reg<={2'b00,w_sign_regime_exp_2};
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end
            'd6: begin
              out_reg<=w_mantissa_1[7:0];
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end
            'd7: begin
              out_reg<={4'd0,w_mantissa_1[11:8]};
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end
            'd8: begin
              out_reg<=w_mantissa_2[7:0];
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end
            'd9: begin
              out_reg<={4'd0,w_mantissa_2[11:8]};
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end

            'd10: begin
              out_reg<=o_result[7:0];
              if(read_data_valid_sync2==1) begin
                rd_data_pointer<=rd_data_pointer+1;
                read_data_ready<=0;
              end
            end
            'd11: begin
             out_reg<=o_result[15:8];
              if(read_data_valid_sync2==1) begin
                read_data_ready<=0;
                read_data<=0;
                alu_ready<=1;
                wr_data_pointer<=0;
              end
            end
            default:begin
              out_reg<=0;
              alu_ready<=1;
              rd_data_pointer<=0;
              read_data_ready<=0;
            end
          endcase
        end
        else if(read_data_valid_sync2==0)begin
          read_data_ready<=1;
        end
      end
    end
  end

  posit_top_open_hw inst_posit_top(
    .i_in_1(data_input_1),
    .i_in_2(data_input_2),
    .o_res(o_result),
    .o_sign_regime_exp_1(w_sign_regime_exp_1),
    .o_sign_regime_exp_2(w_sign_regime_exp_2),
    .o_mantissa_1       (w_mantissa_1),
    .o_mantissa_2       (w_mantissa_2)
  );

  function integer clog2;
    input integer value;
    begin
      value = value-1;
      for (clog2=0; value>0; clog2=clog2+1)
        value = value>>1;
    end
  endfunction

endmodule


//_\TLV_version 1d: tl-x.org, generated by SandPiper(TM) 1.14-2022/10/10-beta-Pro
//_\source top.tlv 36

//_\SV
   // Include Tiny Tapeout Lab.
   // Included URL: "https://raw.githubusercontent.com/os-fpga/Virtual-FPGA-Lab/35e36bd144fddd75495d4cbc01c4fc50ac5bde6f/tlv_lib/tiny_tapeout_lib.tlv"// Included URL: "https://raw.githubusercontent.com/os-fpga/Virtual-FPGA-Lab/a069f1e4e19adc829b53237b3e0b5d6763dc3194/tlv_lib/fpga_includes.tlv"
//_\source top.tlv 79
//_\SV

// ================================================
// A simple Makerchip Verilog test bench driving random stimulus.
// Modify the module contents to your needs.
// ================================================

// Provide a wrapper module to debounce input signals if requested.

//_\SV

// =======================
// The Tiny Tapeout module
// =======================

module tt_um_ajstein_stopwatch (
    input  wire [7:0] ui_in,    // Dedicated inputs - connected to the input switches
    output wire [7:0] uo_out,   // Dedicated outputs - connected to the 7 segment display
       // The FPGA is based on TinyTapeout 3 which has no bidirectional I/Os (vs. TT6 for the ASIC).
    input  wire [7:0] uio_in,   // IOs: Bidirectional Input path
    output wire [7:0] uio_out,  // IOs: Bidirectional Output path
    output wire [7:0] uio_oe,   // IOs: Bidirectional Enable path (active high: 0=input, 1=output)

    input  wire       ena,      // will go high when the design is enabled
    input  wire       clk,      // clock
    input  wire       rst_n     // reset_n - low to reset
);
   wire reset = ! rst_n;

// ---------- Generated Code Inlined Here (before 1st \TLV) ----------
// Generated by SandPiper(TM) 1.14-2022/10/10-beta-Pro from Redwood EDA, LLC.
// (Installed here: /usr/local/mono/sandpiper/distro.)
// Redwood EDA, LLC does not claim intellectual property rights to this file and provides no warranty regarding its correctness or quality.

// For silencing unused signal messages.
`define BOGUS_USE(ignore)

genvar digit, input_label, leds, switch;

//
// Signals declared top-level.
//

// For $slideswitch.
wire [7:0] L0_slideswitch_a0;

// For $sseg_decimal_point_n.
wire L0_sseg_decimal_point_n_a0;

// For $sseg_digit_n.
wire [7:0] L0_sseg_digit_n_a0;

// For $sseg_segment_n.
wire [6:0] L0_sseg_segment_n_a0;

// For /fpga_pins/fpga$cycle_counter.
wire [31:0] FpgaPins_Fpga_cycle_counter_a0;
reg  [31:0] FpgaPins_Fpga_cycle_counter_a1;

// For /fpga_pins/fpga$display_counter.
wire [3:0] FpgaPins_Fpga_display_counter_a0;
reg  [3:0] FpgaPins_Fpga_display_counter_a1;

// For /fpga_pins/fpga$reset.
wire FpgaPins_Fpga_reset_a0;

// For /fpga_pins/fpga$segments.
wire [6:0] FpgaPins_Fpga_segments_a0;

   //
   // Scope: /fpga_pins
   //

      //
      // Scope: /fpga
      //

         // Staging of $cycle_counter.
         always @(posedge clk) FpgaPins_Fpga_cycle_counter_a1[31:0] <= FpgaPins_Fpga_cycle_counter_a0[31:0];

         // Staging of $display_counter.
         always @(posedge clk) FpgaPins_Fpga_display_counter_a1[3:0] <= FpgaPins_Fpga_display_counter_a0[3:0];

//
// Debug Signals
//

generate

   if (1) begin : DEBUG_SIGS_GTKWAVE

      (* keep *) wire [7:0] \@0$slideswitch ;
      assign \@0$slideswitch = L0_slideswitch_a0;
      (* keep *) wire  \@0$sseg_decimal_point_n ;
      assign \@0$sseg_decimal_point_n = L0_sseg_decimal_point_n_a0;
      (* keep *) wire [7:0] \@0$sseg_digit_n ;
      assign \@0$sseg_digit_n = L0_sseg_digit_n_a0;
      (* keep *) wire [6:0] \@0$sseg_segment_n ;
      assign \@0$sseg_segment_n = L0_sseg_segment_n_a0;

      //
      // Scope: /digit[0:0]
      //
      for (digit = 0; digit <= 0; digit=digit+1) begin : \/digit

         //
         // Scope: /leds[7:0]
         //
         for (leds = 0; leds <= 7; leds=leds+1) begin : \/leds
            (* keep *) wire  \//@0$viz_lit ;
            assign \//@0$viz_lit = L1_Digit[digit].L2_Leds[leds].L2_viz_lit_a0;
         end
      end

      //
      // Scope: /fpga_pins
      //
      if (1) begin : \/fpga_pins

         //
         // Scope: /fpga
         //
         if (1) begin : \/fpga
            (* keep *) wire [31:0] \//@0$cycle_counter ;
            assign \//@0$cycle_counter = FpgaPins_Fpga_cycle_counter_a0;
            (* keep *) wire [3:0] \//@0$display_counter ;
            assign \//@0$display_counter = FpgaPins_Fpga_display_counter_a0;
            (* keep *) wire  \//@0$reset ;
            assign \//@0$reset = FpgaPins_Fpga_reset_a0;
            (* keep *) wire [6:0] \//@0$segments ;
            assign \//@0$segments = FpgaPins_Fpga_segments_a0;
         end
      end

      //
      // Scope: /switch[7:0]
      //
      for (switch = 0; switch <= 7; switch=switch+1) begin : \/switch
         (* keep *) wire  \/@0$viz_switch ;
         assign \/@0$viz_switch = L1_Switch[switch].L1_viz_switch_a0;
      end

   end

endgenerate

// ---------- Generated Code Ends ----------
//_\TLV
   /* verilator lint_off UNOPTFLAT */
   //_\source top.tlv 72   // Instantiated from top.tlv, 146 as: m5+tt_lab.
      // Connect Tiny Tapeout I/Os to Virtual FPGA Lab.
      //_\source /raw.githubusercontent.com/osfpga/VirtualFPGALab/35e36bd144fddd75495d4cbc01c4fc50ac5bde6f/tlvlib/tinytapeoutlib.tlv 76   // Instantiated from top.tlv, 74 as: m5+tt_connections()
         assign L0_slideswitch_a0[7:0] = ui_in;
         assign L0_sseg_segment_n_a0[6:0] = ~ uo_out[6:0];
         assign L0_sseg_decimal_point_n_a0 = ~ uo_out[7];
         assign L0_sseg_digit_n_a0[7:0] = 8'b11111110;
      //_\end_source
      // Instantiate the Virtual FPGA Lab.
      //_\source /raw.githubusercontent.com/osfpga/VirtualFPGALab/a069f1e4e19adc829b53237b3e0b5d6763dc3194/tlvlib/fpgaincludes.tlv 307   // Instantiated from top.tlv, 76 as: m5+board(/top, /fpga, 7, $, , stopwatch)

         //_\source /raw.githubusercontent.com/osfpga/VirtualFPGALab/a069f1e4e19adc829b53237b3e0b5d6763dc3194/tlvlib/fpgaincludes.tlv 355   // Instantiated from /raw.githubusercontent.com/osfpga/VirtualFPGALab/a069f1e4e19adc829b53237b3e0b5d6763dc3194/tlvlib/fpgaincludes.tlv, 309 as: m4+thanks(m5__l(309)m5_eval(m5_get(BOARD_THANKS_ARGS)))
            //_/thanks

         //_\end_source

         // Board VIZ.

         // Board Image.

         //_/fpga_pins

            //_/fpga
               //_\source top.tlv 43   // Instantiated from /raw.githubusercontent.com/osfpga/VirtualFPGALab/a069f1e4e19adc829b53237b3e0b5d6763dc3194/tlvlib/fpgaincludes.tlv, 340 as: m4+stopwatch.

                  assign FpgaPins_Fpga_reset_a0 = reset;
                  assign FpgaPins_Fpga_cycle_counter_a0[31:0] = FpgaPins_Fpga_reset_a0 ? 1 :
                      FpgaPins_Fpga_cycle_counter_a1 == 20000000 ? 1 :
                      FpgaPins_Fpga_cycle_counter_a1 + 1;
                  assign FpgaPins_Fpga_display_counter_a0[3:0] =
                     FpgaPins_Fpga_reset_a0 ? 4'd0 :
                     FpgaPins_Fpga_cycle_counter_a0 == 20000000
                         ? FpgaPins_Fpga_display_counter_a1 == 9 ? 0 :
                           FpgaPins_Fpga_display_counter_a1 + 1 :
                     //default
                           FpgaPins_Fpga_display_counter_a1;
                  assign FpgaPins_Fpga_segments_a0[6:0] =
                     (FpgaPins_Fpga_display_counter_a0 == 0) ? 7'b1000000 :
                     (FpgaPins_Fpga_display_counter_a0 == 1) ? 7'b1111001 :
                     (FpgaPins_Fpga_display_counter_a0 == 2) ? 7'b0100100 :
                     (FpgaPins_Fpga_display_counter_a0 == 3) ? 7'b0110000 :
                     (FpgaPins_Fpga_display_counter_a0 == 4) ? 7'b0011001 :
                     (FpgaPins_Fpga_display_counter_a0 == 5) ? 7'b0010010 :
                     (FpgaPins_Fpga_display_counter_a0 == 6) ? 7'b0000010 :
                     (FpgaPins_Fpga_display_counter_a0 == 7) ? 7'b1111000 :
                     (FpgaPins_Fpga_display_counter_a0 == 8) ? 7'b0000000 :
                     7'b0010000 ; // '9'
                  assign uo_out = {1'b0, ~FpgaPins_Fpga_segments_a0};
                  assign uio_out = 8'b0;
                  assign uio_oe = 8'b0;
               //_\end_source

         // LEDs.

         // 7-Segment
         //_\source /raw.githubusercontent.com/osfpga/VirtualFPGALab/a069f1e4e19adc829b53237b3e0b5d6763dc3194/tlvlib/fpgaincludes.tlv 395   // Instantiated from /raw.githubusercontent.com/osfpga/VirtualFPGALab/a069f1e4e19adc829b53237b3e0b5d6763dc3194/tlvlib/fpgaincludes.tlv, 346 as: m4+fpga_sseg.
            generate for (digit = 0; digit <= 0; digit=digit+1) begin : L1_Digit //_/digit

               for (leds = 0; leds <= 7; leds=leds+1) begin : L2_Leds //_/leds

                  // For $viz_lit.
                  wire L2_viz_lit_a0;

                  assign L2_viz_lit_a0 = (! L0_sseg_digit_n_a0[digit]) && ! ((leds == 7) ? L0_sseg_decimal_point_n_a0 : L0_sseg_segment_n_a0[leds % 7]);

               end
            end endgenerate
         //_\end_source

         // slideswitches
         //_\source /raw.githubusercontent.com/osfpga/VirtualFPGALab/a069f1e4e19adc829b53237b3e0b5d6763dc3194/tlvlib/fpgaincludes.tlv 454   // Instantiated from /raw.githubusercontent.com/osfpga/VirtualFPGALab/a069f1e4e19adc829b53237b3e0b5d6763dc3194/tlvlib/fpgaincludes.tlv, 349 as: m4+fpga_switch.
            generate for (switch = 0; switch <= 7; switch=switch+1) begin : L1_Switch //_/switch

               // For $viz_switch.
               wire L1_viz_switch_a0;

               assign L1_viz_switch_a0 = L0_slideswitch_a0[switch];

            end endgenerate
         //_\end_source

         // pushbuttons

      //_\end_source
      // Label the switch inputs [0..7] (1..8 on the physical switch panel) (top-to-bottom).
      //_\source /raw.githubusercontent.com/osfpga/VirtualFPGALab/35e36bd144fddd75495d4cbc01c4fc50ac5bde6f/tlvlib/tinytapeoutlib.tlv 82   // Instantiated from top.tlv, 78 as: m5+tt_input_labels_viz(⌈"UNUSED", "UNUSED", "UNUSED", "UNUSED", "UNUSED", "UNUSED", "UNUSED", "UNUSED"⌉)
         generate for (input_label = 0; input_label <= 7; input_label=input_label+1) begin : L1_InputLabel //_/input_label

         end endgenerate
      //_\end_source

   //_\end_source

/*SV_plus*/

   // ==========================================
   // If you are using Verilog for your design,
   // your Verilog logic goes here.
   // Note, output assignments are in my_design.
   // ==========================================

//_\SV
endmodule

// Undefine macros defined by SandPiper.
`undef BOGUS_USE


/*
 * Copyright (c) 2024 Anish Singhani
 * SPDX-License-Identifier: Apache-2.0
 */

`default_nettype none

module tt_um_asinghani_tinywspr (
    input  wire [7:0] ui_in,    // Dedicated inputs
    output wire [7:0] uo_out,   // Dedicated outputs
    input  wire [7:0] uio_in,   // IOs: Input path
    output wire [7:0] uio_out,  // IOs: Output path
    output wire [7:0] uio_oe,   // IOs: Enable path (active high: 0=input, 1=output)
    input  wire       ena,      // always 1 when the design is powered, so you can ignore it
    input  wire       clk,      // clock
    input  wire       rst_n     // reset_n - low to reset
);

    assign uio_out = 0;
    assign uio_oe  = 0;

    reg config_start0, config_start1, config_start2;
    always @(posedge clk) begin
        config_start0 <= ui_in[1];
        config_start1 <= config_start0;
        config_start2 <= config_start1;
    end

    reg rf_start0, rf_start1, rf_start2;
    always @(posedge clk) begin
        rf_start0 <= ui_in[2];
        rf_start1 <= rf_start0;
        rf_start2 <= rf_start1;
    end

    reg config_valid0, config_valid1, config_valid2, config_validlast;
    always @(posedge clk) begin
        config_valid0 <= ui_in[0];
        config_valid1 <= config_valid0;
        config_valid2 <= config_valid1;
        config_validlast <= config_valid2;
    end

    TopLevel tl (
        .clock(clk),
        .reset(!rst_n),
        .io_config_bits_in(uio_in),
        .io_config_valid_in(config_valid2 && ~config_validlast),
        .io_config_start(config_start2),
        .io_rf_start(rf_start2),
        .io_rf_out(uo_out[0]),
        .io_bit_out(uo_out[7:6])
    );

    assign uo_out[1] = uo_out[0];
    assign uo_out[5:2] = 0;

endmodule

module StringEncoder (
	clock,
	reset,
	io_config_in_valid,
	io_config_in_bits,
	io_start,
	io_done,
	io_bit_out_valid,
	io_bit_out_bits
);
	input clock;
	input reset;
	input io_config_in_valid;
	input [7:0] io_config_in_bits;
	input io_start;
	output wire io_done;
	output wire io_bit_out_valid;
	output wire io_bit_out_bits;
	reg [3:0] state;
	reg [4:0] pc;
	reg [3:0] instr_op;
	reg [7:0] instr_value;
	reg [27:0] accum;
	reg [27:0] mul_reg;
	reg [27:0] reg_n;
	reg [5:0] power_dbm;
	reg [31:0] conv_reg;
	wire _GEN = state == 4'h0;
	wire _GEN_0 = state == 4'h1;
	wire _GEN_1 = state == 4'h2;
	wire _GEN_2 = instr_op == 4'h0;
	wire _GEN_3 = instr_op == 4'h1;
	wire _GEN_4 = instr_op == 4'h2;
	wire _GEN_5 = instr_op == 4'h3;
	wire _GEN_6 = instr_op == 4'h4;
	wire _GEN_7 = instr_op == 4'h5;
	wire _GEN_8 = instr_op == 4'h6;
	wire _GEN_9 = _GEN_5 | _GEN_6;
	wire _GEN_10 = _GEN | _GEN_0;
	reg io_bit_out_REG_valid;
	reg io_bit_out_REG_bits;
	reg bit_out_tmp_valid_REG;
	reg bit_out_tmp_valid_REG_1;
	reg bit_out_tmp_valid_REG_2;
	reg REG;
	reg REG_1;
	always @(posedge clock) begin : sv2v_autoblock_1
		reg [255:0] _GEN_11;
		reg _GEN_12;
		reg _GEN_13;
		reg _GEN_14;
		reg _GEN_15;
		reg _GEN_16;
		reg _GEN_17;
		reg _GEN_18;
		reg _GEN_19;
		reg _GEN_20;
		reg _GEN_21;
		reg bit_tmp_valid;
		reg [127:0] _GEN_22;
		_GEN_11 = 256'h00000000000000030a0112b3020a0000000a051b0a041b0a031b020a01240000;
		_GEN_12 = _GEN_2 | _GEN_3;
		_GEN_13 = instr_op == 4'h7;
		_GEN_14 = state == 4'h3;
		_GEN_15 = state == 4'h4;
		_GEN_16 = state == 4'h5;
		_GEN_17 = _GEN_14 | _GEN_15;
		_GEN_18 = state == 4'h6;
		_GEN_19 = state == 4'h7;
		_GEN_20 = state == 4'h8;
		_GEN_21 = ((_GEN | _GEN_0) | _GEN_1) | _GEN_17;
		bit_tmp_valid = ~_GEN_21 & (_GEN_16 | _GEN_18 ? ~instr_value[0] : (_GEN_19 ? ~(|instr_value) : (_GEN_20 ? ~instr_value[0] : (state == 4'h9) & (~(|instr_value) | ~instr_value[0]))));
		if (reset)
			state <= 4'h0;
		else begin : sv2v_autoblock_2
			reg [63:0] _GEN_23;
			_GEN_23 = {state, state, state, state, 4'h0, (|instr_value ? state : 4'hb), (|instr_value ? state : 4'ha), (|instr_value ? state : 4'h9), (|instr_value ? state : 4'h8), (|instr_value ? state : 4'h7), (|instr_value ? state : 4'h6), 5'h0a, (io_config_in_valid ? 3'h4 : 3'h3), (_GEN_2 ? 4'h1 : (_GEN_3 ? {2'h0, (io_config_in_valid ? 2'h1 : 2'h2)} : (_GEN_4 ? {2'h0, (|instr_value ? 2'h2 : 2'h1)} : (_GEN_9 ? 4'h1 : (_GEN_7 ? {2'h0, (io_config_in_valid ? 2'h1 : 2'h2)} : (_GEN_8 ? {2'h0, (io_config_in_valid ? 2'h1 : 2'h2)} : (_GEN_13 ? 4'h1 : {2'h0, instr_op == 4'h8, 1'h1}))))))), 4'h2, (io_start ? 4'h1 : state)};
			state <= _GEN_23[state * 4+:4];
		end
		if (_GEN) begin
			if (io_start)
				pc <= 5'h00;
		end
		else if (_GEN_0) begin
			pc <= pc + 5'h01;
			mul_reg <= 28'h0000000;
		end
		else if ((~_GEN_1 | _GEN_12) | ~_GEN_4)
			;
		else
			mul_reg <= mul_reg + accum;
		if (_GEN | ~_GEN_0)
			;
		else begin : sv2v_autoblock_3
			reg [127:0] _GEN_24;
			_GEN_24 = 128'h00000086252462507312312312121210;
			instr_op <= _GEN_24[pc * 4+:4];
		end
		_GEN_22 = {instr_value, instr_value, instr_value, instr_value, instr_value, instr_value - 8'h01, (|instr_value ? instr_value - 8'h01 : 8'h80), (|instr_value ? instr_value - 8'h01 : 8'h3d), (|instr_value ? instr_value - 8'h01 : 8'h0b), (|instr_value ? instr_value - 8'h01 : 8'h01), (|instr_value ? instr_value - 8'h01 : 8'h1d), 8'h37, instr_value, (_GEN_12 | ~_GEN_4 ? instr_value : instr_value - 8'h01), _GEN_11[pc * 8+:8], instr_value};
		instr_value <= _GEN_22[state * 8+:8];
		if (~_GEN_10) begin
			if (_GEN_1) begin
				if (_GEN_2)
					accum <= 28'h0000000;
				else begin : sv2v_autoblock_4
					reg [27:0] _dec_res_T;
					_dec_res_T = accum + {21'h000000, ((_GEN_10 | ~_GEN_1) | _GEN_2 ? 7'h00 : (_GEN_3 ? (io_config_in_valid ? (io_config_in_bits == 8'h20 ? 7'h24 : (io_config_in_bits < 8'h3a ? io_config_in_bits[6:0] - 7'h30 : io_config_in_bits[6:0] - 7'h37)) : 7'h00) : (_GEN_4 | _GEN_9 ? 7'h00 : (_GEN_7 ? (io_config_in_valid ? io_config_in_bits[6:0] + 7'h3f : 7'h00) : (_GEN_8 & io_config_in_valid ? io_config_in_bits[6:0] - 7'h30 : 7'h00)))))};
					if (_GEN_3) begin
						if (io_config_in_valid)
							accum <= _dec_res_T;
					end
					else if (_GEN_4) begin
						if (~(|instr_value))
							accum <= mul_reg;
					end
					else if (_GEN_9) begin : sv2v_autoblock_5
						reg _sub_res_T_2;
						reg [27:0] _GEN_25;
						_sub_res_T_2 = instr_op == 4'h4;
						_GEN_25 = {20'h00000, instr_value};
						accum <= (_sub_res_T_2 ? _GEN_25 : accum) - (_sub_res_T_2 ? accum : _GEN_25);
					end
					else if ((_GEN_7 | _GEN_8) & io_config_in_valid)
						accum <= _dec_res_T;
				end
				if (((((((_GEN_2 | _GEN_3) | _GEN_4) | _GEN_5) | _GEN_6) | _GEN_7) | _GEN_8) | ~_GEN_13)
					;
				else
					reg_n <= accum;
			end
			else begin
				if (((_GEN_14 | _GEN_15) | _GEN_16) | ~(_GEN_18 & ~instr_value[0]))
					;
				else
					accum <= {accum[26:0], 1'h0};
				if (_GEN_17 | ~(_GEN_16 & ~instr_value[0]))
					;
				else
					reg_n <= {reg_n[26:0], 1'h0};
			end
		end
		if (~((_GEN | _GEN_0) | _GEN_1)) begin
			if (_GEN_14) begin
				if (io_config_in_valid)
					power_dbm <= io_config_in_bits[5:0];
			end
			else if ((((_GEN_15 | _GEN_16) | _GEN_18) | _GEN_19) | ~(_GEN_20 & ~instr_value[0]))
				;
			else
				power_dbm <= {power_dbm[4:0], 1'h0};
		end
		if (bit_tmp_valid)
			conv_reg <= {conv_reg[30:0], ~_GEN_21 & (_GEN_16 ? reg_n[27] : (_GEN_18 ? accum[14] : _GEN_19 | (_GEN_20 & power_dbm[5])))};
		else if (_GEN & io_start)
			conv_reg <= 32'h00000000;
		io_bit_out_REG_valid <= bit_out_tmp_valid_REG | bit_out_tmp_valid_REG_2;
		io_bit_out_REG_bits <= (REG_1 ? ^(conv_reg & 32'he4613c47) : ^(conv_reg & 32'hf2d05351));
		bit_out_tmp_valid_REG <= bit_tmp_valid;
		bit_out_tmp_valid_REG_1 <= bit_tmp_valid;
		bit_out_tmp_valid_REG_2 <= bit_out_tmp_valid_REG_1;
		REG <= bit_tmp_valid;
		REG_1 <= REG;
	end
	assign io_done = state == 4'hb;
	assign io_bit_out_valid = io_bit_out_REG_valid;
	assign io_bit_out_bits = io_bit_out_REG_bits;
endmodule
module BitGenerator (
	clock,
	reset,
	io_config_in_valid,
	io_config_in_bits,
	io_start,
	io_bit_out_ready,
	io_bit_out_bits
);
	input clock;
	input reset;
	input io_config_in_valid;
	input [7:0] io_config_in_bits;
	input io_start;
	input io_bit_out_ready;
	output wire [1:0] io_bit_out_bits;
	wire _se_io_done;
	wire _se_io_bit_out_valid;
	wire _se_io_bit_out_bits;
	wire [255:0] _GEN = 256'hfffffffffffffffffffffffc63580ca0e2cdc9045634955858b340a407a47103;
	reg regs_0;
	reg regs_1;
	reg regs_2;
	reg regs_3;
	reg regs_4;
	reg regs_5;
	reg regs_6;
	reg regs_7;
	reg regs_8;
	reg regs_9;
	reg regs_10;
	reg regs_11;
	reg regs_12;
	reg regs_13;
	reg regs_14;
	reg regs_15;
	reg regs_16;
	reg regs_17;
	reg regs_18;
	reg regs_19;
	reg regs_20;
	reg regs_21;
	reg regs_22;
	reg regs_23;
	reg regs_24;
	reg regs_25;
	reg regs_26;
	reg regs_27;
	reg regs_28;
	reg regs_29;
	reg regs_30;
	reg regs_31;
	reg regs_32;
	reg regs_33;
	reg regs_34;
	reg regs_35;
	reg regs_36;
	reg regs_37;
	reg regs_38;
	reg regs_39;
	reg regs_40;
	reg regs_41;
	reg regs_42;
	reg regs_43;
	reg regs_44;
	reg regs_45;
	reg regs_46;
	reg regs_47;
	reg regs_48;
	reg regs_49;
	reg regs_50;
	reg regs_51;
	reg regs_52;
	reg regs_53;
	reg regs_54;
	reg regs_55;
	reg regs_56;
	reg regs_57;
	reg regs_58;
	reg regs_59;
	reg regs_60;
	reg regs_61;
	reg regs_62;
	reg regs_63;
	reg regs_64;
	reg regs_65;
	reg regs_66;
	reg regs_67;
	reg regs_68;
	reg regs_69;
	reg regs_70;
	reg regs_71;
	reg regs_72;
	reg regs_73;
	reg regs_74;
	reg regs_75;
	reg regs_76;
	reg regs_77;
	reg regs_78;
	reg regs_79;
	reg regs_80;
	reg regs_81;
	reg regs_82;
	reg regs_83;
	reg regs_84;
	reg regs_85;
	reg regs_86;
	reg regs_87;
	reg regs_88;
	reg regs_89;
	reg regs_90;
	reg regs_91;
	reg regs_92;
	reg regs_93;
	reg regs_94;
	reg regs_95;
	reg regs_96;
	reg regs_97;
	reg regs_98;
	reg regs_99;
	reg regs_100;
	reg regs_101;
	reg regs_102;
	reg regs_103;
	reg regs_104;
	reg regs_105;
	reg regs_106;
	reg regs_107;
	reg regs_108;
	reg regs_109;
	reg regs_110;
	reg regs_111;
	reg regs_112;
	reg regs_113;
	reg regs_114;
	reg regs_115;
	reg regs_116;
	reg regs_117;
	reg regs_118;
	reg regs_119;
	reg regs_120;
	reg regs_121;
	reg regs_122;
	reg regs_123;
	reg regs_124;
	reg regs_125;
	reg regs_126;
	reg regs_127;
	reg regs_128;
	reg regs_129;
	reg regs_130;
	reg regs_131;
	reg regs_132;
	reg regs_133;
	reg regs_134;
	reg regs_135;
	reg regs_136;
	reg regs_137;
	reg regs_138;
	reg regs_139;
	reg regs_140;
	reg regs_141;
	reg regs_142;
	reg regs_143;
	reg regs_144;
	reg regs_145;
	reg regs_146;
	reg regs_147;
	reg regs_148;
	reg regs_149;
	reg regs_150;
	reg regs_151;
	reg regs_152;
	reg regs_153;
	reg regs_154;
	reg regs_155;
	reg regs_156;
	reg regs_157;
	reg regs_158;
	reg regs_159;
	reg regs_160;
	reg regs_161;
	reg [7:0] ctr;
	always @(posedge clock)
		if (io_bit_out_ready) begin
			regs_0 <= regs_81;
			regs_1 <= regs_82;
			regs_2 <= regs_83;
			regs_3 <= regs_84;
			regs_4 <= regs_85;
			regs_5 <= regs_86;
			regs_6 <= regs_87;
			regs_7 <= regs_88;
			regs_8 <= regs_89;
			regs_9 <= regs_90;
			regs_10 <= regs_91;
			regs_11 <= regs_92;
			regs_12 <= regs_93;
			regs_13 <= regs_94;
			regs_14 <= regs_95;
			regs_15 <= regs_96;
			regs_16 <= regs_97;
			regs_17 <= regs_98;
			regs_18 <= regs_99;
			regs_19 <= regs_100;
			regs_20 <= regs_101;
			regs_21 <= regs_102;
			regs_22 <= regs_103;
			regs_23 <= regs_104;
			regs_24 <= regs_105;
			regs_25 <= regs_106;
			regs_26 <= regs_107;
			regs_27 <= regs_108;
			regs_28 <= regs_109;
			regs_29 <= regs_110;
			regs_30 <= regs_111;
			regs_31 <= regs_112;
			regs_32 <= regs_113;
			regs_33 <= regs_114;
			regs_34 <= regs_115;
			regs_35 <= regs_116;
			regs_36 <= regs_117;
			regs_37 <= regs_118;
			regs_38 <= regs_119;
			regs_39 <= regs_120;
			regs_40 <= regs_121;
			regs_41 <= regs_122;
			regs_42 <= regs_123;
			regs_43 <= regs_124;
			regs_44 <= regs_125;
			regs_45 <= regs_126;
			regs_46 <= regs_127;
			regs_47 <= regs_128;
			regs_48 <= regs_129;
			regs_49 <= regs_130;
			regs_50 <= regs_131;
			regs_51 <= regs_132;
			regs_52 <= regs_133;
			regs_53 <= regs_134;
			regs_54 <= regs_135;
			regs_55 <= regs_136;
			regs_56 <= regs_137;
			regs_57 <= regs_138;
			regs_58 <= regs_139;
			regs_59 <= regs_140;
			regs_60 <= regs_141;
			regs_61 <= regs_142;
			regs_62 <= regs_143;
			regs_63 <= regs_144;
			regs_64 <= regs_145;
			regs_65 <= regs_146;
			regs_66 <= regs_147;
			regs_67 <= regs_148;
			regs_68 <= regs_149;
			regs_69 <= regs_150;
			regs_70 <= regs_151;
			regs_71 <= regs_152;
			regs_72 <= regs_153;
			regs_73 <= regs_154;
			regs_74 <= regs_155;
			regs_75 <= regs_156;
			regs_76 <= regs_157;
			regs_77 <= regs_158;
			regs_78 <= regs_159;
			regs_79 <= regs_160;
			regs_80 <= regs_161;
			regs_81 <= regs_41;
			regs_82 <= regs_42;
			regs_83 <= regs_43;
			regs_84 <= regs_44;
			regs_85 <= regs_0;
			regs_86 <= regs_45;
			regs_87 <= regs_46;
			regs_88 <= regs_47;
			regs_89 <= regs_48;
			regs_90 <= regs_49;
			regs_91 <= regs_50;
			regs_92 <= regs_51;
			regs_93 <= regs_52;
			regs_94 <= regs_53;
			regs_95 <= regs_54;
			regs_96 <= regs_55;
			regs_97 <= regs_56;
			regs_98 <= regs_57;
			regs_99 <= regs_58;
			regs_100 <= regs_59;
			regs_101 <= regs_60;
			regs_102 <= regs_61;
			regs_103 <= regs_62;
			regs_104 <= regs_63;
			regs_105 <= regs_64;
			regs_106 <= regs_65;
			regs_107 <= regs_66;
			regs_108 <= regs_67;
			regs_109 <= regs_68;
			regs_110 <= regs_69;
			regs_111 <= regs_70;
			regs_112 <= regs_71;
			regs_113 <= regs_72;
			regs_114 <= regs_73;
			regs_115 <= regs_74;
			regs_116 <= regs_75;
			regs_117 <= regs_76;
			regs_118 <= regs_77;
			regs_119 <= regs_78;
			regs_120 <= regs_79;
			regs_121 <= regs_80;
			regs_122 <= regs_21;
			regs_123 <= regs_22;
			regs_124 <= regs_23;
			regs_125 <= regs_24;
			regs_126 <= regs_25;
			regs_127 <= regs_26;
			regs_128 <= regs_27;
			regs_129 <= regs_28;
			regs_130 <= regs_29;
			regs_131 <= regs_30;
			regs_132 <= regs_31;
			regs_133 <= regs_32;
			regs_134 <= regs_33;
			regs_135 <= regs_34;
			regs_136 <= regs_35;
			regs_137 <= regs_36;
			regs_138 <= regs_37;
			regs_139 <= regs_38;
			regs_140 <= regs_39;
			regs_141 <= regs_40;
			regs_142 <= regs_11;
			regs_143 <= regs_12;
			regs_144 <= regs_13;
			regs_145 <= regs_14;
			regs_146 <= regs_15;
			regs_147 <= regs_16;
			regs_148 <= regs_17;
			regs_149 <= regs_18;
			regs_150 <= regs_19;
			regs_151 <= regs_20;
			regs_152 <= regs_6;
			regs_153 <= regs_7;
			regs_154 <= regs_8;
			regs_155 <= regs_9;
			regs_156 <= regs_10;
			regs_157 <= regs_3;
			regs_158 <= regs_4;
			regs_159 <= regs_5;
			regs_160 <= regs_2;
			regs_161 <= regs_1;
			ctr <= ctr + 8'h01;
		end
		else begin
			if (_se_io_bit_out_valid) begin
				regs_0 <= regs_1;
				regs_1 <= regs_2;
				regs_2 <= regs_3;
				regs_3 <= regs_4;
				regs_4 <= regs_5;
				regs_5 <= regs_6;
				regs_6 <= regs_7;
				regs_7 <= regs_8;
				regs_8 <= regs_9;
				regs_9 <= regs_10;
				regs_10 <= regs_11;
				regs_11 <= regs_12;
				regs_12 <= regs_13;
				regs_13 <= regs_14;
				regs_14 <= regs_15;
				regs_15 <= regs_16;
				regs_16 <= regs_17;
				regs_17 <= regs_18;
				regs_18 <= regs_19;
				regs_19 <= regs_20;
				regs_20 <= regs_21;
				regs_21 <= regs_22;
				regs_22 <= regs_23;
				regs_23 <= regs_24;
				regs_24 <= regs_25;
				regs_25 <= regs_26;
				regs_26 <= regs_27;
				regs_27 <= regs_28;
				regs_28 <= regs_29;
				regs_29 <= regs_30;
				regs_30 <= regs_31;
				regs_31 <= regs_32;
				regs_32 <= regs_33;
				regs_33 <= regs_34;
				regs_34 <= regs_35;
				regs_35 <= regs_36;
				regs_36 <= regs_37;
				regs_37 <= regs_38;
				regs_38 <= regs_39;
				regs_39 <= regs_40;
				regs_40 <= regs_41;
				regs_41 <= regs_42;
				regs_42 <= regs_43;
				regs_43 <= regs_44;
				regs_44 <= regs_45;
				regs_45 <= regs_46;
				regs_46 <= regs_47;
				regs_47 <= regs_48;
				regs_48 <= regs_49;
				regs_49 <= regs_50;
				regs_50 <= regs_51;
				regs_51 <= regs_52;
				regs_52 <= regs_53;
				regs_53 <= regs_54;
				regs_54 <= regs_55;
				regs_55 <= regs_56;
				regs_56 <= regs_57;
				regs_57 <= regs_58;
				regs_58 <= regs_59;
				regs_59 <= regs_60;
				regs_60 <= regs_61;
				regs_61 <= regs_62;
				regs_62 <= regs_63;
				regs_63 <= regs_64;
				regs_64 <= regs_65;
				regs_65 <= regs_66;
				regs_66 <= regs_67;
				regs_67 <= regs_68;
				regs_68 <= regs_69;
				regs_69 <= regs_70;
				regs_70 <= regs_71;
				regs_71 <= regs_72;
				regs_72 <= regs_73;
				regs_73 <= regs_74;
				regs_74 <= regs_75;
				regs_75 <= regs_76;
				regs_76 <= regs_77;
				regs_77 <= regs_78;
				regs_78 <= regs_79;
				regs_79 <= regs_80;
				regs_80 <= regs_81;
				regs_81 <= regs_82;
				regs_82 <= regs_83;
				regs_83 <= regs_84;
				regs_84 <= regs_85;
				regs_85 <= regs_86;
				regs_86 <= regs_87;
				regs_87 <= regs_88;
				regs_88 <= regs_89;
				regs_89 <= regs_90;
				regs_90 <= regs_91;
				regs_91 <= regs_92;
				regs_92 <= regs_93;
				regs_93 <= regs_94;
				regs_94 <= regs_95;
				regs_95 <= regs_96;
				regs_96 <= regs_97;
				regs_97 <= regs_98;
				regs_98 <= regs_99;
				regs_99 <= regs_100;
				regs_100 <= regs_101;
				regs_101 <= regs_102;
				regs_102 <= regs_103;
				regs_103 <= regs_104;
				regs_104 <= regs_105;
				regs_105 <= regs_106;
				regs_106 <= regs_107;
				regs_107 <= regs_108;
				regs_108 <= regs_109;
				regs_109 <= regs_110;
				regs_110 <= regs_111;
				regs_111 <= regs_112;
				regs_112 <= regs_113;
				regs_113 <= regs_114;
				regs_114 <= regs_115;
				regs_115 <= regs_116;
				regs_116 <= regs_117;
				regs_117 <= regs_118;
				regs_118 <= regs_119;
				regs_119 <= regs_120;
				regs_120 <= regs_121;
				regs_121 <= regs_122;
				regs_122 <= regs_123;
				regs_123 <= regs_124;
				regs_124 <= regs_125;
				regs_125 <= regs_126;
				regs_126 <= regs_127;
				regs_127 <= regs_128;
				regs_128 <= regs_129;
				regs_129 <= regs_130;
				regs_130 <= regs_131;
				regs_131 <= regs_132;
				regs_132 <= regs_133;
				regs_133 <= regs_134;
				regs_134 <= regs_135;
				regs_135 <= regs_136;
				regs_136 <= regs_137;
				regs_137 <= regs_138;
				regs_138 <= regs_139;
				regs_139 <= regs_140;
				regs_140 <= regs_141;
				regs_141 <= regs_142;
				regs_142 <= regs_143;
				regs_143 <= regs_144;
				regs_144 <= regs_145;
				regs_145 <= regs_146;
				regs_146 <= regs_147;
				regs_147 <= regs_148;
				regs_148 <= regs_149;
				regs_149 <= regs_150;
				regs_150 <= regs_151;
				regs_151 <= regs_152;
				regs_152 <= regs_153;
				regs_153 <= regs_154;
				regs_154 <= regs_155;
				regs_155 <= regs_156;
				regs_156 <= regs_157;
				regs_157 <= regs_158;
				regs_158 <= regs_159;
				regs_159 <= regs_160;
				regs_160 <= regs_161;
				regs_161 <= _se_io_bit_out_bits;
			end
			if (_se_io_done)
				ctr <= 8'h00;
		end
	StringEncoder se(
		.clock(clock),
		.reset(reset),
		.io_config_in_valid(io_config_in_valid),
		.io_config_in_bits(io_config_in_bits),
		.io_start(io_start),
		.io_done(_se_io_done),
		.io_bit_out_valid(_se_io_bit_out_valid),
		.io_bit_out_bits(_se_io_bit_out_bits)
	);
	assign io_bit_out_bits = {regs_0, _GEN[ctr]};
endmodule
module TopLevel (
	clock,
	reset,
	io_config_bits_in,
	io_config_valid_in,
	io_config_start,
	io_rf_start,
	io_rf_out,
	io_bit_out
);
	input clock;
	input reset;
	input [7:0] io_config_bits_in;
	input io_config_valid_in;
	input io_config_start;
	input io_rf_start;
	output wire io_rf_out;
	output wire [1:0] io_bit_out;
	wire [1:0] _se_io_bit_out_bits;
	reg [7:0] config_regs_0;
	reg [7:0] config_regs_1;
	reg [7:0] config_regs_2;
	reg [7:0] config_regs_3;
	reg [7:0] config_regs_4;
	reg [7:0] config_regs_5;
	reg [7:0] config_regs_6;
	reg [7:0] config_regs_7;
	reg [7:0] config_regs_8;
	reg [7:0] config_regs_9;
	reg [31:0] symbol_time_ctr;
	reg [31:0] osc_time_ctr;
	reg [7:0] symbol_ctr;
	wire _GEN = symbol_time_ctr == 32'h00000000;
	always @(posedge clock) begin : sv2v_autoblock_1
		reg [31:0] symbol_time;
		symbol_time = {config_regs_0, config_regs_1, config_regs_2, config_regs_3};
		if (io_config_valid_in) begin
			config_regs_0 <= config_regs_1;
			config_regs_1 <= config_regs_2;
			config_regs_2 <= config_regs_3;
			config_regs_3 <= config_regs_4;
			config_regs_4 <= config_regs_5;
			config_regs_5 <= config_regs_6;
			config_regs_6 <= config_regs_7;
			config_regs_7 <= config_regs_8;
			config_regs_8 <= config_regs_9;
			config_regs_9 <= io_config_bits_in;
		end
		if (_GEN) begin
			symbol_time_ctr <= symbol_time;
			symbol_ctr <= symbol_ctr - 8'h01;
		end
		else begin
			if (|symbol_ctr)
				symbol_time_ctr <= symbol_time_ctr - 32'h00000001;
			else if (io_rf_start)
				symbol_time_ctr <= symbol_time;
			if (io_rf_start)
				symbol_ctr <= 8'ha2;
		end
		if (|symbol_ctr)
			osc_time_ctr <= (osc_time_ctr + {config_regs_4, config_regs_5, config_regs_6, config_regs_7}) + {14'h0000, {16'h0000, _se_io_bit_out_bits} * {2'h0, config_regs_8, config_regs_9}};
		else if (io_rf_start)
			osc_time_ctr <= 32'h00000000;
	end
	BitGenerator se(
		.clock(clock),
		.reset(reset),
		.io_config_in_valid(io_config_valid_in),
		.io_config_in_bits(io_config_bits_in),
		.io_start(io_config_start),
		.io_bit_out_ready(_GEN),
		.io_bit_out_bits(_se_io_bit_out_bits)
	);
	assign io_rf_out = osc_time_ctr[31];
	assign io_bit_out = _se_io_bit_out_bits;
endmodule


/*
 * Copyright (c) 2024 Barak Hoffer
 * SPDX-License-Identifier: Apache-2.0
 */

`default_nettype none

module tt_um_vga_snake (
    input  wire [7:0] ui_in,    // Dedicated inputs
    output wire [7:0] uo_out,   // Dedicated outputs
    input  wire [7:0] uio_in,   // IOs: Input path
    output wire [7:0] uio_out,  // IOs: Output path
    output wire [7:0] uio_oe,   // IOs: Enable path (active high: 0=input, 1=output)
    input  wire       ena,      // always 1 when the design is powered, so you can ignore it
    input  wire       clk,      // clock
    input  wire       rst_n     // reset_n - low to reset
);

  // All output pins must be assigned. If not used, assign to 0.
  assign uio_out = 0;
  assign uio_oe  = 0;

  assign uio_out = 8'b0;
  assign uio_oe  = 8'b0;

  // List all unused inputs to prevent warnings
  wire _unused = &{ena, uio_in, ui_in[7:4], 1'b0};

  wire [5:0] rrggbb, rrggbb_snake;
  wire [9:0] x_px;  // X position for actual pixel.
  wire [9:0] y_px;  // Y position for actual pixel.
  wire hsync, vsync, activevideo;

  assign uo_out[0] = rrggbb[5]; // R[1]
  assign uo_out[1] = rrggbb[3]; // G[1]
  assign uo_out[2] = rrggbb[1]; // B[1]
  assign uo_out[3] = vsync;
  assign uo_out[4] = rrggbb[4]; // R[0]
  assign uo_out[5] = rrggbb[2]; // G[1]
  assign uo_out[6] = rrggbb[0]; // B[0]
  assign uo_out[7] = hsync;

  assign rrggbb = activevideo ? rrggbb_snake : 6'b0;

  VgaSyncGen vga_0 (
      .px_clk(clk),
      .hsync(hsync),
      .vsync(vsync),
      .x_px(x_px),
      .y_px(y_px),
      .activevideo(activevideo),
      .reset(~rst_n)
  );

  snake u_snake (
        .clk(clk),
        .rst_n(rst_n),
        .x_px(x_px),
        .y_px(y_px),
        .left(ui_in[0]),
        .right(ui_in[1]),
        .up(ui_in[2]),
        .down(ui_in[3]),
        .rrggbb(rrggbb_snake)
  );

endmodule

`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company: Ridotech
// Engineer: Juan Manuel Rico
//
// Create Date:    09:34:23 30/09/2017
// Module Name:    vga_controller
// Description:    Basic control for 640x480@72Hz VGA signal.
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created for Roland Coeurjoly (RCoeurjoly) in 640x480@85Hz.
// Revision 0.02 - Change for 640x480@60Hz.
// Revision 0.03 - Solved some mistakes.
// Revision 0.04 - Change for 640x480@72Hz and output signals 'activevideo'
//                 and 'px_clk'.
//
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module VgaSyncGen (
            input wire       px_clk,        // Input clock: 31.5MHz
            input wire       reset,         // reset
            output wire      hsync,         // Horizontal sync out
            output wire      vsync,         // Vertical sync out
            output reg [9:0] x_px,          // X position for actual pixel.
            output reg [9:0] y_px,          // Y position for actual pixel.
            output wire      activevideo
         );

    /*
    http://www.epanorama.net/faq/vga2rgb/calc.html
    [*User-Defined_mode,(640X480)]
    PIXEL_CLK   =   31500
    H_DISP      =   640
    V_DISP      =   480
    H_FPORCH    =   24
    H_SYNC      =   40
    H_BPORCH    =   128
    V_FPORCH    =   9
    V_SYNC      =   3
    V_BPORCH    =   28
    */

    // Video structure constants.
    parameter activeHvideo = 640;               // Width of visible pixels.
    parameter activeVvideo =  480;              // Height of visible lines.
    parameter hfp = 24;                         // Horizontal front porch length.
    parameter hpulse = 40;                      // Hsync pulse length.
    parameter hbp = 128;                        // Horizontal back porch length.
    parameter vfp = 9;                          // Vertical front porch length.
    parameter vpulse = 3;                       // Vsync pulse length.
    parameter vbp = 28;                         // Vertical back porch length.
    parameter blackH = hfp + hpulse + hbp;      // Hide pixels in one line.
    parameter blackV = vfp + vpulse + vbp;      // Hide lines in one frame.
    parameter hpixels = blackH + activeHvideo;  // Total horizontal pixels.
    parameter vlines = blackV + activeVvideo;   // Total lines.

    // Registers for storing the horizontal & vertical counters.
    reg [9:0] hc;
    reg [9:0] vc;

    // Counting pixels.
    always @(posedge px_clk)
    begin
        if(reset) begin
            hc <= 0;
            vc <= 0;
        end else begin
            // Keep counting until the end of the line.
            if (hc < hpixels - 1)
                hc <= hc + 1;
            else
            // When we hit the end of the line, reset the horizontal
            // counter and increment the vertical counter.
            // If vertical counter is at the end of the frame, then
            // reset that one too.
            begin
                hc <= 0;
                if (vc < vlines - 1)
                vc <= vc + 1;
            else
               vc <= 0;
            end
        end
     end

    // Generate sync pulses (active low) and active video.
    assign hsync = (hc >= hfp && hc < hfp + hpulse) ? 0:1;
    assign vsync = (vc >= vfp && vc < vfp + vpulse) ? 0:1;
    assign activevideo = (hc >= blackH && vc >= blackV) ? 1:0;

    // Generate color.
    always @(posedge px_clk)
    begin
        if(reset) begin
            x_px <= 0;
            y_px <= 0;
        end else begin
            x_px <= hc - blackH;
            y_px <= vc - blackV;
        end
     end
 endmodule
`default_nettype wire

module snake(clk, rst_n, x_px, y_px, rrggbb, left, right, up, down);
    input clk;
    input rst_n;
    input [9:0] x_px;
    input [9:0] y_px;
    input left;
    input right;
    input up;
    input down;
    output wire [5:0] rrggbb;

    localparam MAX_SIZE = 6;

    reg [MAX_SIZE*10-1:0] snakeX = {(MAX_SIZE){10'd100}}, snakeY={(MAX_SIZE){10'd100}};
    reg [9:0] appleX = 10'd150, appleY = 10'd150;
    reg [9:0] prev_y;
    reg [2:0] size = 3'd0;
    reg [9:0] appleX_n, appleY_n;
    reg [1:0] direction = 2'b01;
    reg eat_apple;
    reg game_over;

    wire [MAX_SIZE-1:0] body;
    wire [MAX_SIZE-1:0] bodySize;
    wire clk;
    wire border, apple;
    wire R, G, B;

    assign R = game_over | apple;
    assign bodySize = body[MAX_SIZE-1:0] & ({(MAX_SIZE){1'b1}} >> (MAX_SIZE-size-1));
    assign G = (|bodySize) && !game_over;
    assign B = border && !game_over;

    assign rrggbb = {R, R, G, G, B, B};

    always @(posedge clk) begin
        if (!rst_n)
            direction <= 2'b01;
        else if (left)
            direction <= 2'b00;
        else if (right)
            direction <= 2'b01;
        else if (up)
            direction <= 2'b10;
        else if (down)
            direction <= 2'b11;
    end

    always @(posedge clk)
    begin
        if(!rst_n)
            game_over <= 1'b0;
        else if((border && bodySize[0]) || (|(bodySize[MAX_SIZE-1:1]) && bodySize[0]))
            game_over <= 1'b1;
    end

    generate
        genvar i;
        for (i = 0; i < MAX_SIZE; i = i+1) begin
            assign body[i] = ((x_px > snakeX[i*10+9:i*10] && x_px < snakeX[i*10+9:i*10]+10) &&
                                (y_px > snakeY[i*10+9:i*10] && y_px < snakeY[i*10+9:i*10]+10));
        end
    endgenerate

    assign border = (x_px < 11) || (x_px > 629) || (y_px < 11) || (y_px > 469);
    assign apple = ((x_px > appleX && x_px < appleX+10) &&
                 (y_px > appleY && y_px < appleY+10));

    always @*
    begin
        case(direction)
            2'b00: begin
                appleX_n = appleX + 30;
                appleY_n = appleY + 120;
            end
            2'b01: begin
                appleX_n = appleX + 70;
                appleY_n = appleY + 140;
            end
            2'b10: begin
                appleX_n = appleX + 60;
                appleY_n = appleY + 40;
            end
            2'b11: begin
                appleX_n = appleX + 80;
                appleY_n = appleY + 20;
            end
        endcase
        if (appleX_n < 11)
            appleX_n = 11;
        if (appleX_n > 619)
            appleX_n = 310;
        if (appleY_n < 11)
            appleY_n = 11;
        if (appleY_n > 459)
            appleY_n = 250;
    end

    always @(posedge clk)
    begin
        if(!rst_n) begin
            snakeX <= {{(MAX_SIZE-1){10'd700}},10'd100};
            snakeY <= {{(MAX_SIZE-1){10'd700}},10'd100};
            appleX <= 10'd150;
            appleY <= 10'd150;
            size <= 0;
            prev_y  <= 10'b0;
            eat_apple <= 1'b0;
        end
        else
        begin
            prev_y <= y_px;
            if (prev_y != y_px && (y_px == 0)) begin
                case(direction)
                    2'b00: snakeX[9:0] <= snakeX[9:0] - 10;
                    2'b01: snakeX[9:0] <= snakeX[9:0] + 10;
                    2'b10: snakeY[9:0] <= snakeY[9:0] - 10;
                    2'b11: snakeY[9:0] <= snakeY[9:0] + 10;
                endcase
                snakeX[MAX_SIZE*10-1:10] <= snakeX[(MAX_SIZE-1)*10-1:0];
                snakeY[MAX_SIZE*10-1:10] <= snakeY[(MAX_SIZE-1)*10-1:0];

                if(eat_apple) begin
                    if (size < MAX_SIZE-1)
                        size <= size + 1;
                    eat_apple <= 0;
                    appleX <= appleX_n;
                    appleY <= appleY_n;
                end

            end
            else if((apple && bodySize[0]))
                eat_apple <= 1'b1;

        end
    end

endmodule


/*
 * Copyright (c) 2024 Applied Invention, LLC
 * SPDX-License-Identifier: Apache-2.0
 */

`default_nettype none

module tt_um_adia_psu_seq_test (
    input  wire [7:0] ui_in,    // Dedicated inputs
    output wire [7:0] uo_out,   // Dedicated outputs
    input  wire [7:0] uio_in,   // IOs: Input path
    output wire [7:0] uio_out,  // IOs: Output path
    output wire [7:0] uio_oe,   // IOs: Enable path (active high: 0=input, 1=output)
    input  wire       ena,      // always 1 when the design is powered, so you can ignore it
    input  wire       clk,      // clock
    input  wire       rst_n     // reset_n - low to reset
);

  wire [8:0] ctl0;
  wire [8:0] ctl1;
  wire r0_w2_en, r1_w3_en, r2_w0_en, r3_w1_en;

  psu_sequencer #(8) seq (clk, rst_n, ctl0, ctl1, r0_w2_en, r1_w3_en, r2_w0_en, r3_w1_en);

  assign uo_out[0] = ui_in[0];
  assign uo_out[7:1] = ui_in[0] ? ctl1[7:1] : ctl0[7:1];
  assign uio_out[0] = ctl0[0];
  assign uio_out[1] = ctl0[8];
  assign uio_out[2] = ctl1[0];
  assign uio_out[3] = ctl1[8];
  assign uio_out[4] = r0_w2_en;
  assign uio_out[5] = r1_w3_en;
  assign uio_out[6] = r2_w0_en;
  assign uio_out[7] = r3_w1_en;

  assign uio_oe = 'hff;

  // List all unused inputs to prevent warnings
  wire _unused = &{ena, 1'b0};

endmodule

/*
 * Copyright (c) 2024 Applied Invention, LLC
 * SPDX-License-Identifier: Apache-2.0
 */

`default_nettype none

module psu_sequencer #(parameter integer steps = 8) (
  input wire clk, input wire rst_n,
  output wire [steps:0] ctl0, output wire [steps:0] ctl1,
  output wire r0_w2_en, output wire r1_w3_en,
  output wire r2_w0_en, output wire r3_w1_en
);
  reg [3:0] phase;
  reg [steps-1:0] step;

  always @(posedge clk or negedge rst_n)
    if (!rst_n) begin
      phase <= 4'b1000;
      step <= 1 << (steps-1);
    end else begin
      step <= {step[steps-2:0], step[steps-1]};
      phase <= step[steps-1] ? {phase[2:0], phase[3]} : phase;
    end

  assign ctl0[0] = (phase[2] & step[steps-1]) | phase[3];
  assign ctl1[0] = (phase[3] & step[steps-1]) | phase[0];

  generate
    genvar i;
    for (i = 1; i < steps; i = i + 1) begin
      assign ctl0[i] = (phase[0] & step[i-1]) | (phase[2] & step[steps-i-1]);
      assign ctl1[i] = (phase[1] & step[i-1]) | (phase[3] & step[steps-i-1]);
    end
  endgenerate

  assign ctl0[steps] = (phase[0] & step[steps-1]) | phase[1];
  assign ctl1[steps] = (phase[1] & step[steps-1]) | phase[2];

  assign r0_w2_en = phase[1] & step[steps-1];
  assign r1_w3_en = phase[2] & step[steps-1];
  assign r2_w0_en = phase[3] & step[steps-1];
  assign r3_w1_en = phase[0] & step[steps-1];

endmodule


/*
 * Copyright (c) 2024 Daniel Burke
 * SPDX-License-Identifier: Apache-2.0
 */

`timescale 1ns / 1ps
`define default_netname none

// Begin Tiny Tapeout wrapper interface
module tt_um_drburke3_top (
    input  wire [7:0] ui_in,    // Dedicated inputs
    output wire [7:0] uo_out,   // Dedicated outputs
    input  wire [7:0] uio_in,   // IOs: Input path
    output wire [7:0] uio_out,  // IOs: Output path
    output wire [7:0] uio_oe,   // IOs: Enable path (active high: 0=input, 1=output)
    input  wire       ena,      // will go high when the design is enabled
    input  wire       clk,      // clock
    input  wire       rst_n     // reset_n - low to reset
);

  // All output pins must be assigned. If not used, assign to 0.
  /// assign uo_out  = ui_in + uio_in;  // Example: ou_out is the sum of ui_in and uio_in
  assign uio_out = 0;
  assign uio_oe  = 0;
  assign uo_out [7:3] = 0;

// Instantiate project

magnitude_comparator my_mag_comp_8b(
.A      (ui_in[7:0]),   // input A
.LT_out    (uo_out[0]),  // A less than B
.EQ_out    (uo_out[1]),  // A equal to B
.GT_out    (uo_out[2]),  // A greater than B
.B      (uio_in[7:0])  // input B
);

endmodule
// End Tiny Tapeout wrapper interface

///////////////////////////////////////////////////////////////////////
// Magnitude Comparator                                              //
//                                                                   //
// Designer: Clint Cole (Digilent)                                   //
// https://www.realdigital.org/doc/a39d855f71772426c968c0151112b476  //
//                                                                   //
// This component is bit-sliced expandable, structural code          //
// re-expressed in the AND-INV format to target optimized ABC9       //
// AIG graph synthesis in OpenLane.                                  //
//                                                                   //
// The element is scaled by repeating the comparator_bitslice module //
// as needed taking the outputs from the proceeding bit as inputs    //
// as below.                                                         //
//                                                                   //
///////////////////////////////////////////////////////////////////////
module magnitude_comparator(
    input [7:0] A,
    input [7:0] B,
    output LT_out,
    output EQ_out,
    output GT_out
    );

wire [7:0] GT_internal;
wire [7:0] EQ_internal;
wire [7:0] LT_internal;

comparator_bitslice slice_0 (
    .A(A[0]),
    .B(B[0]),
    .LT_in(1'b0),
    .EQ_in(1'b1),
    .GT_in(1'b0),
    .LT_out(LT_internal[0]),
    .EQ_out(EQ_internal[0]),
    .GT_out(GT_internal[0])
    );

comparator_bitslice slice_1 (
    .A(A[1]),
    .B(B[1]),
    .LT_in(LT_internal[0]),
    .EQ_in(EQ_internal[0]),
    .GT_in(GT_internal[0]),
    .LT_out(LT_internal[1]),
    .EQ_out(EQ_internal[1]),
    .GT_out(GT_internal[1])
    );

comparator_bitslice slice_2 (
    .A(A[2]),
    .B(B[2]),
    .LT_in(LT_internal[1]),
    .EQ_in(EQ_internal[1]),
    .GT_in(GT_internal[1]),
    .LT_out(LT_internal[2]),
    .EQ_out(EQ_internal[2]),
    .GT_out(GT_internal[2])
    );

comparator_bitslice slice_3 (
    .A(A[3]),
    .B(B[3]),
    .LT_in(LT_internal[2]),
    .EQ_in(EQ_internal[2]),
    .GT_in(GT_internal[2]),
    .LT_out(LT_internal[3]),
    .EQ_out(EQ_internal[3]),
    .GT_out(GT_internal[3])
    );

  comparator_bitslice slice_4 (
    .A(A[4]),
    .B(B[4]),
    .LT_in(LT_internal[3]),
    .EQ_in(EQ_internal[3]),
    .GT_in(GT_internal[3]),
    .LT_out(LT_internal[4]),
    .EQ_out(EQ_internal[4]),
    .GT_out(GT_internal[4])
    );

comparator_bitslice slice_5 (
    .A(A[5]),
    .B(B[5]),
    .LT_in(LT_internal[4]),
    .EQ_in(EQ_internal[4]),
    .GT_in(GT_internal[4]),
    .LT_out(LT_internal[5]),
    .EQ_out(EQ_internal[5]),
    .GT_out(GT_internal[5])
    );

comparator_bitslice slice_6 (
    .A(A[6]),
    .B(B[6]),
    .LT_in(LT_internal[5]),
    .EQ_in(EQ_internal[5]),
    .GT_in(GT_internal[5]),
    .LT_out(LT_internal[6]),
    .EQ_out(EQ_internal[6]),
    .GT_out(GT_internal[6])
    );

comparator_bitslice slice_7 (
    .A(A[7]),
    .B(B[7]),
    .LT_in(LT_internal[6]),
    .EQ_in(EQ_internal[6]),
    .GT_in(GT_internal[6]),
    .LT_out(LT_internal[7]),
    .EQ_out(EQ_internal[7]),
    .GT_out(GT_internal[7])
    );

assign LT_out = LT_internal[3];
assign EQ_out = EQ_internal[3];
assign GT_out = GT_internal[3];

endmodule

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 05/13/2024 11:36:50 AM
// Design Name:
// Module Name: comparator_bitslice
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////

module comparator_bitslice(
    input A,
    input B,
    input LT_in,
    input EQ_in,
    input GT_in,
    output LT_out,
    output EQ_out,
    output GT_out
    );

// original naive structural Verilog code as per RealDigital
// assign GT_out =  ( A & ~B ) | (~(A ^ B) & GT_in);
// re-expressed in AND-INV form for optimal processing in ABC9 AIG graph format
assign GT_out = ~(~( A & ~B ) & ~(~(~(~A & ~B) & ~(A & B)) & GT_in));

// original naive structural Verilog code as per RealDigital
// assign EQ_out =  EQ_in & (( A & B ) | (~A & ~B));
// re-expressed in AND-INV form for optimal processing in ABC9 AIG graph format
assign EQ_out = EQ_in & ~(~( A & B ) & ~(~A & ~B));

// original naive structural Verilog code as per RealDigital
// assign LT_out = ( B & ~A ) | ( ~(A ^ B) & LT_in);
// re-expressed in AND-INV form for optimal processing in ABC9 AIG graph format
assign LT_out = ~(~( B & ~A ) & ~( ~(( ~(~A & ~B)) & ~(A & B)) & LT_in));

endmodule