dakies/OSS_Verilog huggingface dataset:
module tbuart (
	input  ser_rx
);
	reg [3:0] recv_state;
	reg [2:0] recv_divcnt;
	reg [7:0] recv_pattern;
	reg [8*50-1:0] recv_buf_data;	// 50 characters.  Increase as needed for tests.

	reg clk;

	initial begin
		clk <= 1'b0;
		recv_state <= 0;
		recv_divcnt <= 0;
		recv_pattern <= 0;
		recv_buf_data <= 0;
	end

	// NOTE:  Running at 3.0us clock period @ 5 clocks per bit = 15.0us per
	// bit ~= 64 kbaud. Not tuned to any particular UART.  Most run at
	// 9600 baud default and will bounce up to higher baud rates when
	// passed specific command words.

	always #1500 clk <= (clk === 1'b0);

	always @(posedge clk) begin
		recv_divcnt <= recv_divcnt + 1;
		case (recv_state)
			0: begin
				if (!ser_rx)
					recv_state <= 1;
				recv_divcnt <= 0;
			end
			1: begin
				if (2*recv_divcnt > 3'd3) begin
					recv_state <= 2;
					recv_divcnt <= 0;
				end
			end
			10: begin
				if (recv_divcnt > 3'd3) begin
					// 0x0a = '\n'
					if (recv_pattern == 8'h0a) begin
						$display("output: %s", recv_buf_data);
					end else begin
						recv_buf_data <= {recv_buf_data, recv_pattern};
					end
					recv_state <= 0;
				end
			end
			default: begin
				if (recv_divcnt > 3'd3) begin
					recv_pattern <= {ser_rx, recv_pattern[7:1]};
					recv_state <= recv_state + 1;
					recv_divcnt <= 0;
				end
			end
		endcase
	end

endmodule
module uart_tb;
	reg clock;
	reg RSTB;
	reg power1, power2;

	wire gpio;
	wire flash_csb;
	wire flash_clk;
	wire flash_io0;
	wire flash_io1;
	wire [37:0] mprj_io;
	wire [15:0] checkbits;
	wire uart_tx;
	wire SDO;

	assign checkbits = mprj_io[31:16];
	assign uart_tx = mprj_io[6];

	always #12.5 clock <= (clock === 1'b0);

	initial begin
		clock = 0;
	end

	initial begin
		$dumpfile("uart.vcd");
		$dumpvars(0, uart_tb);

		$display("Wait for UART o/p");
		repeat (150) begin
			repeat (10000) @(posedge clock);
			// Diagnostic. . . interrupts output pattern.
		end
		$finish;
	end

	initial begin
		RSTB <= 1'b0;
		#1000;
		RSTB <= 1'b1;	    // Release reset
		#2000;
	end

	initial begin		// Power-up sequence
		power1 <= 1'b0;
		power2 <= 1'b0;
		#200;
		power1 <= 1'b1;
		#200;
		power2 <= 1'b1;
	end

	always @(checkbits) begin
		if(checkbits == 16'hA000) begin
			$display("UART Test started");
		end
		else if(checkbits == 16'hAB00) begin
			`ifdef GL
				$display("UART Test (GL) passed");
			`else
				$display("UART Test (RTL) passed");
			`endif
			$finish;
		end
	end

	wire VDD3V3;
	wire VDD1V8;
	wire VSS;

	assign VDD3V3 = power1;
	assign VDD1V8 = power2;
	assign VSS = 1'b0;
	
	assign mprj_io[3] = 1'b1;  // Force CSB high.

	caravel uut (
		.vddio	  (VDD3V3),
		.vssio	  (VSS),
		.vdda	  (VDD3V3),
		.vssa	  (VSS),
		.vccd	  (VDD1V8),
		.vssd	  (VSS),
		.vdda1    (VDD3V3),
		.vdda2    (VDD3V3),
		.vssa1	  (VSS),
		.vssa2	  (VSS),
		.vccd1	  (VDD1V8),
		.vccd2	  (VDD1V8),
		.vssd1	  (VSS),
		.vssd2	  (VSS),
		.clock	  (clock),
		.gpio     (gpio),
		.mprj_io  (mprj_io),
		.flash_csb(flash_csb),
		.flash_clk(flash_clk),
		.flash_io0(flash_io0),
		.flash_io1(flash_io1),
		.resetb	  (RSTB)
	);

	spiflash #(
		.FILENAME("uart.hex")
	) spiflash (
		.csb(flash_csb),
		.clk(flash_clk),
		.io0(flash_io0),
		.io1(flash_io1),
		.io2(),			// not used
		.io3()			// not used
	);

	// Testbench UART
	tbuart tbuart (
		.ser_rx(uart_tx)
	);
		
endmodule
module pll_tb;
	reg clock;
	reg power1;
	reg power2;
	reg RSTB;

	wire gpio;
	wire [15:0] checkbits;
	wire [7:0] spivalue;
	wire [37:0] mprj_io;
	wire flash_csb;
	wire flash_clk;
	wire flash_io0;
	wire flash_io1;
	wire SDO;

	assign checkbits = mprj_io[31:16];
	assign spivalue  = mprj_io[15:8];

	// External clock is used by default.  Make this artificially fast for the
	// simulation.  Normally this would be a slow clock and the digital PLL
	// would be the fast clock.

	always #10 clock <= (clock === 1'b0);

	initial begin
		clock = 0;
	end

	initial begin
		$dumpfile("pll.vcd");
		$dumpvars(0, pll_tb);
		repeat (25) begin
			repeat (1000) @(posedge clock);
			$display("+1000 cycles");
		end
		$display("%c[1;31m",27);
		`ifdef GL
			$display ("Monitor: Timeout, Test PLL (GL) Failed");
		`else
			$display ("Monitor: Timeout, Test PLL (RTL) Failed");
		`endif
		 $display("%c[0m",27);
		$finish;
	end

	// Monitor
	initial begin
	    wait(checkbits == 16'hA040);
		`ifdef GL
			$display("Monitor: Test PLL (GL) Started");
		`else
			$display("Monitor: Test PLL (RTL) Started");
		`endif

	    wait(checkbits == 16'hA041);
            // $display("   SPI value = 0x%x (should be 0x04)", spivalue);
            // if(spivalue !== 32'h04) begin
            //     $display("Monitor: Test PLL (RTL) Failed");
            //     $finish;
            // end
	    wait(checkbits == 16'hA042);
            // $display("   SPI value = 0x%x (should be 0x56)", spivalue);
            // if(spivalue !== 32'h56) begin
            //     $display("Monitor: Test PLL (RTL) Failed");
            //     $finish;
            // end

	    wait(checkbits == 16'hA090);
		`ifdef GL
            $display("Monitor: Test PLL (GL) Passed");
		`else
		    $display("Monitor: Test PLL (RTL) Passed");
		`endif
            $finish;
	end

	initial begin
		RSTB <= 1'b0;
		#1000;
		RSTB <= 1'b1;	    // Release reset
		#2000;
	end

	initial begin
		power1 <= 1'b0;
		power2 <= 1'b0;
		#200;
		power1 <= 1'b1;
		#200;
		power2 <= 1'b1;
	end

	always @(checkbits) begin
		#1 $display("GPIO state = %b ", checkbits);
	end

	wire VDD3V3;
	wire VDD1V8;
	wire VSS;
	
	assign VDD3V3 = power1;
	assign VDD1V8 = power2;
	assign VSS = 1'b0;

	assign mprj_io[3] = 1'b1;  // Force CSB high.

	caravel uut (
		.vddio	  (VDD3V3),
		.vssio	  (VSS),
		.vdda	  (VDD3V3),
		.vssa	  (VSS),
		.vccd	  (VDD1V8),
		.vssd	  (VSS),
		.vdda1    (VDD3V3),
		.vdda2    (VDD3V3),
		.vssa1	  (VSS),
		.vssa2	  (VSS),
		.vccd1	  (VDD1V8),
		.vccd2	  (VDD1V8),
		.vssd1	  (VSS),
		.vssd2	  (VSS),
		.clock    (clock),
		.gpio     (gpio),
		.mprj_io  (mprj_io),
		.flash_csb(flash_csb),
		.flash_clk(flash_clk),
		.flash_io0(flash_io0),
		.flash_io1(flash_io1),
		.resetb	  (RSTB)
	);

	spiflash #(
		.FILENAME("pll.hex")
	) spiflash (
		.csb(flash_csb),
		.clk(flash_clk),
		.io0(flash_io0),
		.io1(flash_io1),
		.io2(),			// not used
		.io3()			// not used
	);

endmodule
module perf_tb;
	reg clock;
	reg RSTB;
	reg power1, power2;

	wire gpio;
	wire [15:0] checkbits;
	wire [37:0] mprj_io;
	wire flash_csb;
	wire flash_clk;
	wire flash_io0;
	wire flash_io1;

	assign checkbits = mprj_io[31:16];

	// External clock is used by default.  Make this artificially fast for the
	// simulation.  Normally this would be a slow clock and the digital PLL
	// would be the fast clock.

	always #10 clock <= (clock === 1'b0);

	initial begin
		clock = 0;
	end

	reg [31:0] kcycles;

	initial begin
		$dumpfile("perf.vcd");
		$dumpvars(0, perf_tb);

		kcycles = 0;
		// Repeat cycles of 1000 clock edges as needed to complete testbench
		repeat (150) begin
			repeat (1000) @(posedge clock);
			//$display("+1000 cycles");
			kcycles <= kcycles + 1;
		end
		$display("%c[1;31m",27);
		`ifdef GL
			$display ("Monitor: Timeout, Test Performance (GL) Failed");
		`else
			$display ("Monitor: Timeout, Test Performance (RTL) Failed");
		`endif
		$display("%c[0m",27);
		$finish;
	end

	initial begin
		RSTB <= 1'b0;
		#1000;
		RSTB <= 1'b1;	    // Release reset
		#2000;
	end

	initial begin			// Power-up sequence
		power1 <= 1'b0;
		power2 <= 1'b0;
		#200;
		power1 <= 1'b1;
		#200;
		power2 <= 1'b1;
	end

	always @(checkbits) begin
		//#1 $display("GPIO state = %X ", gpio);
		if(checkbits == 16'hA000) begin
			kcycles = 0;
			$display("Performance Test started");
		end
		else if(checkbits == 16'hAB00) begin
			//$display("Monitor: number of cycles/100 iterations: %d KCycles", kcycles);
			`ifdef GL
				$display("Monitor: Test Performance (GL) passed [%0d KCycles]", kcycles);
			`else
				$display("Monitor: Test Performance (RTL) passed [%0d KCycles]", kcycles);
			`endif
			$finish;
		end
	end
	
	wire VDD3V3;
	wire VDD1V8;
	wire VSS;

	assign VDD3V3 = power1;
	assign VDD1V8 = power2;
	assign VSS = 1'b0;

	assign mprj_io[3] = 1'b1;       // Force CSB high.

	caravel uut (
		.vddio	  (VDD3V3),
		.vssio	  (VSS),
		.vdda	  (VDD3V3),
		.vssa	  (VSS),
		.vccd	  (VDD1V8),
		.vssd	  (VSS),
		.vdda1    (VDD3V3),
		.vdda2    (VDD3V3),
		.vssa1	  (VSS),
		.vssa2	  (VSS),
		.vccd1	  (VDD1V8),
		.vccd2	  (VDD1V8),
		.vssd1	  (VSS),
		.vssd2	  (VSS),
		.clock	  (clock),
		.gpio     (gpio),
		.mprj_io  (mprj_io),
		.flash_csb(flash_csb),
		.flash_clk(flash_clk),
		.flash_io0(flash_io0),
		.flash_io1(flash_io1),
		.resetb	  (RSTB)
	);

	spiflash #(
		.FILENAME("perf.hex")
	) spiflash (
		.csb(flash_csb),
		.clk(flash_clk),
		.io0(flash_io0),
		.io1(flash_io1),
		.io2(),			// not used
		.io3()			// not used
	);

endmodule
module la_test1_tb;
	reg clock;
    	reg RSTB;
	reg power1, power2;

    	wire gpio;
	wire uart_tx;
    	wire [37:0] mprj_io;
	wire [15:0] checkbits;

	assign checkbits  = mprj_io[31:16];
	assign uart_tx = mprj_io[6];

	always #12.5 clock <= (clock === 1'b0);

	initial begin
		clock = 0;
	end

	initial begin
		$dumpfile("la_test1.vcd");
		$dumpvars(0, la_test1_tb);

		// Repeat cycles of 1000 clock edges as needed to complete testbench
		repeat (200) begin
			repeat (1000) @(posedge clock);
			// $display("+1000 cycles");
		end
		$display("%c[1;31m",27);
		$display ("Monitor: Timeout, Test Mega-Project IO (RTL) Failed");
		$display("%c[0m",27);
		$finish;
	end

	initial begin
		wait(checkbits == 16'hAB40);
		$display("LA Test 1 started");
		wait(checkbits == 16'hAB41);
		wait(checkbits == 16'hAB51);
		#10000;
		$finish;
	end

	initial begin
		RSTB <= 1'b0;
		#1000;
		RSTB <= 1'b1;	    // Release reset
		#2000;
	end

	initial begin		// Power-up sequence
		power1 <= 1'b0;
		power2 <= 1'b0;
		#200;
		power1 <= 1'b1;
		#200;
		power2 <= 1'b1;
	end

    	wire flash_csb;
	wire flash_clk;
	wire flash_io0;
	wire flash_io1;

	wire VDD1V8;
    	wire VDD3V3;
	wire VSS;
    
	assign VDD3V3 = power1;
	assign VDD1V8 = power2;
	assign VSS = 1'b0;

	caravel uut (
		.vddio	  (VDD3V3),
		.vssio	  (VSS),
		.vdda	  (VDD3V3),
		.vssa	  (VSS),
		.vccd	  (VDD1V8),
		.vssd	  (VSS),
		.vdda1    (VDD3V3),
		.vdda2    (VDD3V3),
		.vssa1	  (VSS),
		.vssa2	  (VSS),
		.vccd1	  (VDD1V8),
		.vccd2	  (VDD1V8),
		.vssd1	  (VSS),
		.vssd2	  (VSS),
		.clock	  (clock),
		.gpio     (gpio),
        	.mprj_io  (mprj_io),
		.flash_csb(flash_csb),
		.flash_clk(flash_clk),
		.flash_io0(flash_io0),
		.flash_io1(flash_io1),
		.resetb	  (RSTB)
	);

	spiflash #(
		.FILENAME("la_test1.hex")
	) spiflash (
		.csb(flash_csb),
		.clk(flash_clk),
		.io0(flash_io0),
		.io1(flash_io1),
		.io2(),			// not used
		.io3()			// not used
	);

	// Testbench UART
	tbuart tbuart (
		.ser_rx(uart_tx)
	);

endmodule
module io_ports_tb;
	reg clock;
    	reg RSTB;
	reg power1, power2;
	reg power3, power4;

    	wire gpio;
    	wire [37:0] mprj_io;
	wire [7:0] mprj_io_0;

	assign mprj_io_0 = mprj_io[7:0];

	// External clock is used by default.  Make this artificially fast for the
	// simulation.  Normally this would be a slow clock and the digital PLL
	// would be the fast clock.

	always #12.5 clock <= (clock === 1'b0);

	initial begin
		clock = 0;
	end

	initial begin
		$dumpfile("io_ports.vcd");
		$dumpvars(0, io_ports_tb);

		// Repeat cycles of 1000 clock edges as needed to complete testbench
		repeat (25) begin
			repeat (1000) @(posedge clock);
			// $display("+1000 cycles");
		end
		$display("%c[1;31m",27);
		$display ("Monitor: Timeout, Test Mega-Project IO Ports (RTL) Failed");
		$display("%c[0m",27);
		$finish;
	end

	initial begin
	    // Observe Output pins [7:0]
	    wait(mprj_io_0 == 8'h01);
	    wait(mprj_io_0 == 8'h02);
	    wait(mprj_io_0 == 8'h03);
    	    wait(mprj_io_0 == 8'h04);
	    wait(mprj_io_0 == 8'h05);
            wait(mprj_io_0 == 8'h06);
	    wait(mprj_io_0 == 8'h07);
            wait(mprj_io_0 == 8'h08);
	    wait(mprj_io_0 == 8'h09);
            wait(mprj_io_0 == 8'h0A);   
	    wait(mprj_io_0 == 8'hFF);
	    wait(mprj_io_0 == 8'h00);

	    $display("Monitor: Test 1 Mega-Project IO (RTL) Passed");
	    $finish;
	end

	initial begin
		RSTB <= 1'b0;
		#2000;
		RSTB <= 1'b1;	    // Release reset
	end

	initial begin		// Power-up sequence
		power1 <= 1'b0;
		power2 <= 1'b0;
		power3 <= 1'b0;
		power4 <= 1'b0;
		#200;
		power1 <= 1'b1;
		#200;
		power2 <= 1'b1;
		#200;
		power3 <= 1'b1;
		#200;
		power4 <= 1'b1;
	end

	always @(mprj_io) begin
		#1 $display("MPRJ-IO state = %b ", mprj_io[7:0]);
	end

	wire flash_csb;
	wire flash_clk;
	wire flash_io0;
	wire flash_io1;

	wire VDD3V3 = power1;
	wire VDD1V8 = power2;
	wire USER_VDD3V3 = power3;
	wire USER_VDD1V8 = power4;
	wire VSS = 1'b0;

	caravel uut (
		.vddio	  (VDD3V3),
		.vssio	  (VSS),
		.vdda	  (VDD3V3),
		.vssa	  (VSS),
		.vccd	  (VDD1V8),
		.vssd	  (VSS),
		.vdda1    (USER_VDD3V3),
		.vdda2    (USER_VDD3V3),
		.vssa1	  (VSS),
		.vssa2	  (VSS),
		.vccd1	  (USER_VDD1V8),
		.vccd2	  (USER_VDD1V8),
		.vssd1	  (VSS),
		.vssd2	  (VSS),
		.clock	  (clock),
		.gpio     (gpio),
        	.mprj_io  (mprj_io),
		.flash_csb(flash_csb),
		.flash_clk(flash_clk),
		.flash_io0(flash_io0),
		.flash_io1(flash_io1),
		.resetb	  (RSTB)
	);

	spiflash #(
		.FILENAME("io_ports.hex")
	) spiflash (
		.csb(flash_csb),
		.clk(flash_clk),
		.io0(flash_io0),
		.io1(flash_io1),
		.io2(),			// not used
		.io3()			// not used
	);

endmodule
module la_test2_tb;
	reg clock;
    	reg RSTB;
	reg power1, power2;

    	wire gpio;
    	wire [37:0] mprj_io;
	wire [15:0] checkbits;

	assign checkbits = mprj_io[31:16];

	always #12.5 clock <= (clock === 1'b0);

	initial begin
		clock = 0;
	end

	initial begin
		$dumpfile("la_test2.vcd");
		$dumpvars(0, la_test2_tb);

		// Repeat cycles of 1000 clock edges as needed to complete testbench
		repeat (30) begin
			repeat (1000) @(posedge clock);
			// $display("+1000 cycles");
		end
		$display("%c[1;31m",27);
		$display ("Monitor: Timeout, Test Mega-Project IO (RTL) Failed");
		$display("%c[0m",27);
		$finish;
	end

	initial begin
		wait(checkbits == 16'h AB60);
		$display("Monitor: Test 2 MPRJ-Logic Analyzer Started");
		wait(checkbits == 16'h AB61);
		$display("Monitor: Test 2 MPRJ-Logic Analyzer Passed");
		$finish;
	end

	initial begin
		RSTB <= 1'b0;
		#1000;
		RSTB <= 1'b1;	    // Release reset
		#2000;
	end

	initial begin		// Power-up sequence
		power1 <= 1'b0;
		power2 <= 1'b0;
		#200;
		power1 <= 1'b1;
		#200;
		power2 <= 1'b1;
	end

    	wire flash_csb;
	wire flash_clk;
	wire flash_io0;
	wire flash_io1;

	wire VDD1V8;
    	wire VDD3V3;
	wire VSS;
    
	assign VDD3V3 = power1;
	assign VDD1V8 = power2;
	assign VSS = 1'b0;

	caravel uut (
		.vddio	  (VDD3V3),
		.vssio	  (VSS),
		.vdda	  (VDD3V3),
		.vssa	  (VSS),
		.vccd	  (VDD1V8),
		.vssd	  (VSS),
		.vdda1    (VDD3V3),
		.vdda2    (VDD3V3),
		.vssa1	  (VSS),
		.vssa2	  (VSS),
		.vccd1	  (VDD1V8),
		.vccd2	  (VDD1V8),
		.vssd1	  (VSS),
		.vssd2	  (VSS),
		.clock	  (clock),
		.gpio     (gpio),
        	.mprj_io  (mprj_io),
		.flash_csb(flash_csb),
		.flash_clk(flash_clk),
		.flash_io0(flash_io0),
		.flash_io1(flash_io1),
		.resetb	  (RSTB)
	);

	spiflash #(
		.FILENAME("la_test2.hex")
	) spiflash (
		.csb(flash_csb),
		.clk(flash_clk),
		.io0(flash_io0),
		.io1(flash_io1),
		.io2(),
		.io3()
	);

endmodule
module config_tile #(
    parameter COMB_N = 4236,
    parameter MEM_N = 132
) (
    input clk,
    input rst,
    input shift_enable,

    output [COMB_N-1:0] comb_config,
    output [MEM_N-1:0] mem_config,
    output comb_set,  // Set signal from set_soft or set_hard depending on which one you're using.
    output mem_set,   // Gated by second configuration bit, controls whether you set configuration values.

    input set_soft,   // From fabric.
    input set_hard,   // From tile/column.
    input shift_in_hard,
    input shift_in_soft,

    output shift_out
);
    wire set_internal;
    wire shift_in_internal;

    wire mem_ctrl;
    wire input_mux;

    assign shift_in_internal = input_mux ? shift_in_soft : shift_in_hard;
    assign set_internal = input_mux ? set_soft : set_hard;

    assign mem_set = (~mem_ctrl) & set_internal;
    assign comb_set = set_internal;

    wire [1:0] internal_config_inter;

    config_latch #(.LENGTH(2)) internal_config (
        .clk(clk),
        .rst(rst),
        .set(set_internal),

        .shifter_data(internal_config_inter),
        .config_bits({input_mux, mem_ctrl})
    );

    wire comb_mem_bridge;

    shift_chain #(.LENGTH(COMB_N + 2)) comb_shifter (
        .clk(clk),
        .rst(rst),
        .shift_enable(shift_enable),
        .shift_in(shift_in_internal),
        .shift_out(comb_mem_bridge),
        .config_data({internal_config_inter, comb_config})
    );

    shift_chain #(.LENGTH(MEM_N)) mem_shifter (
        .clk(clk),
        .rst(rst),
        .shift_enable(shift_enable),
        .shift_in(comb_mem_bridge),
        .shift_out(shift_out),
        .config_data(mem_config)
    );
endmodule
module baked_clb_switch_box #(
  parameter WS = 4,
  parameter WD = 8
)(
  // Common
  input wire clk,
  input wire rst,

  // Confiuration Signals:

  input wire cen,

  // Config set input (from tile module)
  input wire set_in,

  // Config shift input (from tile module)
  input wire shift_in,
  // Config shift output (to tile module)
  output wire shift_out,

  // Single Wires
  inout [WS-1:0] north_single, east_single, south_single, west_single,
  // Double Wires
  inout [WD-1:0] north_double, east_double, south_double, west_double
);

localparam SWITCHBOX_CONF_WIDTH = (WS + WD/2)*6;

wire [SWITCHBOX_CONF_WIDTH-1:0] switch_conf_bus;

reg [SWITCHBOX_CONF_WIDTH-1:0] switch_conf_regs;

always @(clk) begin
  if (set_in) begin
    switch_conf_regs <= switch_conf_bus;
  end
end

clb_switch_box #(
  .WS(WS),
  .WD(WD)
) switcharoni (
  .north_single(north_single),
  .east_single(east_single),
  .west_single(west_single),
  .south_single(south_single),

  .north_double(north_double),
  .east_double(east_double),
  .west_double(west_double),
  .south_double(south_double),

  .c(switch_conf_regs)
);

// OH GREAT ABC9 WORK THY OPTIMIZATIONS VERILY
config_tile #(
  .COMB_N(SWITCHBOX_CONF_WIDTH),
  .MEM_N(0)
) configuroni (
  .clk(clk),
  .rst(rst),

  .shift_enable(cen & (~set_in)),
  .shift_in_hard(shift_in),
  .shift_in_soft(shift_in),
  .shift_out(shift_out),

  .set_hard(set_in),
  .set_soft(set_in),

  .comb_config(switch_conf_bus),
  .comb_set(),

  .mem_config(),
  .mem_set()
);

endmodule
module baked_connection_block_east #(
  parameter WS = 4,
  parameter WD = 8,
  parameter WG = 0,
  parameter CLBIN = 10,
  parameter CLBIN0 = 10,
  parameter CLBIN1 = 10,
  parameter CLBOUT = 5,
  parameter CLBOUT0 = 5,
  parameter CLBOUT1 = 5,
  parameter CARRY = 1,
  parameter CLBOS = 4,
  parameter CLBOS_BIAS = 0,
  parameter CLBOD = 4,
  parameter CLBOD_BIAS = 0,
  parameter CLBX = 1
)(
  // Common
  input wire clk,
  input wire rst,

  // Confiuration Signals:

  input wire cen,

  // Config set input (from tile module)
  input wire set_in,

  // Config shift input (from tile module)
  input wire shift_in,
  // Config shift output (to tile module)
  output wire shift_out,

  // Single Wires
  inout [WS-1:0] single0, single1,
  // Double Wires
  inout [WD-1:0] double0, double1,
  // Global Wires
  //inout [WG-1:0] global, /* manually disabled since WG = 0 for hardening */

  input [CLBOUT-1:0] clb0_output,
  input [CLBOUT-1:0] clb1_output,
  input [CARRY-1:0]  clb0_cout,
  input [CARRY-1:0]  clb1_cout,
  output [CLBIN-1:0] clb0_input,
  output [CLBIN-1:0] clb1_input,
  output [CARRY-1:0] clb0_cin,
  output [CARRY-1:0] clb1_cin
);

baked_connection_block #(
  .WS(WS),
  .WD(WD),
  .WG(WG),
  .CLBIN(CLBIN),
  .CLBIN0(CLBIN0),
  .CLBIN1(CLBIN1),
  .CLBOUT(CLBOUT),
  .CLBOUT0(CLBOUT0),
  .CLBOUT1(CLBOUT1),
  .CARRY(CARRY),
  .CLBOS(CLBOS),
  .CLBOS_BIAS(CLBOS_BIAS),
  .CLBOD(CLBOD),
  .CLBOD_BIAS(CLBOD_BIAS),
  .CLBX(CLBX)
) inst (
  .clk(clk),
  .rst(rst),
  .cen(cen),
  .set_in(set_in),
  .shift_in(shift_in),
  .shift_out(shift_out),
  .single0(single0),
  .single1(single1),
  .double0(double0),
  .double1(double1),
  //.global(global),  /* manually disabled since WG = 0 for hardening */
  .clb0_output(clb0_output),
  .clb1_output(clb1_output),
  .clb0_cout(clb0_cout),
  .clb1_cout(clb1_cout),
  .clb0_input(clb0_input),
  .clb1_input(clb1_input),
  .clb0_cin(clb0_cin),
  .clb1_cin(clb1_cin)
);

endmodule
module baked_connection_block_north #(
  parameter WS = 4,
  parameter WD = 8,
  parameter WG = 0,
  parameter CLBIN = 10,
  parameter CLBIN0 = 10,
  parameter CLBIN1 = 10,
  parameter CLBOUT = 5,
  parameter CLBOUT0 = 5,
  parameter CLBOUT1 = 5,
  parameter CARRY = 1,
  parameter CLBOS = 4,
  parameter CLBOS_BIAS = 0,
  parameter CLBOD = 4,
  parameter CLBOD_BIAS = 0,
  parameter CLBX = 1
)(
  // Common
  input wire clk,
  input wire rst,

  // Confiuration Signals:

  input wire cen,

  // Config set input (from tile module)
  input wire set_in,

  // Config shift input (from tile module)
  input wire shift_in,
  // Config shift output (to tile module)
  output wire shift_out,

  // Single Wires
  inout [WS-1:0] single0, single1,
  // Double Wires
  inout [WD-1:0] double0, double1,
  // Global Wires
  //inout [WG-1:0] global,  /* manually disabled since WG = 0 for hardening */

  input [CLBOUT-1:0] clb0_output,
  input [CLBOUT-1:0] clb1_output,
  input [CARRY-1:0]  clb0_cout,
  input [CARRY-1:0]  clb1_cout,
  output [CLBIN-1:0] clb0_input,
  output [CLBIN-1:0] clb1_input,
  output [CARRY-1:0] clb0_cin,
  output [CARRY-1:0] clb1_cin
);

baked_connection_block #(
  .WS(WS),
  .WD(WD),
  .WG(WG),
  .CLBIN(CLBIN),
  .CLBIN0(CLBIN0),
  .CLBIN1(CLBIN1),
  .CLBOUT(CLBOUT),
  .CLBOUT0(CLBOUT0),
  .CLBOUT1(CLBOUT1),
  .CARRY(CARRY),
  .CLBOS(CLBOS),
  .CLBOS_BIAS(CLBOS_BIAS),
  .CLBOD(CLBOD),
  .CLBOD_BIAS(CLBOD_BIAS),
  .CLBX(CLBX)
) inst (
  .clk(clk),
  .rst(rst),
  .cen(cen),
  .set_in(set_in),
  .shift_in(shift_in),
  .shift_out(shift_out),
  .single0(single0),
  .single1(single1),
  .double0(double0),
  .double1(double1),
  //.global(global),  /* manually disabled since WG = 0 for hardening */
  .clb0_output(clb0_output),
  .clb1_output(clb1_output),
  .clb0_cout(clb0_cout),
  .clb1_cout(clb1_cout),
  .clb0_input(clb0_input),
  .clb1_input(clb1_input),
  .clb0_cin(clb0_cin),
  .clb1_cin(clb1_cin)
);

endmodule
module config_latch #(
    parameter LENGTH = 8
) (
    input clk,
    input rst,
    input set,

    input [LENGTH-1:0] shifter_data,
    output [LENGTH-1:0] config_bits
);
    reg [LENGTH-1:0] stored_bits;

    assign config_bits = stored_bits;

    always @(posedge clk) begin
        if (rst == 1) begin
            stored_bits <= 0;
        end
        else if (set == 1) begin
            stored_bits <= shifter_data;
        end
        else begin
            stored_bits <= stored_bits;
        end
    end
endmodule
module lut #(
    parameter INPUTS=4, 
    parameter MEM_SIZE=2**INPUTS
) (
    // IO
    input [INPUTS-1:0] addr, 
    output out,

    // Block Style Configuration
    input clk,
    input comb_set,
    input [MEM_SIZE-1:0] config_in
);

block_config_latches #(.ADDR_BITS(INPUTS), .PREDEC(1)) latches0 (
    .addr(addr), 
    .out(out),
    .clk(clk),
    .comb_set(comb_set),
    .config_in(config_in)
);

endmodule
module switch_box_element_two
  (
   inout [1:0] north, east, south, west,
   input [11:0] c
   );

   transmission_gate n0e0(east[0], north[0], c[0]);
   transmission_gate e1s0(south[0], east[1], c[1]);
   transmission_gate s1w1(west[1], south[1], c[2]);
   transmission_gate w0n1(north[1], west[0], c[3]);
   
   transmission_gate n0s0(south[0], north[0], c[4]);
   transmission_gate e1w1(west[1], east[1], c[5]);
   transmission_gate s1n1(north[1], south[1], c[6]);
   transmission_gate w0e0(east[0], west[0], c[7]);
   
   transmission_gate n1e1(east[1], north[1], c[8]);
   transmission_gate e0s1(south[1], east[0], c[9]);
   transmission_gate s0w0(west[0], south[0], c[10]);
   transmission_gate w1n0(north[0], west[1], c[11]);
   
endmodule
module universal_switch_box 
  #(
    parameter W = 8
    ) 
   (
    inout [W-1:0]   north, east, south, west,
    input [W*6-1:0] c
    );
   
   genvar 	    i;
   generate
      for(i = 0; i < W / 2; i = i + 1) begin : switch_box_element_two
	 switch_box_element_two elem
	      (
	       .north(north[i*2+1:i*2]),
	       .east(east[i*2+1:i*2]),
	       .south(south[i*2+1:i*2]),
	       .west(west[i*2+1:i*2]),
	       .c(c[12*(i+1)-1:12*i])
	       );
      end
      if(W%2 == 1) begin : switch_box_element_one
	 switch_box_element_one elem 
	   (
	    .north(north[W-1]),
	    .east(east[W-1]),
	    .south(south[W-1]),
	    .west(west[W-1]),
	    .c(c[W*6-1:(W-1)*6])
	    );
      end
   endgenerate
   
endmodule
module shift_bit (
    input clk,
    input rst,

    input shift_enable,

    input shift_in,
    output shift_out
);
    reg config_bit;
    assign shift_out = config_bit;

    always @(posedge clk) begin
        if (rst == 1'b0) begin
            if (shift_enable == 1'b1) begin
                config_bit <= shift_in;
            end else begin
                config_bit <= config_bit;
            end
        end
        else config_bit <= 1'b0;
    end
endmodule
module shift_chain #(
    parameter LENGTH = 8
) (
    input clk,
    input rst,

    input shift_enable,
    
    input shift_in,
    output shift_out,

    output [LENGTH-1:0] config_data
);
    wire [LENGTH-1:0] intermediate;

    assign config_data = intermediate;

    genvar i;
    generate
        if (LENGTH == 0) assign shift_out = shift_in;
        if (LENGTH >= 1) begin
            shift_bit head_bit (
                .clk(clk),
                .rst(rst),
                .shift_enable(shift_enable),
                .shift_in(shift_in),
                .shift_out(intermediate[LENGTH - 1])
            );
            assign shift_out = intermediate[0];
        end
        if (LENGTH > 1) begin
            for (i = 1; i < LENGTH; i = i + 1) begin
                shift_bit shift_bit_i (
                    .clk(clk),
                    .rst(rst),
                    .shift_enable(shift_enable),
                    .shift_in(intermediate[i]),
                    .shift_out(intermediate[i - 1])
                );
            end
        end
    endgenerate
endmodule
module lut_sXX_softcode #(
    parameter INPUTS=4, 
    parameter MEM_SIZE=2**INPUTS
) (
    input [INPUTS*2-1:0] addr,
    output [1:0] out,

    // Block Style Configuration
    // NOTE: MOST SIGNIFICANT BIT OF CFG DETERMINES FRACTURING
    // config_in = {use_fracture, first_lut, second_lut}
    input clk,
    input comb_set,
    input [2*MEM_SIZE:0] config_in
);

wire second_in, out_upper, out_lower;
reg split = 1'b0;
assign second_in = split ? addr[INPUTS-1] : out_upper;
assign out = {out_upper, out_lower}; // had to split out because of verilator's optimization strategy giving unoptflat errors

always @(posedge clk) begin
    if (comb_set) begin
        split <= config_in[2*MEM_SIZE];
    end
end

lut #(.INPUTS(INPUTS)) first_lut (
    .addr(addr[INPUTS*2-1:INPUTS]),
    .out(out_upper),
    .clk(clk),
    .comb_set(comb_set),
    .config_in(config_in[2*MEM_SIZE-1:MEM_SIZE])
);

lut #(.INPUTS(INPUTS)) second_lut (
    .addr({second_in, addr[INPUTS-2:0]}),
    .out(out_lower),
    .clk(clk),
    .comb_set(comb_set),
    .config_in(config_in[MEM_SIZE-1:0])
);

endmodule
module wishbone_configuratorinator_00 (
    // Global signals
    input wb_clk_i,
    input wb_rst_i,

    // Wishbone signals
    input wbs_stb_i,
    input wbs_cyc_i,
    input wbs_we_i,
    // Write mask
    input [3:0] wbs_sel_i,
    input [31:0] wbs_data_i,
    input [31:0] wbs_addr_i,
    output wbs_ack_o, // Its bad form but its also 1 in the morning
    output [31:0] wbs_data_o,

    // Config output
    output cen,
    output [3:0] set_out,
    output [3:0] shift_out
);
    wishbone_configuratorinator #(.BASE_ADDR(32'h3000_0000)) configy (
        .wb_clk_i(wb_clk_i),
        .wb_rst_i(wb_rst_i),
        .wbs_stb_i(wbs_stb_i),
        .wbs_cyc_i(wbs_cyc_i),
        .wbs_we_i(wbs_we_i),
        .wbs_sel_i(wbs_sel_i),
        .wbs_data_i(wbs_data_i),
        .wbs_addr_i(wbs_addr_i),
        .wbs_ack_o(wbs_ack_o),
        .wbs_data_o(wbs_data_o),
        .cen(cen),
        .set_out(set_out),
        .shift_out(shift_out)
    );
endmodule
module wishbone_configuratorinator_10 (
    // Global signals
    input wb_clk_i,
    input wb_rst_i,

    // Wishbone signals
    input wbs_stb_i,
    input wbs_cyc_i,
    input wbs_we_i,
    // Write mask
    input [3:0] wbs_sel_i,
    input [31:0] wbs_data_i,
    input [31:0] wbs_addr_i,
    output wbs_ack_o, // Its bad form but its also 1 in the morning
    output [31:0] wbs_data_o,

    // Config output
    output cen,
    output [3:0] set_out,
    output [3:0] shift_out
);
    wishbone_configuratorinator #(.BASE_ADDR(32'h3000_0010)) configy (
        .wb_clk_i(wb_clk_i),
        .wb_rst_i(wb_rst_i),
        .wbs_stb_i(wbs_stb_i),
        .wbs_cyc_i(wbs_cyc_i),
        .wbs_we_i(wbs_we_i),
        .wbs_sel_i(wbs_sel_i),
        .wbs_data_i(wbs_data_i),
        .wbs_addr_i(wbs_addr_i),
        .wbs_ack_o(wbs_ack_o),
        .wbs_data_o(wbs_data_o),
        .cen(cen),
        .set_out(set_out),
        .shift_out(shift_out)
    );
endmodule
module carry_chain_single (
        input P, 
        input G, 
        input Ci,
        output Co, 
        output S
    );

    assign Co = P ? Ci : G;
    assign S  = P ^ Ci;
endmodule
module carry_chain #(
        parameter INPUTS=4
    ) (
        input  [INPUTS-1:0] P,
        input  [INPUTS-1:0] G,
        output [INPUTS-1:0] S,
        input  Ci,
        output Co
    );

    wire [INPUTS:0] C;
    assign C[0] = Ci;
    assign Co = C[INPUTS];

    generate 
        genvar i;
        for (i = 0; i < INPUTS; i=i+1) begin
            carry_chain_single cc1 (
                .P(P[i]),
                .G(G[i]),
                .S(S[i]),
                .Ci(C[i]),
                .Co(C[i+1])
            );
        end
    endgenerate
endmodule
module transmission_gate_oneway(output a, input b, input c);
   assign a = c? b: 1'bz;
endmodule
module mux_f_slice #(
    parameter NUM_LUTS=2, 
    parameter MUX_LEVEL=1
) (
    input  [NUM_LUTS-1:0] luts_out,
    input  [MUX_LEVEL-1:0] addr,
    output [NUM_LUTS-1:0] out,

    // Block Style Configuration
    input clk,
    input comb_set,
    input [MUX_LEVEL-1:0] config_in
);

reg [MUX_LEVEL-1:0] config_state;

generate
    if (MUX_LEVEL==1) begin
        assign out[0] = config_state[0] ? (addr[0] ? luts_out[1] : luts_out[0]) : luts_out[0];
        assign out[1] = luts_out[1];
    end else begin
        wire [NUM_LUTS-1:0] intermediate_out;
        localparam HALF_LUTS = NUM_LUTS/2;
        assign out[0] = config_state[MUX_LEVEL-1] ? (addr[MUX_LEVEL-1] ? intermediate_out[HALF_LUTS] : intermediate_out[0]) : intermediate_out[0];
        assign out[NUM_LUTS-1:1] = intermediate_out[NUM_LUTS-1:1];
        mux_f_slice #(
            .NUM_LUTS(HALF_LUTS), .MUX_LEVEL(MUX_LEVEL-1)
        ) mux_lower (
            .luts_out(luts_out[HALF_LUTS-1:0]),
            .addr(addr[MUX_LEVEL-2:0]),
            .out(intermediate_out[HALF_LUTS-1:0]),
            .clk(clk),
            .comb_set(comb_set),
            .config_in(config_in[MUX_LEVEL-2:0])
        );
        mux_f_slice #(
            .NUM_LUTS(HALF_LUTS), .MUX_LEVEL(MUX_LEVEL-1)
        ) mux_higher (
            .luts_out(luts_out[NUM_LUTS-1:HALF_LUTS]),
            .addr(addr[MUX_LEVEL-2:0]),
            .out(intermediate_out[NUM_LUTS-1:HALF_LUTS]),
            .clk(clk),
            .comb_set(comb_set),
            .config_in(config_in[MUX_LEVEL-2:0])
        );
    end
endgenerate

always @(posedge clk) begin
    if (comb_set) begin
        config_state <= config_in;
    end
end

endmodule
module transmission_gate_cell(inout A, inout B, input C, input Cnot);
  // Use the verilog primitive where available, in which case c_not is not
  // used.
  tranif1(A, B, C);
endmodule
module slicel #(
    parameter S_XX_BASE=4, 
    parameter NUM_LUTS = 4,
    // 2x configs bits for the dual LUTs in SXX + 1 config bit for internal LUT select
    parameter CFG_SIZE=2*(2**S_XX_BASE)+1,
    // assume NUM_LUTS is a power of 2
    parameter MUX_LVLS = $clog2(NUM_LUTS)
) (
    input clk,
    // Set config bits for comb logic
    input comb_set,
    // Set register initial states
    input mem_set,

    // Input to LUTS (from fabric)
    input [2*S_XX_BASE*NUM_LUTS-1:0] luts_in,
    // Input to MUXS (from fabric)
    input [MUX_LVLS-1:0] higher_order_addr,

    // Config bits
    input [CFG_SIZE*NUM_LUTS-1:0] luts_config_in,
    input [MUX_LVLS-1:0] inter_lut_mux_config,
    // Output register initial state
    input [2*NUM_LUTS-1:0] regs_config_in,
    // Enable Carry
    input config_use_cc,

    // Output Register Write Enable (from fabric)
    input reg_ce,
    // Carry in (from fabric)
    input Ci,
    // Carry out (to fabric)
    output Co,

    // Unregistered output (to fabric)
    output [2*NUM_LUTS-1:0] out,
    // Unregistered output (to fabric)
    output reg [2*NUM_LUTS-1:0] sync_out
);

wire [2*NUM_LUTS-1:0] luts_out;
wire [NUM_LUTS-1:0] muxes_out;
wire [NUM_LUTS-1:0] muxes_in;
wire [NUM_LUTS-1:0] cc_p;
wire [NUM_LUTS-1:0] cc_g;
wire [NUM_LUTS-1:0] cc_s;

reg use_cc;
always @(posedge clk) begin
    if (comb_set) begin
        use_cc <= config_use_cc;
    end
end
             
generate
    genvar i;
    genvar j;
    for (i = 0; i < NUM_LUTS; i=i+1) begin
        lut_sXX_softcode #(.INPUTS(S_XX_BASE)) lut (
            .addr(luts_in[2*S_XX_BASE*(i+1)-1:2*S_XX_BASE*i]),
            .out(luts_out[2*i+1:2*i]),
            .clk(clk),
            .comb_set(comb_set),
            .config_in(luts_config_in[CFG_SIZE*(i+1)-1:CFG_SIZE*i])
        );

        assign cc_p[i] = luts_out[2*i];
        assign cc_g[i] = luts_out[2*i+1];
        assign muxes_in[i] = luts_out[2*i];
        assign out[2*i+1:2*i] = use_cc ? 
                        {luts_out[2*i+1], cc_s[i]} :
                        {luts_out[2*i+1], muxes_out[i]};

        // Registers capture main CLB outputs
        always @(posedge clk) begin
            if (mem_set) begin
                // set the initial states of the FFs from the configuration bits
                sync_out[2*i+1:2*i] <= regs_config_in[2*i+1:2*i];
            end
            else if (reg_ce) begin
                sync_out[2*i+1:2*i] <= out[2*i+1:2*i];
            end
        end
    end
endgenerate

// carry chain will utilize outputs of smallest fracture size
// 2**(fraclvl-1) will be the number of propegate/generates
carry_chain #(.INPUTS(NUM_LUTS)) cc (
    .P(cc_p),
    .G(cc_g),
    .S(cc_s),
    .Ci(Ci),
    .Co(Co)
);

// MUX the primary S44 outputs, analog to MUX7 and MUX8
mux_f_slice #(
    .NUM_LUTS(NUM_LUTS), .MUX_LEVEL(MUX_LVLS)
) muxes (
    .luts_out(muxes_in),
    .addr(higher_order_addr),
    .out(muxes_out),
    .clk(clk),
    .comb_set(comb_set),
    .config_in(inter_lut_mux_config)
);

endmodule
module baked_slicel #(
  parameter S_XX_BASE = 4,
  parameter NUM_LUTS = 4,
  parameter MUX_LVLS = $clog2(NUM_LUTS)
)(
  // Common
  input wire clk,
  input wire rst,


  // Configuration signals:

  // Shift enable signal for the config block
  input wire cen,

  // Hardwired config set input (from northward tile)
  input wire set_in,
  // Soft config set input (from fabric)
  input wire set_in_soft,

  // Hardwired config shift input (from northward tile)
  input wire shift_in,
  // Soft shifter input (from fabric)
  input wire shift_in_soft,

  output wire set_out,
  output wire shift_out,


  // LUT Signals:

  // Input to all the luts (from fabric)
  input wire [2*S_XX_BASE*NUM_LUTS-1:0] luts_input,
  // MUX address input for big luts (from fabric)
  input wire [MUX_LVLS-1:0] higher_order_address,
  // Output register WE (from fabric)
  input wire reg_we,

  // Output from LUTs (to fabric)
  output wire [2*NUM_LUTS-1:0] comb_output,
  // Output from LUTs (registered to fabric)
  output wire [2*NUM_LUTS-1:0] sync_output,

  // Carry in input (from fabric)
  input wire carry_in,
  // Carry out output (to fabric)
  output wire carry_out
);

//localparam MUX_LVLS = $clog2(NUM_LUTS);
localparam LUT_CONF_WIDTH = 2*(2**S_XX_BASE) + 1;

// N luts + Muxing + carry enable
localparam TOTAL_COMB_CONF_WIDTH = NUM_LUTS*LUT_CONF_WIDTH + MUX_LVLS + 1;
// Register reset states
localparam TOTAL_MEM_CONF_WIDTH = 2*NUM_LUTS;

wire comb_set;
wire mem_set;

wire [TOTAL_COMB_CONF_WIDTH-1:0] slicel_comb_conf_bus;
wire [TOTAL_MEM_CONF_WIDTH-1:0] slicel_mem_conf_bus; 

assign set_out = comb_set;

slicel #(
  .S_XX_BASE(S_XX_BASE),
  .NUM_LUTS(NUM_LUTS)
) sliceluroni (
  .clk(clk),
  .comb_set(comb_set),
  .mem_set(mem_set),

  .luts_in(luts_input),
  .higher_order_addr(higher_order_address),
  .reg_ce(reg_we),

  .out(comb_output),
  .sync_out(sync_output),

  .Ci(carry_in),
  .Co(carry_out),

  .luts_config_in(slicel_comb_conf_bus[LUT_CONF_WIDTH*NUM_LUTS-1:0]),
  .inter_lut_mux_config(slicel_comb_conf_bus[MUX_LVLS+LUT_CONF_WIDTH*NUM_LUTS-1:LUT_CONF_WIDTH*NUM_LUTS]),
  .config_use_cc(slicel_comb_conf_bus[TOTAL_COMB_CONF_WIDTH-1]),

  .regs_config_in(slicel_mem_conf_bus)
);

config_tile #(
  .COMB_N(TOTAL_COMB_CONF_WIDTH),
  .MEM_N(TOTAL_MEM_CONF_WIDTH)
) configuroni (
  .clk(clk),
  .rst(rst),

  .shift_enable(cen & (~set_in)),
  .shift_in_hard(shift_in),
  .shift_in_soft(shift_in_soft),
  .shift_out(shift_out),

  .set_hard(set_in),
  .set_soft(set_in_soft),

  .comb_config(slicel_comb_conf_bus),
  .comb_set(comb_set),

  .mem_config(slicel_mem_conf_bus),
  .mem_set(mem_set)
);

endmodule
module block_config_latches #(
    parameter ADDR_BITS=4, 
    parameter MEM_SIZE=2**ADDR_BITS,
    parameter PREDEC=0 // useful only for 4-LUT right now
) (
    // IO
    input [ADDR_BITS-1:0] addr, 
    output out,

    // Block Style Configuration
    input clk,
    input comb_set,
    input [MEM_SIZE-1:0] config_in
);

reg [MEM_SIZE-1:0] mem = 0;

generate
    if (PREDEC==1) begin
        wire [3:0] intermediate_out; // 4 muxes -> 1 predecoded mux
        wire [3:0] intermediate_use;
        genvar i;
        for (i = 0; i < MEM_SIZE/4; i=i+1) begin
            // Why won't this map as a 4-mux?
            //assign intermediate_out[i] = mem[4*i+addr[1:0]];

`ifdef USE_POWER_PINS
            sky130_fd_sc_hd__mux4_1 _TECHMAP_MUX4 (
                .X(intermediate_out[i]),
                .A0(mem[4*i]),
                .A1(mem[4*i + 1]),
                .A2(mem[4*i + 2]),
                .A3(mem[4*i + 3]),
                .S0(addr[0]),
                .S1(addr[1]),
                .VPWR(1'b1),
                .VGND(1'b0)
            );
`else
            sky130_fd_sc_hd__mux4_1 _TECHMAP_MUX4 (
                .X(intermediate_out[i]),
                .A0(mem[4*i]),
                .A1(mem[4*i + 1]),
                .A2(mem[4*i + 2]),
                .A3(mem[4*i + 3]),
                .S0(addr[0]),
                .S1(addr[1])
            );
`endif
            transmission_gate tg(intermediate_out[i], out, intermediate_use[i]);
            if (i==0)
                assign intermediate_use[i] = ~addr[ADDR_BITS-1] & ~addr[ADDR_BITS-2];
            else if (i==1) 
                assign intermediate_use[i] = ~addr[ADDR_BITS-1] & addr[ADDR_BITS-2];
            else if (i==2) 
                assign intermediate_use[i] = addr[ADDR_BITS-1] & ~addr[ADDR_BITS-2];
            else 
                assign intermediate_use[i] = addr[ADDR_BITS-1] & addr[ADDR_BITS-2];
        end
    end
    else begin
        assign out = mem[addr];
    end
endgenerate

// Block Style Configuration Logic
always @(clk) begin
    if (comb_set) begin
        mem = config_in;
    end
end

endmodule
module transmission_gate(inout a, inout b, input c);
  transmission_gate_cell impl(.A(a), .B(b), .C(c), .Cnot(~c));
endmodule
module clb_switch_box 
  #(
    parameter WS = 8,
    parameter WD = 8 // WD must be multiple of 2
    ) 
   (
    inout [WS-1:0] 	    north_single, east_single, south_single, west_single,
    inout [WD-1:0] 	    north_double, east_double, south_double, west_double,
    input [(WS+WD/2)*6-1:0] c
    );
   
   universal_switch_box 
     #(
       .W(WS)
       )
   susb
     (
      .north(north_single),
      .east(east_single),
      .south(south_single),
      .west(west_single),
      .c(c[WS*6-1:0])
      );
   
   universal_switch_box 
     #(
       .W(WD/2)
       )
   dusb
     (
      .north(north_double[WD/2-1:0]),
      .east(east_double[WD-1:WD/2]),
      .south(south_double[WD-1:WD/2]),
      .west(west_double[WD/2-1:0]),
      .c(c[(WS+WD/2)*6-1:WS*6])
      );
   
   genvar 		    i;
   generate
      for(i = 0; i < WD / 2; i = i + 1) begin : double_direct_connection
         // tran(north_double[i+WD/2], south_double[i]);
         // tran(east_double[i], west_double[i+WD/2]);
         assign north_double[i+WD/2] = south_double[i];
         assign east_double[i] = west_double[i+WD/2];
      end
   endgenerate
   
endmodule
module Traffic_Test;

  // Inputs
  reg NS_VEHICLE_DETECT;
  reg EW_VEHICLE_DETECT;

  // Outputs
  wire NS_RED;
  wire NS_YELLOW;
  wire NS_GREEN;
  wire EW_RED;
  wire EW_YELLOW;
  wire EW_GREEN;

  // Clock
  reg clk;

  // Counters
  wire[4:0] count1;
  wire[3:0] count2;
  wire[1:0] count3;

  // Counter Modules
  nsCounter clock1(clk, count1); 	 // Count a total of 32 seconds
  ewCounter clock2(clk, count2); 	 // Counts a total of 16 seconds
  yellowCounter clock3(clk, count3); // Counts a total of 4 seconds

  // Main Traffic Module
  Traffic CORE (count1, count2, count3, NS_VEHICLE_DETECT, EW_VEHICLE_DETECT, NS_RED, NS_YELLOW, NS_GREEN, EW_RED, EW_YELLOW, EW_GREEN);

  initial begin

    clk = 0;
    NS_VEHICLE_DETECT = 0;
    EW_VEHICLE_DETECT = 0;

    $display("  NS | EW ");
    $display("R Y G R Y G ");
    $monitor("%h %h %h %h %h %h", NS_RED, NS_YELLOW, NS_GREEN, EW_RED, EW_YELLOW, EW_GREEN);

    #1000 $finish;
  end

  always begin
    #1 clk = ~clk;
  end
endmodule
module Traffic_Test;

  // Inputs
  reg NS_VEHICLE_DETECT;
  reg EW_VEHICLE_DETECT;

  // Outputs
  wire NS_RED;
  wire NS_YELLOW;
  wire NS_GREEN;
  wire EW_RED;
  wire EW_YELLOW;
  wire EW_GREEN;

  // Clock
  reg clk;

  // Counters
  wire[4:0] count1;
  wire[3:0] count2;
  wire[1:0] count3;

  // Counter Modules
  nsCounter clock1(clk, count1); 	 // Count a total of 32 seconds
  ewCounter clock2(clk, count2); 	 // Counts a total of 16 seconds
  yellowCounter clock3(clk, count3); // Counts a total of 4 seconds

  // Main Traffic Module
  Traffic CORE (count1, count2, count3, NS_VEHICLE_DETECT, EW_VEHICLE_DETECT, NS_RED, NS_YELLOW, NS_GREEN, EW_RED, EW_YELLOW, EW_GREEN);

  initial begin

    clk = 0;
    NS_VEHICLE_DETECT = 0;
    EW_VEHICLE_DETECT = 1;

    $display("                         NS | EW ");
    $display("              (Time) | R Y G R Y G ");
    $monitor("%d | %h %h %h %h %h %h", $time, NS_RED, NS_YELLOW, NS_GREEN, EW_RED, EW_YELLOW, EW_GREEN);

    #1000 $finish;
  end

  always begin
    #1 clk = ~clk;
  end

  always @ (clk) begin
    if ($time % 2 == 0) begin
      NS_VEHICLE_DETECT = ~NS_VEHICLE_DETECT;
    end

    if ($time % 15 == 0) begin
      EW_VEHICLE_DETECT = ~EW_VEHICLE_DETECT;
    end
  end
endmodule
module Traffic_Test;

  // Inputs
  reg NS_VEHICLE_DETECT;
  reg EW_VEHICLE_DETECT;

  // Outputs
  wire NS_RED;
  wire NS_YELLOW;
  wire NS_GREEN;
  wire EW_RED;
  wire EW_YELLOW;
  wire EW_GREEN;

  // Clock
  reg clk;

  // Counters
  wire[4:0] count1;
  wire[3:0] count2;
  wire[1:0] count3;

  // Counter Modules
  nsCounter clock1(clk, count1); 	 // Count a total of 32 seconds
  ewCounter clock2(clk, count2); 	 // Counts a total of 16 seconds
  yellowCounter clock3(clk, count3); // Counts a total of 4 seconds

  // Main Traffic Module
  Traffic CORE (count1, count2, count3, NS_VEHICLE_DETECT, EW_VEHICLE_DETECT, NS_RED, NS_YELLOW, NS_GREEN, EW_RED, EW_YELLOW, EW_GREEN);

  initial begin

    clk = 0;
    NS_VEHICLE_DETECT = 0;
    EW_VEHICLE_DETECT = 1;

    $display("                         NS | EW ");
    $display("              (Time) | R Y G R Y G ");
    $monitor("%d | %h %h %h %h %h %h", $time, NS_RED, NS_YELLOW, NS_GREEN, EW_RED, EW_YELLOW, EW_GREEN);

    #1000 $finish;
  end

  always begin
    #1 clk = ~clk;
  end

  always @ (clk) begin
    if ($time % 6 == 0) begin
      NS_VEHICLE_DETECT = ~NS_VEHICLE_DETECT;
    end

    if ($time % 15 == 0) begin
    	EW_VEHICLE_DETECT = ~EW_VEHICLE_DETECT;
  	end
  end
endmodule
module Traffic
(
  input [4:0] nsCounter,
  input [3:0] ewCounter,
  input [1:0] yellowCounter,
  input NS_VEHICLE_DETECT,
  input EW_VEHICLE_DETECT,
  output reg NS_RED,
  output reg NS_YELLOW,
  output reg NS_GREEN,
  output reg EW_RED,
  output reg EW_YELLOW,
  output reg EW_GREEN
);

  // Sets the start state at: 001100
  initial begin
    NS_RED <= 0;
    NS_YELLOW <= 0;
    NS_GREEN <= 1;
    EW_RED <= 1;
    EW_YELLOW <= 0;
    EW_GREEN <= 0;
  end

  always @ (nsCounter) begin
  	// Sets the start state at: 010100
    if (nsCounter == 31 & EW_VEHICLE_DETECT & NS_GREEN) begin
       NS_RED <= 0;
       NS_YELLOW <= 1;
       NS_GREEN <= 0;
       EW_RED <= 1;
       EW_YELLOW <= 0;
       EW_GREEN <= 0;
    end
  end

  // Sets the start state at: 100010
  always @ (ewCounter) begin
    if (ewCounter == 15 & EW_GREEN) begin
       NS_RED <= 1;
       NS_YELLOW <= 0;
       NS_GREEN <= 0;
       EW_RED <= 0;
       EW_YELLOW <= 1;
       EW_GREEN <= 0;
    end
  end

  // Sets the start state at: 001100
  always @ (yellowCounter) begin
    if (yellowCounter == 3 & NS_YELLOW) begin
       NS_RED <= 1;
       NS_YELLOW <= 0;
       NS_GREEN <= 0;
       EW_RED <= 0;
       EW_YELLOW <= 0;
       EW_GREEN <= 1;
    end

    // Sets the start state at: 100001
    if (yellowCounter == 3 & EW_YELLOW) begin
       NS_RED <= 0;
       NS_YELLOW <= 0;
       NS_GREEN <= 1;
       EW_RED <= 1;
       EW_YELLOW <= 0;
       EW_GREEN <= 0;
    end
  end
endmodule
module nsCounter
(
    input clk,
    output [4:0] count
);

  wire clk;
  reg[4:0] count;

  initial
    	count = 0;

  always @ ( negedge clk )
    		count[0] <= ~count[0];

  always @ ( negedge count[0] )
    		count[1] <= ~count[1];

  always @ ( negedge count[1] )
    		count[2] <= ~count[2];

  always @ ( negedge count[2] )
    		count[3] <= ~count[3];

  always @ ( negedge count[3] )
    		count[4] <= ~count[4];

endmodule
module ewCounter
(
    input clk,
    output [3:0] count
);

  wire clk;
  reg[3:0] count;

  initial
    	count = 0;

  always @ ( negedge clk )
    		count[0] <= ~count[0];

  always @ ( negedge count[0] )
    		count[1] <= ~count[1];

  always @ ( negedge count[1] )
    		count[2] <= ~count[2];

  always @ ( negedge count[2] )
    		count[3] <= ~count[3];

endmodule
module yellowCounter
(
  input clk,
 	output [1:0] count
);

  wire clk;
  reg[1:0] count;

  initial
    	count = 0;

  always @ ( negedge clk )
    		count[0] <= ~count[0];

  always @ ( negedge count[0] )
    		count[1] <= ~count[1];

endmodule
module Traffic_Test;

  // Inputs
  reg NS_VEHICLE_DETECT;
  reg EW_VEHICLE_DETECT;

  // Outputs
  wire NS_RED;
  wire NS_YELLOW;
  wire NS_GREEN;
  wire EW_RED;
  wire EW_YELLOW;
  wire EW_GREEN;

  // Clock
  reg clk;

  // Counters
  wire[4:0] count1;
  wire[3:0] count2;
  wire[1:0] count3;

  // Counter Modules
  nsCounter clock1(clk, count1); 	 // Count a total of 32 seconds
  ewCounter clock2(clk, count2); 	 // Counts a total of 16 seconds
  yellowCounter clock3(clk, count3); // Counts a total of 4 seconds

  // Main Traffic Module
  Traffic CORE (count1, count2, count3, NS_VEHICLE_DETECT, EW_VEHICLE_DETECT, NS_RED, NS_YELLOW, NS_GREEN, EW_RED, EW_YELLOW, EW_GREEN);

  initial begin

    clk = 0;
    NS_VEHICLE_DETECT = 1;
    EW_VEHICLE_DETECT = 1;

    $display("                         NS | EW ");
    $display("              (Time) | R Y G R Y G ");
    $monitor("%d | %h %h %h %h %h %h", $time, NS_RED, NS_YELLOW, NS_GREEN, EW_RED, EW_YELLOW, EW_GREEN);

    #1000 $finish;
  end

  always begin
    #1 clk = ~clk;
  end
endmodule