/*
 * Copyright (c) 2024 Eric Fogleman
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * Blocks for fully-segmented mismatch shaping encoder
 * from SEGMENTED MISMATCH-SHAPING D/A CONVERSION,
 * Fishov, Fogleman, Siragusa, Galton
 * 2002 IEEE International Symposium on Circuits and Systems (ISCAS)
 */
/* verilator lint_off DECLFILENAME */

// retiming reg
module ef_smsdac_reg #(parameter BITS = 8) (
    input i_clk,
    input i_rst_b,
    input [BITS-1:0] i_d,
    output reg [BITS-1:0] o_q );

	always @( posedge i_clk, negedge i_rst_b )
		if ( i_rst_b == 1'b0 )
			o_q <= 0;
		else
			o_q <= i_d;

endmodule

// the segmenting switching block
module ef_smsdac_mse_seg_sb (
	input i_clk,
	input i_rst_b,
	input i_r,
	input i_en,
	input i_x,
	input i_xc,
	output wire [1:0] o_y,
	output wire o_yc );

	wire odd = i_x ^ i_xc;	// input parity
	wire q;				// switching sequence

	// "carry" output (lsb weight); round up/down on odd input
	assign o_yc = odd ? q : i_x;

	// 3-level DAC outputs
	assign o_y[1] = odd & ~q;
	assign o_y[0] = ~odd | ~q;

	// switching sequence state machine
	ef_smsdac_mse_sb_sm sb_sm(
		.i_clk(i_clk),
		.i_rst_b(i_rst_b),
		.i_odd(odd),
		.i_r(i_r),
		.i_en(i_en),
		.o_q(q));

endmodule

// the binary switching block
module ef_smsdac_mse_bin_sb (
	input i_clk,
	input i_rst_b,
	input i_r,
	input i_en,
	input i_x,
	input i_xc,
	output wire [1:0] o_y) ;

	wire q;				// switching sequence
	wire odd = i_x ^ i_xc;		// input parity

	// 3-level DAC output
	// if odd, split based on switching sequence
	assign o_y[1] = odd ? q : i_xc;
	assign o_y[0] = odd ? ~q : i_xc;

	// switching sequence state machine
	ef_smsdac_mse_sb_sm sb_sm(
		.i_clk(i_clk),
		.i_rst_b(i_rst_b),
		.i_odd(odd),
		.i_r(i_r),
		.i_en(i_en),
		.o_q(q));

endmodule

// the switching sequence state machine
// updates only when sb input is odd
// i_r is a random dither bit
// i_en == 1'b0 halts state machine and routes i_r to q
module ef_smsdac_mse_sb_sm(
	input i_clk,
	input i_rst_b,
	input i_odd,
	input i_r,
	input i_en,
	output wire o_q );

	// switching sequence; update only on odd inputs
	// en == 1'b0 stops mismatch shaping (static encoder)
	reg [1:0] q;
	wire [1:0] q_d;   // next state info
	assign q_d[1] = (i_en & i_odd) ? ~q[1]: q[1];
	assign q_d[0] = (i_en & i_odd) ? ( q[1] ? i_r : ~q[0] ) : q[0];

	// enabled:  highpass shaping
	// disabled:  random shaping (whitening)
	assign o_q = i_en ? q[0] : i_r;

	always @( posedge i_clk, negedge i_rst_b ) begin
		if ( i_rst_b == 1'b0 )
			q <= 2'b00;
		else
			q <= q_d;
	end

endmodule
/* verilator lint_on DECLFILENAME */

/*
 * Copyright (c) 2024 Eric Fogleman
 * SPDX-License-Identifier: Apache-2.0
  *
 * LFSR w/ multiple tapped outputs
 * updates K states at a time to avoid correlation in tapped bits
 * From: A 3.3-V SINGLE-POLY CMOS AUDIO ADC DELTA–SIGMA MODULATOR WITH 98-DB
 * PEAK SINAD AND 105-DB PEAK SFDR, Fogleman et al
 */

/* verilator lint_off DECLFILENAME */
// n = 20, 1 + x^3 + x^n, K = 8
module ef_lfsr20_8 (
	input i_clk,
	input i_rst_b,
	input i_en,
	output wire [7:0] o_r );

	reg [19:0] q;
	assign o_r[7:0] = q[8:1];

	always @( posedge i_clk, negedge i_rst_b ) begin
		if( ~i_rst_b ) begin
			q[19:1] <= 19'b0;
			q[0] <= 1'b1;
		end
		else begin
			if ( i_en ) begin
				// jumps 8 states per clock
				q[19:12] <= q[7:0] ^ q[10:3];
				q[11:0] <= q[19:8];
			end
		end
	end

endmodule
/* verilator lint_on DECLFILENAME */

/*
 * Copyright (c) 2024 Eric Fogleman
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * 8-b fully-segmented mismatch shaping encoder
 * from SEGMENTED MISMATCH-SHAPING D/A CONVERSION,
 * Fishov, Fogleman, Siragusa, Galton
 * 2002 IEEE International Symposium on Circuits and Systems (ISCAS)
 * y0 drives 1x 3-level DAC
 * y1: 2x, y2: 4x, ..., y6: 64x
 * 128x DAC driven by x7, yc
 * i_en == 1'b0 stops mismatch shaping (static encoder)
 */
/* verilator lint_off DECLFILENAME */

// 8-b hierarchical encoder
// seg switching blocks to requantize the input
// binary switching blocks for each scaled 3-level DAC
module ef_smsdac8_mse (
	input i_clk,
	input i_rst_b,
	input i_en,
	input [7:0] i_x,
	input i_xc,
	input [7:0] i_r,
	output [13:0] o_y );	// y64[1:0], y32[1:0], ..., y1[1;0]

	// 8 layers:  input 7, output 0
	// elements numbered top to bottom.
	// signals and instances use layer, element notation:
	// u_s70 is 0th switching block in layer 7
	// y70 is output of layer 7, element 0

	// carry outs from segmenting switching blocks
	wire yc70, yc60, yc50, yc40, yc30, yc20, yc10;

	wire [1:0] y10, y20, y30, y40, y50, y60;  // to binary encoders
    // verilator lint_off UNUSEDSIGNAL
	wire [1:0] y70;	 // unused
    // verilator lint_on UNUSEDSIGNAL

	// layer 7
	ef_smsdac_mse_seg_sb u_s70(
		.i_x(i_x[0]),
		.i_xc(i_xc),
		.i_r(i_r[7]),
		.i_en(i_en),
		.i_clk(i_clk),
		.i_rst_b(i_rst_b),
		.o_yc(yc70),
		.o_y(y70[1:0]) );  // unused

	// layer 6
	ef_smsdac_mse_seg_sb u_s60(
		.i_x(i_x[1]),
		.i_xc(yc70),
		.i_r(i_r[6]),
		.i_en(i_en),
		.i_clk(i_clk),
		.i_rst_b(i_rst_b),
		.o_yc(yc60),
		.o_y(y60[1:0]) );

	ef_smsdac_mse_bin_sb u_s06(
		.i_x(y60[1]),
		.i_xc(y60[0]),
		.i_r(i_r[6]),
		.i_en(i_en),
		.i_clk(i_clk),
		.i_rst_b(i_rst_b),
		.o_y(o_y[1:0]) );	// 1*delta DAC

	// layer 5
	ef_smsdac_mse_seg_sb u_s50(
		.i_x(i_x[2]),
		.i_xc(yc60),
		.i_r(i_r[5]),
		.i_en(i_en),
		.i_clk(i_clk),
		.i_rst_b(i_rst_b),
		.o_yc(yc50),
		.o_y(y50[1:0]) );

	ef_smsdac_mse_bin_sb u_s05(
		.i_x(y50[1]),
		.i_xc(y50[0]),
		.i_r(i_r[5]),
		.i_en(i_en),
		.i_clk(i_clk),
		.i_rst_b(i_rst_b),
		.o_y(o_y[3:2]) );	// 2*delta DAC

	// layer 4
	ef_smsdac_mse_seg_sb u_s40(
		.i_x(i_x[3]),
		.i_xc(yc50),
		.i_r(i_r[4]),
		.i_en(i_en),
		.i_clk(i_clk),
		.i_rst_b(i_rst_b),
		.o_yc(yc40),
		.o_y(y40[1:0]) );

	ef_smsdac_mse_bin_sb u_s04(
		.i_x(y40[1]),
		.i_xc(y40[0]),
		.i_r(i_r[4]),
		.i_en(i_en),
		.i_clk(i_clk),
		.i_rst_b(i_rst_b),
		.o_y(o_y[5:4]) );	// 4*delta DAC

	// layer 3
	ef_smsdac_mse_seg_sb u_s30(
		.i_x(i_x[4]),
		.i_xc(yc40),
		.i_r(i_r[3]),
		.i_en(i_en),
		.i_clk(i_clk),
		.i_rst_b(i_rst_b),
		.o_yc(yc30),
		.o_y(y30[1:0]) );

	ef_smsdac_mse_bin_sb u_s03(
		.i_x(y30[1]),
		.i_xc(y30[0]),
		.i_r(i_r[3]),
		.i_en(i_en),
		.i_clk(i_clk),
		.i_rst_b(i_rst_b),
		.o_y(o_y[7:6]) );	// 8*delta DAC

	// layer 2
	ef_smsdac_mse_seg_sb u_s20(
		.i_x(i_x[5]),
		.i_xc(yc30),
		.i_r(i_r[2]),
		.i_en(i_en),
		.i_clk(i_clk),
		.i_rst_b(i_rst_b),
		.o_yc(yc20),
		.o_y(y20[1:0]) );

	ef_smsdac_mse_bin_sb u_s02(
		.i_x(y20[1]),
		.i_xc(y20[0]),
		.i_r(i_r[2]),
		.i_en(i_en),
		.i_clk(i_clk),
		.i_rst_b(i_rst_b),
		.o_y(o_y[9:8]) );	// 16*delta DAC

	// layer 1
	ef_smsdac_mse_seg_sb u_s10(
		.i_x(i_x[6]),
		.i_xc(yc20),
		.i_r(i_r[1]),
		.i_en(i_en),
		.i_clk(i_clk),
		.i_rst_b(i_rst_b),
		.o_yc(yc10),
		.o_y(y10[1:0]) );

	ef_smsdac_mse_bin_sb u_s01(
		.i_x(y10[1]),
		.i_xc(y10[0]),
		.i_r(i_r[1]),
		.i_en(i_en),
		.i_clk(i_clk),
		.i_rst_b(i_rst_b),
		.o_y(o_y[11:10]) );	// 32*delta DAC

	// layer 0
	// {i_x[7], yc10};
	// ms-segment from {input msb, final carry out}
	ef_smsdac_mse_bin_sb u_s00(
		.i_x(i_x[7]),
		.i_xc(yc10),
		.i_r(i_r[0]),
		.i_en(i_en),
		.i_clk(i_clk),
		.i_rst_b(i_rst_b),
		.o_y(o_y[13:12]) );	// 64*delta DAC

endmodule

// DAC top level
//
module ef_smsdac8_top(
    input i_clk,
    input i_rst_b,
    input i_en_enc,
    input i_en_dith,
    input [7:0] i_x,
    output wire [13:0] o_y );	// y64[1:0], y32[1:0], ..., y1[1;0]

    wire [7:0] x_sync1, x_sync2; // input data synchronizer
    wire [7:0] r;  // random dither bits
    wire [13:0] y;  // encoder outputs to final reclock

    // input data sync reg
    ef_smsdac_reg #(.BITS(8)) u_sync1(
        .i_clk(i_clk),
        .i_rst_b(i_rst_b),
        .i_d(i_x),
        .o_q(x_sync1) );

    // input data sync reg
    ef_smsdac_reg #(.BITS(8)) u_sync2(
        .i_clk(i_clk),
        .i_rst_b(i_rst_b),
        .i_d(x_sync1),
        .o_q(x_sync2) );

    // mismatch-shaping encoder
    ef_smsdac8_mse u_dac(
        .i_clk(i_clk),
        .i_rst_b(i_rst_b),
        .i_en(i_en_enc),
        .i_x(x_sync2),
        .i_xc(1'b0),  // no carry in
        .i_r(r),
        .o_y(y) );

    // LFSR
    ef_lfsr20_8 u_lfsr(
        .i_clk(i_clk),
        .i_rst_b(i_rst_b),
        .i_en(i_en_dith),
        .o_r(r) );

    // output retiming reg
    ef_smsdac_reg #(.BITS(14)) u_reg(
        .i_clk(i_clk),
        .i_rst_b(i_rst_b),
        .i_d(y),
        .o_q(o_y) );

endmodule
/* verilator lint_on DECLFILENAME */

/*
 * Copyright (c) 2024 Eric Fogleman
 * SPDX-License-Identifier: Apache-2.0
 *
 * TT project wrapper for ef_smsdac
 * 1-10 MHz Segmented mismatch-shaping DAC
 * Input clock at 1-50 MHz
 * 8-b unsigned input data on ui_in[7:0]; sync'd to clk (oversampled)
 * uo_out[7:0] connect to {64x, 32x, 16x, 8x} weight 3-level DACs
 * uio_out[7:3] optionally connect to {4x, 2x, 1x} 3-level DACs
 */

`default_nettype none

module tt_um_ejfogleman_smsdac8 (
    input  wire [7:0] ui_in,    // Dedicated inputs
    output wire [7:0] uo_out,   // Dedicated outputs
    // verilator lint_off UNUSEDSIGNAL
    input  wire [7:0] uio_in,   // IOs: Input path
    // verilator lint_off UNUSEDSIGNAL
    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
    );

  // release reset when project enabled
  wire ena_and_rst_n = ena & rst_n;

  assign uio_oe[7:0] = 8'b11111100;    // uio[7:2] used to bring out extra DAC lsbs
  assign uio_out[1:0] = 2'h0;    // uio[1:0] used as control inputs

  ef_smsdac8_top u_top(
    .i_clk(clk),
    .i_rst_b(ena_and_rst_n),
    .i_en_enc(uio_in[0]),
    .i_en_dith(uio_in[1]),
    .i_x(ui_in[7:0]),
    .o_y({uo_out[7:0],uio_out[7:2]}) );

endmodule


/*
 * Copyright (c) 2024 Your Name
 * SPDX-License-Identifier: Apache-2.0
 */
/* verilator lint_off UNUSEDSIGNAL */
`default_nettype none
	/* verilator lint_off WIDTHTRUNC */
module tt_um_ender_clock (
	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 reset;
wire clock ;
assign clock=clk;
assign reset=rst_n;
//control signel
wire [2:0]status;
parameter status_show_time=3'd0;
parameter status_show_hour=3'd1;
parameter status_show_minute=3'd2;
parameter status_show_month=3'd3;
parameter status_show_day=3'd4;
reg clock_run_flag;
reg[15:0]clock_counter;
always @(posedge clock or negedge reset)
begin
	if(!reset)
	begin
		clock_counter<=16'd0;
	end
	else
	begin
	       clock_counter<=clock_counter+16'd1;
	end
end
//second clock
wire second_flag;
wire [15:0]clock_count;
time_control #(16,0) time_control_second_flags(  .clock(clock),  .reset((reset&clock_run_flag)), .add_req(1'd1),.carry_flag(second_flag),.data_out(clock_count),.max(16'd32767) );
//second
wire second_carry;
wire [5:0]seond;
time_control #(6,0) time_control_second(  .clock(clock),  .reset((reset&clock_run_flag)), .add_req(second_flag),.carry_flag(second_carry),.data_out(seond),.max(6'd59) );
//minutes
wire [5:0]minute;
wire minute_carry;
	time_control #(6,0) time_control_minute(  .clock(clock),  .reset(reset), .add_req(second_carry||((status==status_show_minute)&&key_add_negedge)),.data_out(minute),.carry_flag(minute_carry),.max(6'd59) );
//hour
wire [4:0]hour;
wire hour_carry;
	time_control #(5,0) time_control_hour(  .clock(clock),  .reset(reset), .add_req(minute_carry||((status==status_show_hour)&&key_add_negedge)),.data_out(hour),.carry_flag(hour_carry),.max(5'd23) );
//day
wire [4:0]day;
wire[4:0]day_this_month;
wire day_carry;
	time_control #(5,1) time_control_day(  .clock(clock),  .reset(reset), .add_req(hour_carry||((status==status_show_day)&&key_add_negedge)),.data_out(day),.carry_flag(day_carry),.max(day_this_month[4:0]) );
//month
wire [3:0]month;
wire month_carry;
	time_control #(4,1) time_control_month(  .clock(clock),  .reset(reset), .add_req(day_carry||((status==status_show_month)&&key_add_negedge)),.data_out(month),.carry_flag(month_carry),.max(4'd12) );
//key
wire key_10ms_flag;
wire key_add_negedge;
wire [8:0]counter_10ms;
time_control #(9,0) time_control_10ms(  .clock(clock),  .reset(reset), .add_req(1'b1),.data_out(counter_10ms),.carry_flag(key_10ms_flag),.max(9'd327) );

key key_add(  .clock(clock),  .reset(reset), .time_flag(key_10ms_flag), .key_in(ui_in[1]), .key_out(key_add_negedge) );
wire key_mode_negedge;
key key_mode(  .clock(clock),  .reset(reset), .time_flag(key_10ms_flag), .key_in(ui_in[0]), .key_out(key_mode_negedge) );

	//clock_run_flag
	always @(posedge clock or negedge reset)
	begin
	   if(!reset)
	   begin
	       clock_run_flag<=1'd1;
	   end
	   else
	   begin
	       if((status!=status_show_time)&&(key_add_negedge))
	       begin
	           clock_run_flag<=1'd0;
	       end
	       if(status==status_show_time)
	       begin
	           clock_run_flag<=1'd1;
	       end
	   end
	end
day_of_month day_of_month_0(.month(month),.day_this_month(day_this_month));
	//status
	wire status_carry;
	time_control #(3,status_show_time) time_control_status(  .clock(clock),  .reset(reset), .add_req(key_mode_negedge),.data_out(status),.max(status_show_day[2:0]),.carry_flag(status_carry));

wire [3:0]segment_byte_control;
assign segment_byte_control=status==status_show_time?4'b1111:status==status_show_minute?4'b0011:status==status_show_hour?4'b1100:status==status_show_day?4'b0011:status==status_show_month?4'b1100:0;
segment_show segment_show1(.clock(clock),.reset(reset),.data_show(data_show),.segment(uo_out[6:0]),.byte_status(clock_counter[5:3]),.bytee(uio_out[3:0]),.segment_byte_control(segment_byte_control));
wire[11:0]data_show;
assign data_show=status==status_show_time?(ui_in[1]==1?{1'd0,hour,minute}:{2'd0,month,1'd0,day[4:0]}):status==status_show_minute?{6'd0,minute}:status==status_show_hour?{1'd0,hour,6'd0}:status==status_show_day?{6'd0,1'd0,day[4:0]}:status==status_show_month?{2'd0,month,6'd0}:0;
assign uio_out[7:4]=data_show[3:0];
assign uio_oe[7:0]=8'hff;
wire segment_D56;
assign segment_D56=(status==status_show_time)&&clock_counter[13]&&(ui_in[1]==1'd1);
assign uo_out[7]=segment_D56;

endmodule
/* verilator lint_on UNUSEDSIGNAL */

/* verilator lint_off UNUSEDSIGNAL */
module segment_show(input wire clock,input wire reset,input  wire [11:0]data_show,
input wire [2:0]byte_status,output wire [3:0]bytee,output wire [6:0]segment,input wire [3:0]segment_byte_control);

wire [5:0]data_showing;
assign data_showing=byte_status==0?data_show[5:0]:byte_status==2?data_show[5:0]:byte_status==4?data_show[11:6]:byte_status==6?data_show[11:6]:0;
wire [3:0]segment_show;
wire [6:0] segment_show_code;
	/* verilator lint_off WIDTHTRUNC  */
	wire [3:0]hundreds;
	wire [3:0]tens;
	assign hundreds= (data_showing / 10) ;
	assign tens= (data_showing % 10) ;
		/* verilator lint_on WIDTHTRUNC  */
	assign segment_show = (byte_status == 3'd0) ?tens:
                      (byte_status == 3'd2) ?hundreds:
                      (byte_status == 3'd4) ? tens  :
                      (byte_status == 3'd6) ?hundreds  : 4'd0;

segment_code segment_code_0(.number(segment_show),.code(segment_show_code));
assign segment=segment_show_code;
assign bytee=byte_status==0?4'b1110|(~segment_byte_control):byte_status==2?4'b1101|(~segment_byte_control):byte_status==4?4'b1011|(~segment_byte_control):byte_status==6?4'b0111|(~segment_byte_control):4'b1111;
endmodule
/* verilator lint_on UNUSEDSIGNAL */

//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2024/05/06 22:47:05
// Design Name:
// Module Name: time_control
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////

module time_control #(parameter BUS_WIDTH = 6,VALUE_INIT   = 0)(
input  clock,input  reset,
input [BUS_WIDTH-1:0]max,
input add_req,output reg carry_flag,
output reg [BUS_WIDTH-1:0]data_out
    );

 reg [BUS_WIDTH-1:0]data_old;
    	always @(posedge clock or negedge reset)
	begin
		if(!reset)
		begin
			data_out<=VALUE_INIT;
			carry_flag<=1'd0;
		end
		else
		begin

						data_old<=data_out;
			if(add_req)
			begin
				//data<=data+{{BUS_WIDTH-1{1'b0}},{1'd0}};
		          data_out<=data_out+1;

				if(data_out==max)
				begin
					data_out<=VALUE_INIT;
				end
			end
				if((data_old==max)&&(data_out==VALUE_INIT))
			     begin
			         carry_flag<=1'd1;
			     end
			     else
			     begin
			         carry_flag<=1'd0;
			     end
		  end
	end
endmodule

//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2024/05/07 19:49:56
// Design Name:
// Module Name: segment_code
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////

module segment_code(
input wire  [3:0]number,output wire [6:0]code
    );
    assign code=number==0?7'h3f:number==1?7'h06:number==2?7'h5b:number==3?7'h4f:number==4?7'h66:number==5?7'h6d:number==6?7'h7d:number==7?7'h07:number==8?7'h7f:number==9?7'h6f:7'h0;
endmodule

//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2024/05/07 21:01:04
// Design Name:
// Module Name: day_of_month
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////

module day_of_month(
input wire [3:0]month,
output wire[4:0] day_this_month
    );
assign day_this_month=month==1?5'd31:month==2?5'd28:month==3?5'd31:month==4?5'd30:month==5?5'd31:month==6?5'd30:month==7?5'd31:month==8?5'd31:month==9?5'd30:month==10?5'd31:month==11?5'd30:5'd31;
endmodule

//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2024/05/06 22:27:13
// Design Name:
// Module Name: key
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////

module key(
input  clock,input  reset,input time_flag,
input key_in,output key_out
    );

	reg [3:0]key_filter;
	always @(posedge clock or negedge reset)
	begin
	   if(reset==1'd0)
	   begin
	       key_filter<=4'b1111;
	   end
	   else
	   begin
	       if(time_flag==1)
	       begin
	           key_filter<={key_filter[2:0],key_in};
	       end
	   end
	end
	assign key_out=(time_flag==1)&&(key_filter==4'b1100);
endmodule


/*
 * Copyright (c) 2024 Jason Kaufmann
 * SPDX-License-Identifier: Apache-2.0
 */

`default_nettype none

module tt_um_8bitadder (
    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
);

  // Instantiate the rca8 module
  wire [7:0] sum;
  wire cout;

  rca8 adder (
      .A(ui_in),
      .B(uio_in),
      .cin(1'b0),    // Assuming no carry-in for simplicity
      .SUM(sum),
      .cout(cout)
  );

  // Assign the sum to the output
  assign uo_out = sum;

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

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

endmodule

module halfadder(input wire a,
                 input wire b,
                 output wire s,
                 output wire cout);
    assign s = a ^ b;
    assign cout = a & b;
endmodule

module fulladder(input wire cin,
                 input wire a,
                 input wire b,
                 output wire s,
                 output wire cout);
    wire s_tmp, cout_tmp1, cout_tmp2;
    halfadder h0(.a(a), .b(b), .s(s_tmp), .cout(cout_tmp1));
    halfadder h1(.a(s_tmp), .b(cin), .s(s), .cout(cout_tmp2));
    assign cout = cout_tmp1 | cout_tmp2;
endmodule

module rca8(input wire [7:0] A,
            input wire [7:0] B,
            input wire       cin,
            output wire [7:0] SUM,
            output wire      cout);
    wire [7:0] carry;

    fulladder fa0 (.cin(cin),     .a(A[0]), .b(B[0]), .s(SUM[0]), .cout(carry[0]));
    fulladder fa1 (.cin(carry[0]), .a(A[1]), .b(B[1]), .s(SUM[1]), .cout(carry[1]));
    fulladder fa2 (.cin(carry[1]), .a(A[2]), .b(B[2]), .s(SUM[2]), .cout(carry[2]));
    fulladder fa3 (.cin(carry[2]), .a(A[3]), .b(B[3]), .s(SUM[3]), .cout(carry[3]));
    fulladder fa4 (.cin(carry[3]), .a(A[4]), .b(B[4]), .s(SUM[4]), .cout(carry[4]));
    fulladder fa5 (.cin(carry[4]), .a(A[5]), .b(B[5]), .s(SUM[5]), .cout(carry[5]));
    fulladder fa6 (.cin(carry[5]), .a(A[6]), .b(B[6]), .s(SUM[6]), .cout(carry[6]));
    fulladder fa7 (.cin(carry[6]), .a(A[7]), .b(B[7]), .s(SUM[7]), .cout(carry[7]));

    assign cout = carry[7];
endmodule


/*
 * Copyright (c) 2024 Jack Leightcap
 * SPDX-License-Identifier: Apache-2.0
 */

`default_nettype none

module tt_um_jleightcap (
    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 we, halt;
  wire [5:0] count;
  Fractran ft (
      .clk(clk),
      .rst(rst_n),
      .en(ena),
      .accumulator(uio_in),
      .fraction(ui_in),
      .we(we),
      .degree(uo_out),
      .halt(halt),
      .count(count)
  );
  assign uio_out = {we, halt, count};
  assign uio_oe = {we, we, we, we, we, we, we, we};

endmodule

/* AUTOMATICALLY GENERATED VERILOG-2001 SOURCE CODE.
** GENERATED BY CLASH 1.6.3. DO NOT MODIFY.
*/
module Fractran
    ( // Inputs
      input [7:0] accumulator
    , input [7:0] fraction
    , input  clk // clock
    , input  rst // reset
    , input  en // enable

      // Outputs
    , output wire [7:0] degree
    , output wire  we
    , output wire  halt
    , output wire [5:0] count
    );
  // src/Fractran.hs:148:1-9
  wire [17:0] \input ;
  // src/Fractran.hs:120:1-88
  reg [16:0] s1 = {1'd0,   {1'b1,{1'b1,8'b00000000}},   6'b000000};
  wire [7:0] c$case_alt_0;
  wire [7:0] c$app_arg;
  wire  c$app_arg_0;
  wire [0:0] c$app_arg_1;
  // src/Fractran.hs:37:3-6
  wire [7:0] a;
  // src/Fractran.hs:107:1-6
  wire [8:0] v;
  wire [16:0] result;
  wire [9:0] result_0;
  wire [9:0] c$case_alt_1;
  wire [9:0] c$case_alt_2;
  wire [9:0] c$case_alt_3;
  wire [9:0] c$case_alt_4;
  // src/Fractran.hs:56:7-8
  wire [7:0] ipv;
  wire [7:0] c$app_arg_2;
  wire [9:0] c$case_alt_5;
  wire  c$case_scrut;
  // src/Fractran.hs:56:7-8
  wire [7:0] f;
  // src/Fractran.hs:81:1-6
  wire [8:0] f_0;
  // src/Fractran.hs:81:1-6
  wire [8:0] a_0;
  // src/Fractran.hs:148:1-9
  reg [8:0] c$input_app_arg;
  // src/Fractran.hs:148:1-9
  reg [8:0] c$input_app_arg_0;
  wire [9:0] c$app_arg_selection_1;
  wire [9:0] c$app_arg_selection_6;
  wire [7:0] c$bv;
  wire [15:0] c$case_alt;

  assign \input  = {c$input_app_arg_0,
                    c$input_app_arg};

  // register begin
  always @(posedge clk or  posedge  rst) begin : s1_register
    if ( rst) begin
      s1 <= {1'd0,   {1'b1,{1'b1,8'b00000000}},   6'b000000};
    end else if (en) begin
      s1 <= result;
    end
  end
  // register end

  assign c$case_alt_0 = v[8:8] ? (a) : 8'b11111111;

  assign c$app_arg_selection_1 = s1[15:6];

  assign c$app_arg = c$app_arg_selection_1[9:9] ? c$case_alt_0 : (8'b00000000);

  assign c$app_arg_0 = s1[16:16] ? (1'b1) : (1'b0);

  assign c$app_arg_selection_6 = s1[15:6];

  assign c$app_arg_1 = c$app_arg_selection_6[9:9] ? 1'b0 : 1'b1;

  assign c$case_alt = {c$app_arg,   c$app_arg_0,
                       (c$app_arg_1),   s1[5:0]};

  assign a = v[7:0];

  assign v = s1[14:6];

  assign result = s1[16:16] ? {1'd0,   result_0,
                               s1[5:0]} : {1'd1,   result_0,
                                           s1[5:0] + 6'b000001};

  assign result_0 = a_0[8:8] ? c$case_alt_1 : c$case_alt_2;

  assign c$case_alt_1 = f_0[8:8] ? c$case_alt_3 : {1'b1,a_0};

  assign c$case_alt_2 = f_0[8:8] ? c$case_alt_5 : {1'b1,{1'b0,8'bxxxxxxxx}};

  assign c$case_alt_3 = c$case_scrut ? {1'b1,{1'b1,(ipv + f) % 8'b01111110}} : c$case_alt_4;

  assign c$case_alt_4 = (ipv >= c$app_arg_2) ? {1'b1,{1'b1,(ipv - c$app_arg_2) + 8'b00000001}} : {1'b0,9'bxxxxxxxxx};

  assign ipv = a_0[7:0];

  assign c$app_arg_2 = -f;

  assign c$case_alt_5 = c$case_scrut ? {1'b1,{1'b1,f}} : {1'b0,9'bxxxxxxxxx};

  assign c$bv = (f);

  assign c$case_scrut = ( c$bv[8-1] ) == (1'b0);

  assign f = f_0[7:0];

  assign f_0 = \input [8:0];

  assign a_0 = \input [17:9];

  always @(*) begin
    case(fraction)
      8'b11111111 : c$input_app_arg = {1'b0,8'bxxxxxxxx};
      default : c$input_app_arg = {1'b1,fraction};
    endcase
  end

  always @(*) begin
    case(accumulator)
      8'b11111111 : c$input_app_arg_0 = {1'b0,8'bxxxxxxxx};
      default : c$input_app_arg_0 = {1'b1,accumulator};
    endcase
  end

  assign degree = c$case_alt[15:8];

  assign we = c$case_alt[7:7];

  assign halt = c$case_alt[6:6];

  assign count = c$case_alt[5:0];

endmodule


/*
 * Copyright (c) 2024 Your Name
 * SPDX-License-Identifier: Apache-2.0
 */

`default_nettype none

module tt_um_router (
    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_oe=8'b11111111;

assign uio_out[7:6]=2'b00;

router_top router_top (
		.clock(clk),
		.resetn(rst_n),
		.data_in(ui_in[2:0]),
		.pkt_valid(ui_in[3]),
		.read_enb_0(ui_in[4]),
		.read_enb_1(ui_in[5]),
		.read_enb_2(ui_in[6]),
		.data_out_0(uo_out[2:0]),
		.data_out_1(uo_out[5:3]),
		.data_out_2(uio_out[2:0]),
		.vld_out_0(uio_out[3]),
		.vld_out_1(uio_out[4]),
		.vld_out_2(uio_out[5]),
		.err(uo_out[6]),
		.busy(uo_out[7])
		);

endmodule

module router_fifo(clock,resetn,soft_reset,write_enb,read_enb,
                   lfd_state,data_in,full,empty,data_out);

  input clock,resetn,soft_reset;
  input write_enb,read_enb,lfd_state;
  input [2:0]data_in;

  output reg [2:0] data_out;
  output full,empty;

  reg [4:0] rd_pointer,wr_pointer;
  reg [6:0] count;
  reg [8:0] mem [15:0];

  integer i;

   reg lfd_state_t;

  always@(posedge clock)
    begin
      if(!resetn)
        lfd_state_t <= 0;
      else
        lfd_state_t <= lfd_state;
    end

  // ------Read Operation-------
  always@(posedge clock)
    begin
      if(!resetn)
          data_out = 3'b0;
      else if(soft_reset)
          data_out = 3'bz;
      else if((read_enb) && (!empty))
        data_out = mem[rd_pointer[2:0]][2:0];
      else if(count == 0)
           data_out = 3'bz;
    end

  // ------Write Operation------
  always@(posedge clock)
    begin
      if(!resetn || soft_reset)
         begin
            for(i=0;i<16;i=i+1)
            mem[i]<=0;
         end
      else if(write_enb&&(~full))
         begin
           if(lfd_state_t)
	           begin
                 mem[wr_pointer[3:0]][8]<=1'b1;
                 mem[wr_pointer[2:0]][2:0]<=data_in;
	           end

	      else
	           begin
                 mem[wr_pointer[3:0]][8]<=1'b0;
                 mem[wr_pointer[2:0]][2:0]<=data_in;
			   end
         end
     end

  //----Pointer generation block----

   always@(posedge clock)
     begin
       if(!resetn)
        wr_pointer<=0;
      else if(write_enb && (~full))
        wr_pointer<=wr_pointer+1;
     end

   always@(posedge clock) //Read address
     begin
       if(!resetn)
         rd_pointer<=0;
       else if(read_enb && (~empty))
         rd_pointer<=rd_pointer+1;
     end

  //-----counter block while reading------

  always@(posedge clock)
    begin
      if(read_enb && !empty)
        begin
          if((mem[rd_pointer[3:0]][8])==1'b1)
            count <= mem[rd_pointer[3:0]][7:2] + 1'b1;
          else if(count != 0)
            count <= count - 1'b1;
        end
    end
  //---------Full & empty condition-----------
  assign full  = (wr_pointer ==({~rd_pointer[4],rd_pointer[3:0]}));
  assign empty = (rd_pointer == wr_pointer);

endmodule

module router_fsm(clock,resetn,pkt_valid,data_in,fifo_full,fifo_empty_0,fifo_empty_1,fifo_empty_2,
                  soft_reset_0,soft_reset_1,soft_reset_2,parity_done,low_packet_valid,
                  write_enb_reg,detect_add,ld_state,laf_state,lfd_state,full_state,rst_int_reg,busy);

input clock,resetn,pkt_valid,fifo_full,fifo_empty_0,fifo_empty_1,fifo_empty_2;
input soft_reset_0,soft_reset_1,soft_reset_2,parity_done,low_packet_valid;
input [1:0] data_in;
output write_enb_reg,detect_add,ld_state,laf_state,lfd_state,full_state,rst_int_reg,busy;

parameter DECODE_ADDRESS     = 3'b000,
          LOAD_FIRST_DATA 	 = 3'b001,
          LOAD_DATA 		 = 3'b010,
          WAIT_TILL_EMPTY 	 = 3'b011,
          CHECK_PARITY_ERROR = 3'b100,
          LOAD_PARITY 		 = 3'b101,
          FIFO_FULL_STATE 	 = 3'b110,
          LOAD_AFTER_FULL 	 = 3'b111;

  reg [2:0] PS,NS;

  always@(posedge clock)
    begin
      if(!resetn)
        PS <= DECODE_ADDRESS;
      else if(soft_reset_0 || soft_reset_1 || soft_reset_2)
        PS <= DECODE_ADDRESS;
      else
        PS <= NS;
    end

  always@(*)
    begin
      NS = DECODE_ADDRESS;
      case(PS)

        DECODE_ADDRESS :
                  begin
                    if((pkt_valid && (data_in[1:0]==0) && fifo_empty_0)||
                       (pkt_valid && (data_in[1:0]==1) && fifo_empty_1)||
                       (pkt_valid && (data_in[1:0]==2) && fifo_empty_2))

                      NS = LOAD_FIRST_DATA;

                    else if((pkt_valid && (data_in[1:0]==0) && (~fifo_empty_0))||
                            (pkt_valid && (data_in[1:0]==1) && (~fifo_empty_1))||
                            (pkt_valid && (data_in[1:0]==2) && (~fifo_empty_2)))

                      NS = WAIT_TILL_EMPTY;

                    else
                      NS = DECODE_ADDRESS;
                  end

        LOAD_FIRST_DATA :  NS = LOAD_DATA;

        LOAD_DATA       :
                        begin
			      			if(fifo_full)
				 				NS=FIFO_FULL_STATE;
                          else if(!fifo_full && !pkt_valid)
				 				NS=LOAD_PARITY;
			      			else
				 				NS=LOAD_DATA;
			   			end

        WAIT_TILL_EMPTY  :
                        begin
                          if((!fifo_empty_0) || (!fifo_empty_1) || (!fifo_empty_2))
				 			NS=WAIT_TILL_EMPTY;
			      		  else if(fifo_empty_0||fifo_empty_1||fifo_empty_2)
				 			NS=LOAD_FIRST_DATA;
			      		  else
				 			NS=WAIT_TILL_EMPTY;
                         end

        CHECK_PARITY_ERROR:
          				begin
			    			if(fifo_full)
			      	 			NS=FIFO_FULL_STATE;
			    			else
			         			NS=DECODE_ADDRESS;

			   			 end

       LOAD_PARITY     	  :	NS=CHECK_PARITY_ERROR;

       FIFO_FULL_STATE	  :
          				begin
                        	if(!fifo_full)
			         			NS=LOAD_AFTER_FULL;
			      			else if(fifo_full)
			         			NS=FIFO_FULL_STATE;
			  		 		end

        LOAD_AFTER_FULL:
          				begin
          					if((!parity_done) && (!low_packet_valid))
			   					NS=LOAD_DATA;
          					else if((!parity_done) && (low_packet_valid))
			   					NS=LOAD_PARITY;
          					else if(parity_done)
			   					NS=DECODE_ADDRESS;
			   			 end

      endcase
   end

  assign detect_add = ((PS==DECODE_ADDRESS)?1:0);
  assign write_enb_reg=((PS==LOAD_DATA||PS==LOAD_PARITY||PS==LOAD_AFTER_FULL)?1:0);
  assign full_state=((PS==FIFO_FULL_STATE)?1:0);
  assign lfd_state=((PS==LOAD_FIRST_DATA)?1:0);
  assign busy=((PS==FIFO_FULL_STATE||PS==LOAD_AFTER_FULL||PS==WAIT_TILL_EMPTY||PS==LOAD_FIRST_DATA||PS==LOAD_PARITY||PS==CHECK_PARITY_ERROR)?1:0);
  //assign busy=((PS==LOAD_DATA || PS==DECODE_ADDRESS)?0:1);
  assign ld_state=((PS==LOAD_DATA)?1:0);
  assign laf_state=((PS==LOAD_AFTER_FULL)?1:0);
  assign rst_int_reg=((PS==CHECK_PARITY_ERROR)?1:0);

endmodule

module router_reg(clock,resetn,pkt_valid,data_in,fifo_full,detect_add,
                  ld_state,laf_state,full_state,lfd_state,rst_int_reg,err,
                  parity_done,low_packet_valid,dout);

input clock,resetn,pkt_valid,fifo_full,detect_add,ld_state,laf_state,full_state,lfd_state,rst_int_reg;
input [2:0]data_in;
output reg err,parity_done,low_packet_valid;
output reg [2:0]dout;
reg [2:0]header,int_reg,int_parity,ext_parity;

  //------------------------------DATA OUT LOGIC---------------------------------

	always@(posedge clock)
   	begin
      if(!resetn)
      	begin
	     dout    	 <=0;
	     header  	 <=0;
	     int_reg 	 <=0;
       	end
      else if(detect_add && pkt_valid && data_in[1:0]!=2'b11)
	     header<=data_in;
      else if(lfd_state)
	     dout<=header;
      else if(ld_state && !fifo_full)
	     dout<=data_in;
      else if(ld_state && fifo_full)
	     int_reg<=data_in;
      else if(laf_state)
	     dout<=int_reg;
     end

  //---------------------------LOW PACKET VALID LOGIC----------------------------

      	always@(posedge clock)
	   		begin
              if(!resetn)
	 				low_packet_valid<=0;
         		else if(rst_int_reg)
	 				low_packet_valid<=0;

              else if(ld_state && !pkt_valid)
         			low_packet_valid<=1;
			end
  //----------------------------PARITY DONE LOGIC--------------------------------

	always@(posedge clock)
	begin
      if(!resetn)
	  parity_done<=0;
     else if(detect_add)
	  parity_done<=0;
      else if((ld_state && !fifo_full && !pkt_valid)
              ||(laf_state && low_packet_valid && !parity_done))
	  parity_done<=1;
	end

//---------------------------PARITY CALCULATE LOGIC----------------------------

	always@(posedge clock)
	begin
      if(!resetn)
	 int_parity<=0;
	else if(detect_add)
	 int_parity<=0;
	else if(lfd_state && pkt_valid)
	 int_parity<=int_parity^header;
	else if(ld_state && pkt_valid && !full_state)
	 int_parity<=int_parity^data_in;
	else
	 int_parity<=int_parity;
	end

//-------------------------------ERROR LOGIC-----------------------------------

	always@(posedge clock)
		begin
          if(!resetn)
	  			err<=0;
	      else if(parity_done)
	       		begin
	 				if (int_parity==ext_parity)
	    				err<=0;
	 				else
	    			err<=1;
	 			end
	 	   else
	    		err<=0;
	      end

//-------------------------------EXTERNAL PARITY LOGIC-------------------------

	always@(posedge clock)
	begin
      if(!resetn)
	  		ext_parity<=0;
      else if(detect_add)
	  		ext_parity<=0;
      else if((ld_state && !fifo_full && !pkt_valid) || (laf_state && !parity_done && low_packet_valid))
	  		ext_parity<=data_in;
	 end

endmodule

module router_sync(clock,resetn,data_in,detect_add,full_0,full_1,full_2,empty_0,empty_1,empty_2,write_enb_reg,read_enb_0,read_enb_1,read_enb_2,write_enb,fifo_full,vld_out_0,vld_out_1,vld_out_2,soft_reset_0,soft_reset_1,soft_reset_2);

input clock,resetn,detect_add,full_0,full_1,full_2,empty_0,empty_1,empty_2,write_enb_reg,read_enb_0,read_enb_1,read_enb_2;
input [1:0]data_in;
output reg[2:0]write_enb;
output reg fifo_full,soft_reset_0,soft_reset_1,soft_reset_2;
output vld_out_0,vld_out_1,vld_out_2;

  reg [1:0] data_in_tmp;
  reg[4:0]count0,count1,count2;

  always@(posedge clock)
  begin
    if(~resetn)
    data_in_tmp<=0;
    else if(detect_add)
    data_in_tmp<=data_in;
  end

//-----------Address decoding & fifo empty ---------------
always@(*)
  begin
    case(data_in_tmp)
    2'b00:begin
	  fifo_full<=full_0;
	  if(write_enb_reg)
	  write_enb<=3'b001;
	  else
	  write_enb<=0;
	  end
    2'b01:begin
	  fifo_full<=full_1;
	  if(write_enb_reg)
	  write_enb<=3'b010;
	  else
	  write_enb<=0;
	  end
    2'b10:begin
	  fifo_full<=full_2;
	  if(write_enb_reg)
	  write_enb<=3'b100;
	  else
	  write_enb<=0;
	  end
    default:begin
	  fifo_full<=0;
	  write_enb<=0;
	  end
    endcase
  end

//-----------------------------------Valid Byte block----------------------------------

assign vld_out_0 = (~empty_0);
assign vld_out_1 = (~empty_1);
assign vld_out_2 = (~empty_2);

//-----------------------------------Soft Reset block----------------------------------

always@(posedge clock)
  begin

  if(~resetn)
  begin
  count0<=0;
  soft_reset_0<=0;
  end

  else if(vld_out_0)
  begin
  if(~read_enb_0)

    begin
    if(count0==29)
      begin
      soft_reset_0<=1'b1;
      count0<=0;
      end
    else
      begin
      soft_reset_0<=1'b0;
      count0<=count0+1'b1;
      end
    end
  else
  count0<=0;
  end
  end

always@(posedge clock)
  begin

  if(~resetn)
  begin
  count1<=0;
  soft_reset_1<=0;
  end

  else if(vld_out_1)
  begin
  if(~read_enb_1)

    begin
    if(count1==29)
      begin
      soft_reset_1<=1'b1;
      count1<=0;
      end
    else
      begin
      soft_reset_1<=1'b0;
      count1<=count1+1'b1;
      end
    end
  else
  count1<=0;
  end
  end

always@(posedge clock)
  begin

  if(~resetn)
  begin
  count2<=0;
  soft_reset_2<=0;
  end

  else if(vld_out_2)
  begin
  if(~read_enb_2)

    begin
    if(count2==29)
      begin
      soft_reset_2<=1'b1;
      count2<=0;
      end
    else
      begin
      soft_reset_2<=1'b0;
      count2<=count2+1'b1;
      end
    end
  else
  count2<=0;
  end
  end

endmodule

module router_top(clock,resetn,pkt_valid,read_enb_0,read_enb_1,read_enb_2,data_in,
				    busy,err,vld_out_0,vld_out_1,vld_out_2,data_out_0,data_out_1,data_out_2);

  input [2:0]data_in;
  input pkt_valid,clock,resetn,read_enb_0,read_enb_1,read_enb_2;
  output [2:0]data_out_0,data_out_1,data_out_2;
  output vld_out_0,vld_out_1,vld_out_2,err,busy;

	wire soft_reset_0,full_0,empty_0,soft_reset_1,full_1,empty_1,soft_reset_2,full_2,empty_2,
         fifo_full,detect_add,ld_state,laf_state,full_state,lfd_state,rst_int_reg,
         parity_done,low_packet_valid,write_enb_reg;
	wire [2:0]write_enb;
	wire [2:0]d_in;

    //-------fifo instantiation-----

	router_fifo FIFO_0(.clock(clock),
	                   .resetn(resetn),
		           .soft_reset(soft_reset_0),
			   .write_enb(write_enb[0]),
			   .read_enb(read_enb_0),
                           .lfd_state(lfd_state),
			   .data_in(d_in),
			   .full(full_0),
			   .empty(empty_0),
			   .data_out(data_out_0));

	router_fifo FIFO_1(.clock(clock),
	                   .resetn(resetn),
			   .soft_reset(soft_reset_1),
			   .write_enb(write_enb[1]),
			   .read_enb(read_enb_1),
                           .lfd_state(lfd_state),
		           .data_in(d_in),
			   .full(full_1),
			   .empty(empty_1),
			   .data_out(data_out_1));

	router_fifo FIFO_2(.clock(clock),
	                   .resetn(resetn),
			   .soft_reset(soft_reset_2),
			   .write_enb(write_enb[2]),
			   .read_enb(read_enb_2),
                           .lfd_state(lfd_state),
			   .data_in(d_in),
			   .full(full_2),
			   .empty(empty_2),
			   .data_out(data_out_2));

    //-------register instantiation-----

	router_reg REGISTER(.clock(clock),
	                    .resetn(resetn),
			    .pkt_valid(pkt_valid),
	        	    .data_in(data_in),
			    .fifo_full(fifo_full),
	        	    .detect_add(detect_add),
                            .ld_state(ld_state),
			    .laf_state(laf_state),
			    .full_state(full_state),
	       		    .lfd_state(lfd_state),
			    .rst_int_reg(rst_int_reg),
			    .err(err),
                            .parity_done(parity_done),
			    .low_packet_valid(low_packet_valid),
			    .dout(d_in));

    //-------synchronizer instantiation-----

	router_sync SYNCHRONIZER(.clock(clock),
	                         .resetn(resetn),
				 .data_in(data_in[1:0]),
				 .detect_add(detect_add),
				 .full_0(full_0),
				 .full_1(full_1),
				 .full_2(full_2),
				 .empty_0(empty_0),
				 .empty_1(empty_1),
				 .empty_2(empty_2),
				 .write_enb_reg(write_enb_reg),
				 .read_enb_0(read_enb_0),
				 .read_enb_1(read_enb_1),
				 .read_enb_2(read_enb_2),
				 .write_enb(write_enb),
				 .fifo_full(fifo_full),
				 .vld_out_0(vld_out_0),
				 .vld_out_1(vld_out_1),
				 .vld_out_2(vld_out_2),
				 .soft_reset_0(soft_reset_0),
				 .soft_reset_1(soft_reset_1),
				 .soft_reset_2(soft_reset_2));

    //-------fsm instantiation-----

	router_fsm FSM(.clock(clock),
	               .resetn(resetn),
		       .pkt_valid(pkt_valid),
		       .data_in(data_in[1:0]),
		       .fifo_full(fifo_full),
		       .fifo_empty_0(empty_0),
		       .fifo_empty_1(empty_1),
		       .fifo_empty_2(empty_2),
                       .soft_reset_0(soft_reset_0),
		       .soft_reset_1(soft_reset_1),
		       .soft_reset_2(soft_reset_2),
		       .parity_done(parity_done),
		       .low_packet_valid(low_packet_valid),
                       .write_enb_reg(write_enb_reg),
	               .detect_add(detect_add),
		       .ld_state(ld_state),
		       .laf_state(laf_state),
		       .lfd_state(lfd_state),
		       .full_state(full_state),
	               .rst_int_reg(rst_int_reg),
	               .busy(busy));

endmodule


/*
 * Copyright (c) 2024 Your Name
 * SPDX-License-Identifier: Apache-2.0
 */

`default_nettype none

module tt_um_mitssdd (
    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;
     co_processor co_processor  (
    .clk(clk),
    .reset(rst_n),
	.r0(ui_in),
	.check(uio_in[1:0]),
	     .Q(uo_out[0]),
	         .Q1(uo_out[7:6])

);
    fault_pro fault_pro  (
    .clk(clk),
    .reset(rst_n),
	.r0(ui_in),
	.check(uio_in[1:0]),
	.out(uo_out[3:1]),
	.out1(uo_out[5:4])

);

endmodule

module co_processor (
    input [7:0] r0, // 8-bit input
    input [1:0] check, // sensor checking
    input reset,
    input clk, // clock input
    output reg Q, // output Q connected to LED
    output reg [1:0] Q1
);

reg [7:0] proc = 8'b0; // processing register
reg [7:0] r1 = 8'b0;
reg [7:0] r2 = 8'b0;
reg [7:0] r3 = 8'b0;
reg [7:0] r4 = 8'b0;
reg [7:0] res = 8'b0;
reg [7:0] data = 8'b0;
reg [1:0] sense = 2'b0;

always @(posedge clk or posedge reset) begin
    if (reset) begin
        r1 <= 8'b0;
        r2 <= 8'b0;
        r3 <= 8'b0;
        r4 <= 8'b0;
        Q <= 1'b0;
		Q1 <= 2'b0;
		data <= 8'b0;
		sense <= 2'b0;
		proc = 8'b0;
    end else begin
    data <= r0;
    sense <= check;

            case (sense)
                2'b00: proc = r1;
                2'b01: proc = r2;
                2'b10: proc = r3;
                2'b11: proc = r4;
            endcase

            if (proc == data) begin
                Q <= 1'b0;
                Q1 <= 2'b00;
            end else begin
                if (proc > data) begin
                    res = proc - data;
                end else begin
                    res = data - proc;
                end

                if (res > 8'b00000010) begin

                    if (sense == 2'b00) begin
                        r1 <= data;
                        Q1 <= 2'b00;
                        end
                    if (sense == 2'b01) begin
                        r2 <= data;
                        Q1 <= 2'b01;
                        end
                    if (sense == 2'b10) begin
                        r3 <= data;
                        Q1 <= 2'b10;
                        end
                    if (sense == 2'b11) begin
                        r4 <= data;
                        Q1 <= 2'b11;
                        end

                    Q <= 1'b1;
                end else begin
                    Q <= 1'b0;
                    Q1 <= 2'b00;

                end
            end

    end
end

endmodule

module fault_pro(
	input [7:0] r0,
	input [1:0] check,
	input reset,
	input clk,
	output reg [2:0] out,
	output reg [1:0] out1);

	//data storing registers
	reg [9:0] r1=10'b0;
	reg [9:0] r2=10'b0;
	reg [9:0] r3=10'b0;
	reg [9:0] r4=10'b0;

	//1st 4 set mean values
	reg [9:0] m1=10'b0;
	reg [9:0] m2=10'b0;
	reg [9:0] m3=10'b0;
	reg [9:0] m4=10'b0;

	//2nd 4 set mean values
	reg [9:0] w1=10'b0;
	reg [9:0] w2=10'b0;
	reg [9:0] w3=10'b0;
	reg [9:0] w4=10'b0;

	//Difference storing register
	reg [9:0] diff1=10'b0;
	reg [9:0] diff2=10'b0;
	reg [9:0] diff3=10'b0;
	reg [9:0] diff4=10'b0;

	reg [2:0] counter1 = 3'b0;
	reg [2:0] counter2 = 3'b0;
	reg [2:0] counter3 = 3'b0;
	reg [2:0] counter4 = 3'b0;

	reg f1 = 1'b0;
	reg f2 = 1'b0;
	reg f3 = 1'b0;
	reg f4 = 1'b0;

	always @(posedge clk or posedge reset) begin

		if (reset) begin // Reset
			r1 <= 10'b0;
			r2 <= 10'b0;
			r3 <= 10'b0;
			r4 <= 10'b0;

			m1 <= 10'b0;
			m2 <= 10'b0;
			m3 <= 10'b0;
			m4 <= 10'b0;

			w1 <= 10'b0;
			w2 <= 10'b0;
			w3 <= 10'b0;
			w4 <= 10'b0;

			diff1 <= 10'b0;
			diff2 <= 10'b0;
			diff3 <= 10'b0;
			diff4 <= 10'b0;

			counter1 <= 3'b0;
			counter2 <= 3'b0;
			counter3 <= 3'b0;
			counter4 <= 3'b0;

			f1 <= 1'b0;
			f2 <= 1'b0;
			f3 <= 1'b0;
			f4 <= 1'b0;

			out <= 3'b0;
			out1 <= 2'b0;

		end else begin

				case (check)
					2'b00: begin
							r1 <= r1 + r0;
							counter1 <= counter1 + 1;
						end
					2'b01: begin
							r2 <= r2 + r0;
							counter2 <= counter2 + 1;
						end
					2'b10: begin
							r3 <= r3 + r0;
							counter3 <= counter3 + 1;
						end
					2'b11: begin
							r4 <= r4 + r0;
							counter4 <= counter4 + 1;
						end
				endcase

				if(f1 == 0 && counter1 == 4) begin //checking whether sum of 4 data was calculated
					m1 <= r1 >> 2;
					r1 <= 10'b0;
					counter1 <= 3'b0;
					f1 <= 1'b1;
				end
				if(f2 == 0 && counter2 == 4) begin //checking whether sum of 4 data was calculated
					m2 <= r2 >> 2;
					r2 <= 10'b0;
					counter2 <= 3'b0;
					f2 <= 1'b1;
				end
				if(f3 == 0 && counter3 == 4) begin //checking whether sum of 4 data was calculated
					m3 <= r3 >> 2;
					r3 <= 10'b0;
					counter3 <= 3'b0;
					f3 <= 1'b1;
				end
				if(f4 == 0 && counter4 == 4) begin //checking whether sum of 4 data was calculated
					m4 <= r4 >> 2;
					r4 <= 10'b0;
					counter4 <= 3'b0;
					f4 <= 1'b1;
				end

////////////////////////////////////////////////////////////////////////////////

				if(f1 == 1 && counter1 == 4) begin //checking whether sum of 4 data was calculated
					w1 <= r1 >> 2;
					r1 <= 10'b0;
					counter1 <= 3'b0;
					f1 <= 1'b0;
				end
				if(f2 == 1 && counter2 == 4) begin //checking whether sum of 4 data was calculated
					w2 <= r2 >> 2;
					r2 <= 10'b0;
					counter2 <= 3'b0;
					f2 <= 1'b0;
				end
				if(f3 == 1 && counter3 == 4) begin //checking whether sum of 4 data was calculated
					w3 <= r3 >> 2;
					r3 <= 10'b0;
					counter3 <= 3'b0;
					f3 <= 1'b0;
				end
				if(f4 == 1 && counter4 == 4) begin //checking whether sum of 4 data was calculated
					w4 <= r4 >> 2;
					r4 <= 10'b0;
					counter4 <= 3'b0;
					f4 <= 1'b0;
				end

				diff1 <= (w1 > m1) ? (w1 - m1) : (m1 - w1);
				diff2 <= (w2 > m2) ? (w2 - m2) : (m2 - w2);
				diff3 <= (w3 > m3) ? (w3 - m3) : (m3 - w3);
				diff4 <= (w4 > m4) ? (w4 - m4) : (m4 - w4);

				if(diff1 >= 100) begin
					out <= 3'b100;
					out1 <= 2'b00;
					diff1 <= 10'b0;
					w1 <= 10'b0;
					m1 <= 10'b0;
				end
				else if(diff1 >= 50 && diff1 < 100) begin
						out <= 3'b011;
						out1 <= 2'b00;
						diff1 <= 10'b0;
						w1 <= 10'b0;
						m1 <= 10'b0;
				end
				else if(diff1 >= 25 && diff1 < 50) begin
						out <= 3'b010;
						out1 <= 2'b00;
						diff1 <= 10'b0;
						w1 <= 10'b0;
						m1 <= 10'b0;
				end
				else if(diff1 >= 10 && diff1 < 25) begin
						out <= 3'b001;
						out1 <= 2'b00;
						diff1 <= 10'b0;
						w1 <= 10'b0;
						m1 <= 10'b0;
				end
				if(diff2 >= 100) begin
					out <= 3'b100;
					out1 <= 2'b01;
					diff2 <= 10'b0;
					w2 <= 10'b0;
					m2 <= 10'b0;
				end
				else if(diff2 >= 50 && diff2 < 100) begin
						out <= 3'b011;
						out1 <= 2'b01;
						diff2 <= 10'b0;
						w2 <= 10'b0;
						m2 <= 10'b0;
				end
				else if(diff2 >= 25 && diff2 < 50) begin
						out <= 3'b010;
						out1 <= 2'b01;
						diff2 <= 10'b0;
						w2 <= 10'b0;
						m2 <= 10'b0;
				end
				else if(diff2 >= 10 && diff2 < 25) begin
						out <= 3'b001;
						out1 <= 2'b01;
						diff2 <= 10'b0;
						w2 <= 10'b0;
						m2 <= 10'b0;
				end
				if(diff3 >= 100) begin
					out <= 3'b100;
					out1 <= 2'b10;
					diff3 <= 10'b0;
					w3 <= 10'b0;
					m3 <= 10'b0;
				end
				else if(diff3 >= 50 && diff3 <100) begin
						out <= 3'b011;
						out1 <= 2'b10;
						diff3 <= 10'b0;
						w3 <= 10'b0;
						m3 <= 10'b0;
				end
				else if(diff3 >= 25 && diff3 <50) begin
						out <= 3'b010;
						out1 <= 2'b10;
						diff3 <= 10'b0;
						w3 <= 10'b0;
						m3 <= 10'b0;
				end
				else if(diff3 >= 10 && diff3 <25) begin
						out <= 3'b001;
						out1 <= 2'b10;
						diff3 <= 10'b0;
						w3 <= 10'b0;
						m3 <= 10'b0;
				end
				if(diff4 >= 100) begin
					out <= 3'b100;
					out1 <= 2'b11;
					diff4 <= 10'b0;
					w4 <= 10'b0;
					m4 <= 10'b0;
				end
				else if(diff4 >= 50 && diff4 <100) begin
						out <= 3'b011;
						out1 <= 2'b11;
						diff4 <= 10'b0;
						w4 <= 10'b0;
						m4 <= 10'b0;
				end
				else if(diff4 >= 25 && diff4 <50) begin
						out <= 3'b010;
						out1 <= 2'b11;
						diff4 <= 10'b0;
						w4 <= 10'b0;
						m4 <= 10'b0;
				end
				else if(diff4 >= 10 && diff4 <25) begin
						out <= 3'b001;
						out1 <= 2'b11;
						diff4 <= 10'b0;
						w4 <= 10'b0;
						m4 <= 10'b0;
				end

			end

	end
endmodule


/*
 * Copyright (c) 2024 ReJ aka Renaldas Zioma
 * SPDX-License-Identifier: Apache-2.0
 */

`default_nettype none

/*
Video sync generator, used to drive a VGA monitor.
Timing from: https://en.wikipedia.org/wiki/Video_Graphics_Array
To use:
- Wire the hsync and vsync signals to top level outputs
- Add a 3-bit (or more) "rgb" output to the top level
*/

module hvsync_generator(clk, reset, hsync, vsync, display_on, hpos, vpos);

  input clk;
  input reset;
  output reg hsync, vsync;
  output display_on;
  output reg [9:0] hpos;
  output reg [9:0] vpos;

  // declarations for TV-simulator sync parameters
  // horizontal constants
  parameter H_DISPLAY       = 640; // horizontal display width
  parameter H_BACK          =  48; // horizontal left border (back porch)
  parameter H_FRONT         =  16; // horizontal right border (front porch)
  parameter H_SYNC          =  96; // horizontal sync width
  // vertical constants
  parameter V_DISPLAY       = 480; // vertical display height
  parameter V_TOP           =  33; // vertical top border
  parameter V_BOTTOM        =  10; // vertical bottom border
  parameter V_SYNC          =   2; // vertical sync # lines
  // derived constants
  parameter H_SYNC_START    = H_DISPLAY + H_FRONT;
  parameter H_SYNC_END      = H_DISPLAY + H_FRONT + H_SYNC - 1;
  parameter H_MAX           = H_DISPLAY + H_BACK + H_FRONT + H_SYNC - 1;
  parameter V_SYNC_START    = V_DISPLAY + V_BOTTOM;
  parameter V_SYNC_END      = V_DISPLAY + V_BOTTOM + V_SYNC - 1;
  parameter V_MAX           = V_DISPLAY + V_TOP + V_BOTTOM + V_SYNC - 1;

  wire hmaxxed = (hpos == H_MAX) || reset;  // set when hpos is maximum
  wire vmaxxed = (vpos == V_MAX) || reset;  // set when vpos is maximum

  // horizontal position counter
  always @(posedge clk)
  begin
    hsync <= (hpos>=H_SYNC_START && hpos<=H_SYNC_END);
    if(hmaxxed)
      hpos <= 0;
    else
      hpos <= hpos + 1;
  end

  // vertical position counter
  always @(posedge clk)
  begin
    vsync <= (vpos>=V_SYNC_START && vpos<=V_SYNC_END);
    if(hmaxxed)
      if (vmaxxed)
        vpos <= 0;
      else
        vpos <= vpos + 1;
  end

  // display_on is set when beam is in "safe" visible frame
  assign display_on = (hpos<H_DISPLAY) && (vpos<V_DISPLAY);

endmodule

module tt_um_rejunity_vga(
  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
);

  // VGA signals
  wire hsync;
  wire vsync;
  wire [1:0] R;
  wire [1:0] G;
  wire [1:0] B;
  wire video_active;
  wire [9:0] pix_x;
  wire [9:0] pix_y;

  // TinyVGA PMOD
  assign uo_out = {hsync, B[0], G[0], R[0], vsync, B[1], G[1], R[1]};

  // Unused outputs assigned to 0.
  assign uio_out = 0;
  assign uio_oe  = 0;

  // Suppress unused signals warning
  wire _unused_ok = &{ena, ui_in, uio_in};

  reg [9:0] counter;

  hvsync_generator hvsync_gen(
    .clk(clk),
    .reset(~rst_n),
    .hsync(hsync),
    .vsync(vsync),
    .display_on(video_active),
    .hpos(pix_x),
    .vpos(pix_y)
  );

  wire [9:0] moving_x = pix_x + counter*16;
  wire [9:0] moving_y = pix_y + counter*2;

  wire [9:0] moving_x2 = pix_x + counter*7;
  wire [9:0] moving_y2 = pix_y + counter + counter/2;

  wire [9:0] moving_x3 = pix_x + counter*4;
  wire [9:0] moving_y3 = pix_y + counter/2;

  wire [9:0] moving_x4 = pix_x + counter*2;
  wire [9:0] moving_y4 = pix_y + counter/4;

  wire [9:0] moving_x5 = pix_x + counter/2;
  wire [9:0] moving_y5 = pix_y + counter/6;

  wire a = moving_x[8] ^ moving_y[8];
  wire b = moving_x2[7] ^ moving_y2[7];
  wire c = moving_x3[6] ^ moving_y3[6];
  wire d = moving_x4[5] ^ moving_y4[5];
  wire e = moving_x5[4] ^ moving_y5[4];

  // wire x = a | b | c | d | e;

  // assign {R, G, B} =
  //     video_active ?
  //       (a ? 6'b11_11_01 :
  //         (b ? 6'b11_10_01 :
  //           (c ? 6'b11_01_00 :
  //             (d ? 6'b10_00_00 : 6'b00_00_00)))) : 6'b00_00_00;

  wire [5:0] white = ~ui_in[5:0];
  wire [5:0] grey = white ^ 6'b00_10_10;

  assign {R, G, B} =
      video_active ?
        // (a ? (pix_y[0] ^ pix_x[0] ? 6'b11_11_11 : 6'b00_00_00) :
        ((a & (pix_y[1] ^ pix_x[0])) ? white :
          (b & (~pix_y[0] ^ pix_x[1]) ? grey :
            (c ? 6'b10_00_00 :
              (d ? 6'b01_00_00 :
                (e & (pix_y[1] ^ pix_x[0]) ? 6'b01_00_00 : 6'b00_00_00))))) : 6'b00_00_00;

  // assign {R, G, B} =
  //     video_active ?
  //       // (a ? (pix_y[0] ^ pix_x[0] ? 6'b11_11_11 : 6'b00_00_00) :
  //       ((a & (pix_y[1] ^ pix_x[0])) ? 6'b11_11_11 :
  //         (b & (~pix_y[0] ^ pix_x[1]) ? 6'b11_10_10 :
  //           (c ? 6'b10_00_00 :
  //             (d ? 6'b01_00_00 :
  //               (e ? 6'b01_00_00 : 6'b00_00_00))))) : 6'b00_00_00;

  // assign {R, G, B} =
  //     video_active ?
  //       // (a ? (pix_y[0] ^ pix_x[0] ? 6'b11_11_11 : 6'b00_00_00) :
  //       ((a & (pix_y[1] ^ pix_x[0])) ? 6'b11_11_11 :
  //         (b & (~pix_y[0] ^ pix_x[1]) ? 6'b11_10_10 :
  //           (c ? 6'b10_00_00 :
  //             (d ? 6'b01_00_00 : 6'b00_00_00)))) : 6'b00_00_00;

  // assign {R, G, B} =
  //     video_active ?
  //       // (a ? (pix_y[0] ^ pix_x[0] ? 6'b11_11_11 : 6'b00_00_00) :
  //       ((a & (pix_y[0] ^ pix_x[0])) ? 6'b11_11_11 :
  //         (b ? 6'b11_00_01 :
  //           (c ? 6'b10_00_00 :
  //             (d ? 6'b01_00_00 : 6'b00_00_00)))) : 6'b00_00_00;

    // video_active ?
    //   a ? 6'b11_11_00 : 6'b00_00_00;

  // assign R = video_active ? {moving_x[6], moving_y[6]} : 2'b00;
  // assign R = video_active ? x * 2'b11 : 2'b00;
  // assign G = 2'b00;//video_active ? {moving_x[6], pix_y[2]} : 2'b00;
  // assign B = 2'b00;//video_active ? {moving_x[7], pix_y[5]} : 2'b00;

  always @(posedge vsync) begin
    if (~rst_n) begin
      counter <= 0;
    end else begin
      counter <= counter + 1;
    end
  end

endmodule


`default_nettype none
module tt_um_shadow1229_vga_player (
    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 hsync;
    wire vsync;
    reg [3:0] spi_uio_out; //wire ->reg is this right?
    wire [5:0] rrggbb;
    wire [5:0] color_on;
    wire [5:0] color_off;

    /*ui_in
    0: 74880Hz 1-bit PCM(0) / 9360Hz 8-bit PWM(1)
    1: Tiny VGA(0) / VGA clock PMOD(1)
    2: color_off(0) - R
    3: color_off(0) - G
    4: color_off(0) - B
    5: color_on(1)  - R
    6: color_on(1)  - G
    7: color_on(1)  - B

    // https://github.com/mole99/tiny-vga
    // https://github.com/TinyTapeout/tt-vga-clock-pmod
    */
    assign color_on[5:0]  = {ui_in[5], ui_in[5], ui_in[6], ui_in[6], ui_in[7], ui_in[7]};
    assign color_off[5:0] = {ui_in[2], ui_in[2], ui_in[3], ui_in[3], ui_in[4], ui_in[4]};
    assign uo_out[0] = ui_in[1] ? hsync_q   :rrggbb[5];
    assign uo_out[1] = ui_in[1] ? vsync_q   :rrggbb[3];
    assign uo_out[2] = ui_in[1] ? rrggbb[0] :rrggbb[1];
    assign uo_out[3] = ui_in[1] ? rrggbb[1] :vsync_q;
    assign uo_out[4] = ui_in[1] ? rrggbb[2] :rrggbb[4];
    assign uo_out[5] = ui_in[1] ? rrggbb[3] :rrggbb[2];
    assign uo_out[6] = ui_in[1] ? rrggbb[4] :rrggbb[0];
    assign uo_out[7] = ui_in[1] ? rrggbb[5] :hsync_q;

    assign uio_out = ui_in[0] ? {spi_sel,spi_clk,spi_uio_out[3:0],sound_p_pwm,sound_n_pwm}: {spi_sel,spi_clk,spi_uio_out[3:0],sound_p_pcm,sound_n_pcm};
    assign uio_oe = rst_n ? {2'b11,spi_oe[3:0] ,2'b11} : 8'b11000000;

    //PWM modulation: LTC2644
    //W25Q128JVSSIQ address: FFFFFF https://www.adafruit.com/product/5634
    wire reset = ~rst_n;

    reg [127:0] cache_row; //10Byte for line / 3x2 byte for sound
    reg [127:0] data_row;
    reg cache_done;
    reg data_done;

    wire [9:0] x_px;          // X position for actual pixel.
    wire [9:0] y_px;          // Y position for actual pixel.
    wire [9:0] vc;          // vertical counter (0 ~480+40-1)
    //wire [9:0] hc;          // horizontal counter (0 ~ 640+192-1) (52*16-1)
    // blocks are 16 x 16 px. (40 x 30 -> 640 x 480)
    /* verilator lint_off WIDTH */
    wire [6:0] x_block = (x_px) >> 3;
    wire [6:0] v_block = (vc) >> 3;
    /* verilator lint_on WIDTH */
    wire activevideo;
    reg [1:0]frame_iter; //24fps - show same frame for three times
    reg [15:0] n_frame;
    //reg [6:0] x_block_q; //to match up signals using x_block_q
    reg [6:0] v_block_q;
    reg hsync_q;
    reg vsync_q;
    reg activevideo_q;
    //reg draw;
    reg overflow;

    wire px_clk;
    wire spi_clk;
    reg [7:0] read_cmd = 8'b01101011; //Fast Read Quad Output (6Bh, MSB -> LSB, read at rising clk of spi_clk. = falling clk of px_clk)
    wire spi_sel;
    assign px_clk = clk;
    assign spi_clk = ~clk && spi_clk_on;
    assign spi_sel = ~spi_sel_on;
    reg  [3:0] spi_oe;
    reg spi_sel_on;
    reg spi_clk_on;
    reg spi_cmd_on;
    reg spi_addr_on;
    reg spi_dummy_on;
    reg spi_read_on;
    reg [3:0] spi_cmd_n;
    reg [6:0] spi_addr_n;
    reg [3:0] spi_dummy_n;
    reg [5:0] spi_read_n;
    reg [23:0] addr; // this addr tells byte address, not bit address! keep in mind that

    //sound
    reg  [15:0] sound_reg;
    //PCM
    reg  [3:0] sound_block_pcm; //+1 (x_px = 223 / 639 (+1 each 8*52 clocks))/ resets at next data
    reg        pcm_0_aux; //auxilliary register for pcm sound, used at sound_block updating clock
    reg sound_p_pcm;
    reg sound_n_pcm;
    //PWM
    reg [7:0] counter_pwm; //+1 per each clk
    reg [7:0] threshold_pwm;
    reg sound_p_pwm;
    reg sound_n_pwm;

    VgaSyncGen vga_0 (.data_done(data_done), .px_clk(px_clk), .hsync(hsync), .vsync(vsync), .x_px(x_px), .y_px(y_px),.vc(vc), .activevideo(activevideo), .reset(reset));
    assign rrggbb = activevideo_q &&  data_row[79 - x_block] ? color_on : color_off;

    always @(posedge px_clk) begin
        //$display("x_px %d %b | y_px %d %b | hsync %d | vsync %d | activevideo %d | cache_done %d | data_done %d", x_px, x_px, y_px, y_px, hsync, vsync, activevideo, cache_done, data_done);
        if(reset || overflow == 1) begin

            cache_row <= 0;
            data_row <= 0;
            cache_done <= 0;
            data_done <= 0;

            frame_iter <= 0;
            n_frame <= 0;
            //x_block_q <= 0;
            v_block_q <= 0;
            hsync_q <= 1;
            vsync_q <= 1;
            activevideo_q <= 0;
            //draw <= 0;
            overflow <= 0;

            spi_oe <= 0;
            spi_sel_on <= 0;
            spi_clk_on <= 0;
            spi_cmd_on <= 0;
            spi_addr_on <= 0;
            spi_dummy_on <= 0;
            spi_read_on <= 0;
            spi_cmd_n <= 0;
            spi_addr_n <= 0;
            spi_dummy_n <= 0;
            spi_read_n <= 0;
            addr <= 0;

            sound_reg <= 0;
            sound_block_pcm <= 0;
            pcm_0_aux <= 0;
            sound_p_pcm <=0;
            sound_n_pcm <= 1;
            counter_pwm <= 0; //+1 per each clk
            threshold_pwm <= 0;
            sound_p_pwm <=0;
            sound_n_pwm <= 1;
			spi_uio_out <= 0;
        end

        //SPI flash module
        if (cache_done == 0) begin

            if (spi_sel_on == 0) begin
                spi_sel_on <= 1'b1;

            end else begin
                if (spi_clk_on == 0 && spi_cmd_on == 0 && spi_addr_on == 0 && spi_dummy_on == 0 && spi_read_on == 0 ) begin
                    //$display("x_px %d %b | y_px %d %b | hsync %d | vsync %d | activevideo %d | cache_done %d | data_done %d", x_px, x_px, y_px, y_px, hsync, vsync, activevideo, cache_done, data_done);

                    //spi_clk_on <= 1'b1;
                    spi_oe[0] <= 1'b1;
                    spi_cmd_on <= 1'b1;
                    spi_cmd_n <= 0;
                    cache_row <= 0;

                end else if (spi_cmd_on == 1 && spi_addr_on == 0 && spi_dummy_on == 0 && spi_read_on == 0 ) begin
                    spi_clk_on <= 1'b1; //cmd and clk should work simultaneously

                    spi_uio_out[0] <= read_cmd[7-spi_cmd_n];
                    spi_uio_out[1] <= 0;
                    spi_uio_out[2] <= 0;
                    spi_uio_out[3] <= 0;
                    //$display("cmd is %d | %b", spi_cmd_n, read_cmd[7-spi_cmd_n]); //01101011. works fine         //read_cmd = 8'b01101011
                    spi_cmd_n <= spi_cmd_n + 1;

                    if (spi_cmd_n == 7) begin
                        spi_cmd_on <= 0;
                        spi_addr_on <= 1;
                        spi_addr_n <= 0;
                        if (frame_iter <2 && v_block_q == 64) begin
                            //bit_addr <= n_frame * 128*65 + v_block_q*128 + data_done*128 - 8320;
                            addr <= n_frame * 16*65 + v_block_q*16 + data_done*16 - 1040;
                        end else begin
                            //bit_addr <= n_frame * 128*65 + v_block_q*128 + data_done*128 ;
                            addr <= n_frame * 16*65 + v_block_q*16 + data_done*16;
                        end
                        //$display("n_frame %d | frame_iter %d | y_px %d %b | v_block_q %d %b | addr%d",n_frame, frame_iter, y_px, y_px, v_block_q, v_block_q, addr); //01101011. works fine         //read_cmd = 8'b01101011
                    end
                end else if (spi_clk_on == 1 && spi_cmd_on == 0 && spi_addr_on == 1 && spi_dummy_on == 0 && spi_read_on == 0 ) begin
                    spi_uio_out[0] <= addr[23-spi_addr_n];
                    spi_uio_out[1] <= 0;
                    spi_uio_out[2] <= 0;
                    spi_uio_out[3] <= 0;
                    //$display("addr is %d | %d | %b | %b", spi_addr_n, addr, addr, addr[23-spi_addr_n]); //01101011. works fine         //read_cmd = 8'b01101011
                    spi_addr_n <= spi_addr_n + 1;

                    if (spi_addr_n == 23) begin
                        //$display("addr is %d | %d | %b | %b", spi_addr_n, addr, addr, addr[23-spi_addr_n]); //01101011. works fine         //read_cmd = 8'b01101011

                        spi_addr_on <= 0;
                        spi_dummy_on <= 1;
                        spi_dummy_n <= 0;
                    end
                end else if (spi_clk_on == 1 && spi_cmd_on == 0 && spi_addr_on == 0 && spi_dummy_on == 1 && spi_read_on == 0 ) begin
                    spi_oe[0] <= 1'b0;

                    //$display("dummy_n is %d ", spi_dummy_n); //01101011. works fine         //read_cmd = 8'b01101011
                    spi_dummy_n <= spi_dummy_n + 1;
                    //$display("veri dummy_n %d", spi_dummy_n);

                    if (spi_dummy_n == 7) begin
                        spi_dummy_on <= 0;
                        spi_read_on <= 1;
                        spi_read_n <= 0;
                        //$display("veri dummy_n last");
                    end
                end else if (spi_clk_on == 1 && spi_cmd_on == 0 && spi_addr_on == 0 && spi_dummy_on == 0 && spi_read_on == 1 ) begin
                    //1 clk delay in uio_in
                    //$display("read_n %d %b", spi_read_n,uio_in[5:2]);
                    if (spi_read_n > 0 && spi_read_n <= 32) begin
                        cache_row <= {cache_row[123:0], uio_in[5:2]};
                    end

                    if (spi_read_n == 32) begin
                        spi_read_on <= 0;
                        cache_done <= 1;
                        //$display("read end cache_row  : %b", cache_row);
                        //$display("read end data_row   : %b\n", data_row);
                    end

                    spi_read_n <= spi_read_n + 1;

                    //$display("read_n is %d ", spi_read_n); //01101011. works fine         //read_cmd = 8'b01101011
                    //$display("spi_uio_in: %b %b", uio_in, uio_in[5:2]);
                    //$display("cache_row: %b\n", cache_row);

                end
            end
        end else begin
            if (spi_clk_on == 1 && spi_cmd_on == 0 && spi_addr_on == 0 && spi_dummy_on == 0 && spi_read_on == 0) begin
                spi_clk_on <= 0;
                spi_sel_on <= 0;

                //$display("spi_sel_off");
            end
        end
        //SPI flash module end

        //happens only once, at the first time
        if(data_done == 1'b0 && cache_done == 1'b1) begin
            data_done <= 1'b1;
            cache_done <= 1'b0;
            data_row[127:0] <= cache_row[127:0];
        end

        //cache to data
        //x_block_q <= x_block; //is this correct? using reg here
        v_block_q <= v_block;
        hsync_q <= hsync;
        vsync_q <= vsync;
        activevideo_q <= activevideo;
        //$display("  n_frame %d frame_iter %d x_px %d y_px %d sound_reg %b sound_block_pcm %d sound_reg[15-sound_block_pcm] %b sound_p_pcm %b", n_frame, frame_iter, x_px, y_px, sound_reg, sound_block_pcm, sound_reg, sound_p_pcm);
        //$display("data_row: %b", data_row);

        if (x_px == 639 && y_px%8 == 7 && cache_done == 1'b1) begin //right before the sound_reg update, used for pcm
            case (frame_iter)
                0: begin
                    pcm_0_aux <= cache_row[127];
                end
                1: begin
                    pcm_0_aux <= cache_row[111];
                end
                2: begin
                    pcm_0_aux <=  cache_row[95];
                end
            endcase
            //$display("  n_frame %d frame_iter %d x_px %d y_px %d sound_reg %b sound_block_pcm %d sound_reg[15-sound_block_pcm] %b sound_p_pcm %b", n_frame, frame_iter, x_px, y_px, sound_reg, sound_block_pcm, sound_reg, sound_p_pcm);

        end
        //update sound and video data
        if (x_px == 832 && y_px%8 == 0 && cache_done == 1'b1) begin
            cache_done <= 1'b0;
            data_row[127:0] <= cache_row[127:0]; // video update
            sound_block_pcm <= 0;
            //sound_block_pwm <= 0;
            case (frame_iter)
                0: begin
                    sound_reg[15:0] <= cache_row[127:112];
                    threshold_pwm[7:0] <= cache_row[127:120];
                end
                1: begin
                    sound_reg[15:0] <= cache_row[111:96];
                    threshold_pwm[7:0] <= cache_row[111:104];
                end
                2: begin
                    sound_reg[15:0] <= cache_row[95:80];
                    threshold_pwm[7:0] <= cache_row[95:88];
                end
            endcase
            sound_p_pcm <= pcm_0_aux;
            sound_n_pcm <= ~pcm_0_aux;
            //$display("x_px %d %b | y_px %d %b | hsync %d | vsync %d | activevideo %d | cache_done %d | data_done %d", x_px, x_px, y_px, y_px, hsync, vsync, activevideo, cache_done, data_done);
            //$display("cache->data"); //01101011. works fine         //read_cmd = 8'b01101011
            //$display("cache2data cache_row: %b", cache_row);
            //$display("cache2data data_row:  %b\n", data_row);
            //$display("  n_frame %d frame_iter %d x_px %d y_px %d sound_reg %b sound_block_pcm %d sound_reg[15-sound_block_pcm] %b sound_p_pcm %b", n_frame, frame_iter, x_px, y_px, sound_reg, sound_block_pcm, sound_reg, sound_p_pcm);

        end else begin
            sound_p_pcm <= sound_reg[15-sound_block_pcm];
            sound_n_pcm <= ~sound_reg[15-sound_block_pcm];
        end

        if (x_px == 832 && y_px%8 == 4) begin
            threshold_pwm[7:0] <= sound_reg[7:0];
        end

        //PCM update
        if (x_px == 223) begin
            sound_block_pcm <= sound_block_pcm + 1;
        end
        if (x_px == 639) begin
            sound_block_pcm <= sound_block_pcm + 1;
        end

        //PWM update (y 4px / each 256 clk)
        counter_pwm <= counter_pwm + 1;
        if (counter_pwm[7:0] < threshold_pwm[7:0] ) begin
            sound_p_pwm <= 1;
            sound_n_pwm <= 0;
        end else begin
            sound_p_pwm <= 0;
            sound_n_pwm <= 1;
        end
        //update frame_iter
        //1. frame_iter_need_update becomes 1 at y_px = -40
        // 480 - 1   /  -192 mod 1024
        if (y_px == 479 && x_px == 832 ) begin
            frame_iter <= frame_iter + 1'b1;
        end

        //72Hz -> 24 fps
        if(y_px == 479 && x_px == 833 && frame_iter == 2'b11) begin
            n_frame <= n_frame + 1'b1;
            frame_iter <= 2'b00;
        end

        if(y_px == 479 && x_px == 834 && n_frame == 16131) begin
            overflow <= 1; //(2^24 byte / 1040 byte per frame = 16131.9384615 -> overflow happens at 16131th frame)
        end

    end

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        data_done,        // Input clock: 31.5MHz
            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 reg [9:0] vc,          //Y(vertical) counter.
            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 if(data_done == 1'b1) 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 if(data_done == 1'b1) begin
            x_px <= hc - blackH;
            y_px <= vc - blackV;
        end
     end
 endmodule
`default_nettype wire


/*
 * Copyright (c) 2024 Your Name
 * SPDX-License-Identifier: Apache-2.0
 */

`default_nettype none

module tt_um_PUF (
    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;

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

// module top (output [7:0] response, input en, reset, input [9:0] challenge);
    wire [7:0] count1, count2;
    top_f2g uut1(count1, ena,  rst_n, ui_in[4:0]);
    top_f2g uut2(count2, ena,  rst_n, ui_in[4:0]);
comp uut3(count1, count2, uo_out);
endmodule

module f2g (output p, q, r, input a, b, c);
assign p=a;
assign q=a^b;
assign r=a^c;
endmodule

module osc_f2g (output out, input ena);
wire [4:0] p, q, r;
wire A;
f2g g0(p[0], q[0], r[0], A, 1'b1, 1'b1);
f2g g1(p[1], q[1], r[1], r[0], 1'b1, 1'b1);
f2g g2(p[2], q[2], r[2], q[1], 1'b1, 1'b1);
f2g g3(p[3], q[3], r[3], r[2], 1'b1, 1'b1);
f2g g4(p[4], q[4], r[4], q[3], 1'b1, 1'b1);
and a0(out, ena, r[4]);
assign A=out;
endmodule

module top_f2g (output [7:0] count, input ena,  rst_n, input [4:0] ui_in);
wire [31:0] i;
wire mux_out;
genvar x;
generate
    for(x=0; x<32; x=x+1)
    begin
        (* S= "TRUE"*)(* ALLOW_COMBINATORIAL_LOOPS = "true", KEEP = "true" *)
        osc_f2g f0(i[x], ena);
    end
endgenerate

mux32 uut(i, ui_in, mux_out);

counter c(mux_out,  rst_n, count);
endmodule

module mux32(
    input wire[32:1] i,
    input wire[4:0] ui_in,
    output reg m_out
    );

    (* S= "TRUE"*)(* ALLOW_COMBINATORIAL_LOOPS = "true", KEEP = "true" *)
    always @(*)

    begin
    case(ui_in)
        5'b00000: m_out=i[1];
        5'b00001: m_out=i[2];
        5'b00010: m_out=i[3];
        5'b00011: m_out=i[4];
        5'b00100: m_out=i[5];
        5'b00101: m_out=i[6];
        5'b00110: m_out=i[7];
        5'b00111: m_out=i[8];
        5'b01000: m_out=i[9];
        5'b01001: m_out=i[10];
        5'b01010: m_out=i[11];
        5'b01011: m_out=i[12];
        5'b01100: m_out=i[13];
        5'b01101: m_out=i[14];
        5'b01110: m_out=i[15];
        5'b01111: m_out=i[16];
        5'b10000: m_out=i[17];
        5'b10001: m_out=i[18];
        5'b10010: m_out=i[19];
        5'b10011: m_out=i[20];
        5'b10100: m_out=i[21];
        5'b10101: m_out=i[22];
        5'b10110: m_out=i[23];
        5'b10111: m_out=i[24];
        5'b11000: m_out=i[25];
        5'b11001: m_out=i[26];
        5'b11010: m_out=i[27];
        5'b11011: m_out=i[28];
        5'b11100: m_out=i[29];
        5'b11101: m_out=i[30];
        5'b11110: m_out=i[31];
        5'b11111: m_out=i[32];
    endcase
    end
endmodule

module counter(
    input m_out,
    input  rst_n,
    output reg[7:0] count
    );

    (* S= "TRUE"*)(* ALLOW_COMBINATORIAL_LOOPS = "true", KEEP = "true" *)
    initial count=8'h00;
    always @(posedge m_out or posedge  rst_n)
    begin
        if( rst_n)
            begin
                count = 0;
            end
        else
            begin
                count = count + 1;
            end
    end
endmodule

module comp(
    input [7:0] count1,
    input [7:0] count2,
    output reg[7:0] uo_out
    );

    (* S= "TRUE"*)(* ALLOW_COMBINATORIAL_LOOPS = "true", KEEP = "true" *)

    always @(count1 or count2)
        begin
            if(&count1 > &count2)
                begin
                    uo_out <= count1;
                end
            else
                begin
                    uo_out <= count2;
                end
        end
endmodule


/*
 * Copyright (c) 2024 Your Name
 * SPDX-License-Identifier: Apache-2.0
 */

`default_nettype none

module tt_um_multiplier_mbm (
    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_oe=0;

wire [7:0]mcand,mlier;
wire [15:0]ans;
latchh lat1(ui_in,clk,mcand);
latchh lat2(uio_in,clk,mlier);

wire [22:1]s;
wire [21:1]c;

wire [7:0]two_compl;
assign two_compl=~mcand+1;

reg [15:0]p0;
reg [13:0]p1;
reg [11:0]p2;
reg [9:0]p3;

wire [4:0]x1,x2,x3,x4;
//partial 1
 booth_encoding cod1(mlier[1],mlier[0],1'b0,x1[4],x1[3],x1[2],x1[1],x1[0]);
 always @( * )
        begin
          p0=16'd0;
          case (x1)
              5'b10000: p0=16'd0;
              5'b01000: p0={{8{mcand[7]}},mcand};
              5'b00100: p0={{8{two_compl[7]}},two_compl};
              5'b00010: p0={{7{mcand[7]}},mcand,1'b0};
              5'b00001:
              begin
                p0={{7{two_compl[7]}},two_compl,1'b0};
               end
              default: p0=16'd0;
          endcase
      end

//partial 2

    booth_encoding cod2(mlier[3],mlier[2],mlier[1],x2[4],x2[3],x2[2],x2[1],x2[0]);
 always @( * )
        begin
          p1=14'd0;
          case (x2)
              5'b10000: p1=14'd0;
              5'b01000: p1={{6{mcand[7]}},mcand};
              5'b00100: p1={{6{two_compl[7]}},two_compl};
              5'b00010: p1={{5{mcand[7]}},mcand,1'd0};
              5'b00001:
              begin
                p1={{5{two_compl[7]}},two_compl,1'd0};
               end
              default: p1=14'd0;
          endcase
      end

 //partial 3
 booth_encoding cod3(mlier[5],mlier[4],mlier[3],x3[4],x3[3],x3[2],x3[1],x3[0]);
 always @( * )
        begin
          p2=12'd0;
          case (x3)
              5'b10000: p2=12'd0;
              5'b01000: p2={{4{mcand[7]}},mcand};
              5'b00100: p2={{4{two_compl[7]}},two_compl};
              5'b00010: p2={{3{mcand[7]}},mcand,1'd0};
              5'b00001:
              begin
                p2={{3{two_compl[7]}},two_compl,1'd0};
               end
              default: p2=12'd0;
          endcase
      end

//partial 4
booth_encoding cod4(mlier[7],mlier[6],mlier[5],x4[4],x4[3],x4[2],x4[1],x4[0]);
always @( * )
        begin
          p3=10'd0;
          case (x4)
              5'b10000: p3=10'd0;
              5'b01000: p3={{2{mcand[7]}},mcand};
              5'b00100: p3={{2{two_compl[7]}},two_compl};
              5'b00010: p3={{1{mcand[7]}},mcand,1'd0};
              5'b00001:
              begin
                p3={{1{two_compl[7]}},two_compl,1'd0};
               end
              default: p3=10'd0;
          endcase
      end

//1st reduction 4 to 3
assign s[1]=p2[2] ^ p3[0];
assign c[1]=p2[2] & p3[0];

assign s[2]=(p1[5] ^p2[3]) ^ p3[1];
assign c[2]= (p1[5] & p2[3]) | (p2[3] & p3[1]) | (p3[1] & p1[5]);

assign s[3]=( p1[6] ^p2[4] ) ^ p3[2];
assign c[3]= (p1[6] & p2[4]) | (p2[4] & p3[2]) | (p3[2] & p1[6]);

assign s[4]=( p1[7] ^p2[5] ) ^ p3[3];
assign c[4]= (p1[7] & p2[5]) | (p2[5] & p3[3]) | (p3[3] & p1[7]);

assign s[5]=( p1[8] ^p2[6] ) ^ p3[4];
assign c[5]= (p1[8] & p2[6]) | (p2[6] & p3[4]) | (p3[4] & p1[8]);

assign s[6]=( p1[9] ^p2[7] ) ^ p3[5];
assign c[6]= (p1[9] & p2[7]) | (p2[7] & p3[5]) | (p3[5] & p1[9]);

assign s[7]=( p1[10] ^p2[8] ) ^ p3[6];
assign c[7]= (p1[10] & p2[8]) | (p2[8] & p3[6]) | (p3[6] & p1[10]);

assign s[8]=( p1[11] ^p2[9] ) ^ p3[7];
assign c[8]= (p1[11] & p2[9]) | (p2[9] & p3[7]) | (p3[7] & p1[11]);

assign s[9]=( p1[12] ^p2[10] ) ^ p3[8];
assign c[9]= (p1[12] & p2[10]) | (p2[10] & p3[8]) | (p3[8] & p1[12]);

assign s[10]=( p1[13] ^p2[11] ) ^ p3[9];
//assign c[10]= (p1[13] & p2[11]) | (p2[11] & p3[9]) | (p3[9] & p1[13]);

//2nd reduction 3 to 2
assign s[11]=p1[2] ^ p2[0];
assign c[11]=p1[2] & p2[0];

assign s[12]=( p0[5] ^p1[3] ) ^ p2[1];
assign c[12]= (p0[5] & p1[3]) | (p1[3] & p2[1]) | (p2[1] & p0[5]);

assign s[13]=( p0[6] ^p1[4] ) ^ s[1];
assign c[13]= (p0[6] & p1[4]) | (p1[4] & s[1]) | (s[1] & p0[6]);

assign s[14]=( p0[7] ^c[1] ) ^ s[2];
assign c[14]= (p0[7] & c[1]) | (c[1] & s[2]) | (s[2] & p0[7]);

assign s[15]=( p0[8] ^c[2] ) ^ s[3];
assign c[15]= (p0[8] & c[2]) | (c[2] & s[3]) | (s[3] & p0[8]);

assign s[16]=( p0[9] ^c[3] ) ^ s[4];
assign c[16]= (p0[9] & c[3]) | (c[3] & s[4]) | (s[4] & p0[9]);

assign s[17]=( p0[10] ^c[4] ) ^ s[5];
assign c[17]= (p0[10] & c[4]) | (c[4] & s[5]) | (s[5] & p0[10]);

assign s[18]=( p0[11] ^c[5] ) ^ s[6];
assign c[18]= (p0[11] & c[5]) | (c[5] & s[6]) | (s[6] & p0[11]);

assign s[19]=( p0[12] ^c[6] ) ^ s[7];
assign c[19]= (p0[12] & c[6]) | (c[6] & s[7]) | (s[7] & p0[12]);

assign s[20]=( p0[13] ^c[7] ) ^ s[8];
assign c[20]= (p0[13] & c[7]) | (c[7] & s[8]) | (s[8] & p0[13]);

assign s[21]=( p0[14] ^c[8] ) ^ s[9];
assign c[21]= (p0[14] & c[8]) | (c[8] & s[9]) | (s[9] & p0[14]);

assign s[22]=( p0[15] ^c[9] ) ^ s[10];

cla cla1(.x({c[21:11],p0[4:0]}),.y({s[22:11],p1[1],p1[0]}),.cin(1'b0),.sum({ans}));

latchh lat3(ans[7:0],clk,uo_out);
latchh lat4(ans[15:8],clk,uio_out);

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

endmodule

module latchh(input [7:0]d,           // 1-bit input pin for data
             input clk,          // 1-bit input pin for enabling the latch
              output reg [7:0]q);     // 1-bit output pin for data output

   always @ (posedge clk)
    q <= d;
endmodule

module booth_encoding(input a,b,c,
                output zero,one,minus_one,two, minus_two);
wire a_n,b_n,c_n,a1,a2,a3,a4,a5,a6;
wire [7:0]i;

decoder_3_8 dec({a,b,c},i);

assign a_n=~a;
assign b_n=~b;
assign c_n=~c;

assign a1= a_n & b_n & c_n & i[0];
assign a2=a & b & c & i[7];
assign a3= a_n & b_n & c & i[1];
assign a4= a_n & b & c_n & i[2];

assign zero= a1 | a2;
assign one= a3 | a4;

assign a5= a & b_n & c & i[5];
assign a6= a & b & c_n & i[6];
assign minus_one= a5 | a6;

assign two= a_n & b & c & i[3];
assign minus_two=a & b_n & c_n & i[4];

endmodule

module decoder_3_8(input [2:0]din,
                    output reg[7:0]dout);
 always @( din )
        begin
          dout=8'd0;
          case (din)
              3'b000: dout[0]=1'b1;
              3'b001: dout[1]=1'b1;
              3'b010: dout[2]=1'b1;
              3'b011: dout[3]=1'b1;
              3'b100: dout[4]=1'b1;
              3'b101: dout[5]=1'b1;
              3'b110: dout[6]=1'b1;
              3'b111: dout[7]=1'b1;
              default: dout=8'd0;
          endcase
      end
endmodule

module cla(input [15:0]x, input [13:0]y, input cin, output  [15:0]sum);
wire [13:0] p;
wire [13:0]g;
wire [13:1] c;

assign sum[0]= x[0];
assign sum[1]= x[1];

assign p[0]= x[2] ^ y[0];
assign g[0]= x[2] & y[0];
assign c[1]= g[0] | (p[0] & cin);
assign sum[2]= p[0] ^ cin;

assign p[1]= x[3] ^ y[1];
assign g[1]= x[3] & y[1];
assign c[2]= g[1] | (p[1] & g[0]) | (p[1] & p[0] & cin);
assign sum[3]= p[1] ^ c[1];

assign p[2]= x[4] ^ y[2];
assign g[2]= x[4] & y[2];
assign c[3]= g[2] | (p[2] & g[1]) | (p[2] & p[1] & g[0]) | (p[2] & p[1] & p[0] & cin);
assign sum[4]= p[2] ^ c[2];

assign p[3]= x[5] ^ y[3];
assign g[3]= x[5] & y[3];
assign c[4]= g[3] | (p[3] & g[2]) | (p[3] & p[2] & g[1]) | (p[3] & p[2] & p[1] & g[0]) | (p[3] & p[2] & p[1] & p[0] & cin);
assign sum[5]= p[3] ^ c[3];

assign p[4]= x[6] ^ y[4];
assign g[4]= x[6] & y[4];
assign c[5]= g[4] | (p[4] & g[3]) |(p[4] & p[3] & g[2]) |(p[4] & p[3] & p[2] & g[1]) | (p[4] & p[3] & p[2] & p[1] & g[0]) | (p[4] & p[3] & p[2] & p[1] & p[0] & cin);
assign sum[6]= p[4] ^ c[4];

assign p[5]= x[7] ^ y[5];
assign g[5]= x[7] & y[5];
assign c[6]= g[5] | (p[5] & g[4]) |(p[5] & p[4] & g[3]) |(p[5] & p[4] & p[3] & g[2]) | (p[5] & p[4] & p[3] & p[2] & g[1]) | (p[5] & p[4] & p[3] & p[2] & p[1] & g[0]) | (p[5] & p[4] & p[3] & p[2] & p[1] & p[0] & cin);
assign sum[7]= p[5] ^ c[5];

assign p[6]= x[8] ^ y[6];
assign g[6]= x[8] & y[6];
assign c[7]= g[6] | (p[6] & g[5]) | (p[6] & p[5] & g[4]) |(p[6] & p[5] & p[4] & g[3]) |(p[6] & p[5] & p[4] & p[3] & g[2]) | (p[6]  & p[5] & p[4] & p[3] & p[2] & g[1]) | (p[6] & p[5] & p[4] & p[3] & p[2] & p[1] & g[0]) | (p[6] & p[5] & p[4] & p[3] & p[2] & p[1] & p[0] & cin);
assign sum[8]= p[6] ^ c[6];

assign p[7]= x[9] ^ y[7];
assign g[7]= x[9] & y[7];
assign c[8]= g[7] | (p[7] & g[6]) | (p[7] & p[6] & g[5]) | (p[7] & p[6] & p[5] & g[4]) |(p[7] & p[6] & p[5] & p[4] & g[3]) |(p[7] & p[6] & p[5] & p[4] & p[3] & g[2]) | (p[7] & p[6] & p[5] & p[4] & p[3] & p[2] & g[1]) | (p[7] & p[6] & p[5] & p[4] & p[3] & p[2] & p[1] & g[0]) | (p[7] & p[6] & p[5] & p[4] & p[3] & p[2] & p[1] & p[0] & cin);
assign sum[9]= p[7] ^ c[7];

assign p[8]= x[10] ^ y[8];
assign g[8]= x[10] & y[8];
assign c[9]= g[8] | (p[8] & g[7]) | (p[8] & p[7] & g[6]) | (p[8] & p[7] & p[6] & g[5]) | (p[8] & p[7] & p[6] & p[5] & g[4]) |(p[8] & p[7] & p[6] & p[5] & p[4] & g[3]) |(p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & g[2]) | (p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & p[2] & g[1]) | (p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & p[2] & p[1] & g[0]) | (p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & p[2] & p[1] & p[0] & cin);
assign sum[10]= p[8] ^ c[8];

assign p[9]= x[11] ^ y[9];
assign g[9]= x[11] & y[9];
assign c[10]= g[9] | (p[9] & g[8]) | (p[9] & p[8] & g[7]) | (p[9] & p[8] & p[7] & g[6]) | (p[9] & p[8] & p[7] & p[6] & g[5]) | (p[9] & p[8] & p[7] & p[6] & p[5] & g[4]) |(p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & g[3]) |(p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & g[2]) | (p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & p[2] & g[1]) | (p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & p[2] & p[1] & g[0]) | (p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & p[2] & p[1] & p[0] & cin);
assign sum[11]= p[9] ^ c[9];

assign p[10]= x[12] ^ y[10];
assign g[10]= x[12] & y[10];
assign c[11]= g[10] | (p[10] & g[9]) | (p[10] & p[9] & g[8]) | (p[10] & p[9] & p[8] & g[7]) | (p[10] & p[9] & p[8] & p[7] & g[6]) | (p[10] & p[9] & p[8] & p[7] & p[6] & g[5]) | (p[10] & p[9] & p[8] & p[7] & p[6] & p[5] & g[4]) |(p[10] & p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & g[3]) |(p[10] & p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & g[2]) | (p[10] & p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & p[2] & g[1]) | (p[10] & p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & p[2] & p[1] & g[0]) | (p[10] & p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & p[2] & p[1] & p[0] & cin);
assign sum[12]= p[10] ^ c[10];

assign p[11]= x[13] ^ y[11];
assign g[11]= x[13] & y[11];
assign c[12]= g[11] | (p[11] & g[10]) | (p[11] & p[10] & g[9]) | (p[11] & p[10] & p[9] & g[8]) | (p[11] & p[10] & p[9] & p[8] & g[7]) | (p[11] & p[10] & p[9] & p[8] & p[7] & g[6]) | (p[11] & p[10] & p[9] & p[8] & p[7] & p[6] & g[5]) | (p[11] & p[10] & p[9] & p[8] & p[7] & p[6] & p[5] & g[4]) |(p[11] & p[10] & p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & g[3]) |(p[11] & p[10] & p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & g[2]) | (p[11] & p[10] & p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & p[2] & g[1]) | (p[11] & p[10] & p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & p[2] & p[1] & g[0]) | (p[11] & p[10] & p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & p[2] & p[1] & p[0] & cin);
assign sum[13]= p[11] ^ c[11];

assign p[12]= x[14] ^ y[12];
assign g[12]= x[14] & y[12];
assign c[13]= g[12] | (p[12] & g[11]) | (p[12] & p[11] & g[10]) | (p[12] & p[11] & p[10] & g[9]) | (p[12] & p[11] & p[10] & p[9] & g[8]) | (p[12] & p[11] & p[10] & p[9] & p[8] & g[7]) | (p[12] & p[11] & p[10] & p[9] & p[8] & p[7] & g[6]) | (p[12] & p[11] & p[10] & p[9] & p[8] & p[7] & p[6] & g[5]) | (p[12] & p[11] & p[10] & p[9] & p[8] & p[7] & p[6] & p[5] & g[4]) |(p[12] & p[11] & p[10] & p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & g[3]) |(p[12] & p[11] & p[10] & p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & g[2]) | (p[12] & p[11] & p[10] & p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & p[2] & g[1]) | (p[12] & p[11] & p[10] & p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & p[2] & p[1] & g[0]) | (p[12] & p[11] & p[10] & p[9] & p[8] & p[7] & p[6] & p[5] & p[4] & p[3] & p[2] & p[1] & p[0] & cin);
assign sum[14]= p[12] ^ c[12];

assign p[13]= x[15] ^ y[13];
assign g[13]= x[15] & y[13];
assign sum[15]= p[13] ^ c[13];

endmodule