dakies/OSS_Verilog huggingface dataset:
module sky130_ef_io__gpiov2_pad_wrapped (IN_H, PAD_A_NOESD_H, PAD_A_ESD_0_H, PAD_A_ESD_1_H,
    PAD, DM, HLD_H_N, IN, INP_DIS, IB_MODE_SEL, ENABLE_H, ENABLE_VDDA_H,
    ENABLE_INP_H, OE_N, TIE_HI_ESD, TIE_LO_ESD, SLOW, VTRIP_SEL, HLD_OVR,
    ANALOG_EN, ANALOG_SEL, ENABLE_VDDIO, ENABLE_VSWITCH_H, ANALOG_POL, OUT,
    AMUXBUS_A, AMUXBUS_B, VSSA, VDDA, VSWITCH, VDDIO_Q, VCCHIB, VDDIO, VCCD,
    VSSIO, VSSD, VSSIO_Q 
    );

input OUT;  		
input OE_N;  		
input HLD_H_N;		
input ENABLE_H;
input ENABLE_INP_H;	
input ENABLE_VDDA_H;	
input ENABLE_VSWITCH_H;	
input ENABLE_VDDIO;	
input INP_DIS;		
input IB_MODE_SEL;
input VTRIP_SEL;	
input SLOW;		
input HLD_OVR;		
input ANALOG_EN;	
input ANALOG_SEL;	
input ANALOG_POL;	
input [2:0] DM;		

inout VDDIO;	
inout VDDIO_Q;	
inout VDDA;
inout VCCD;
inout VSWITCH;
inout VCCHIB;
inout VSSA;
inout VSSD;
inout VSSIO_Q;
inout VSSIO;

inout PAD;
inout PAD_A_NOESD_H,PAD_A_ESD_0_H,PAD_A_ESD_1_H;
inout AMUXBUS_A;
inout AMUXBUS_B;

output IN;
output IN_H;
output TIE_HI_ESD, TIE_LO_ESD;

// Instantiate original version with metal4-only power bus
sky130_fd_io__top_gpiov2 gpiov2_base (
    .IN_H(IN_H),
    .PAD_A_NOESD_H(PAD_A_NOESD_H),
    .PAD_A_ESD_0_H(PAD_A_ESD_0_H),
    .PAD_A_ESD_1_H(PAD_A_ESD_1_H),
    .PAD(PAD),
    .DM(DM),
    .HLD_H_N(HLD_H_N),
    .IN(IN),
    .INP_DIS(INP_DIS),
    .IB_MODE_SEL(IB_MODE_SEL),
    .ENABLE_H(ENABLE_H),
    .ENABLE_VDDA_H(ENABLE_VDDA_H),
    .ENABLE_INP_H(ENABLE_INP_H),
    .OE_N(OE_N),
    .TIE_HI_ESD(TIE_HI_ESD),
    .TIE_LO_ESD(TIE_LO_ESD),
    .SLOW(SLOW),
    .VTRIP_SEL(VTRIP_SEL),
    .HLD_OVR(HLD_OVR),
    .ANALOG_EN(ANALOG_EN),
    .ANALOG_SEL(ANALOG_SEL),
    .ENABLE_VDDIO(ENABLE_VDDIO),
    .ENABLE_VSWITCH_H(ENABLE_VSWITCH_H),
    .ANALOG_POL(ANALOG_POL),
    .OUT(OUT),
    .AMUXBUS_A(AMUXBUS_A),
    .AMUXBUS_B(AMUXBUS_B),
    .VSSA(VSSA),
    .VDDA(VDDA),
    .VSWITCH(VSWITCH),
    .VDDIO_Q(VDDIO_Q),
    .VCCHIB(VCCHIB),
    .VDDIO(VDDIO),
    .VCCD(VCCD),
    .VSSIO(VSSIO),
    .VSSD(VSSD),
    .VSSIO_Q(VSSIO_Q) 
);

endmodule
module RAM256 #(parameter   USE_LATCH=1,
                            WSIZE=4 ) 
(
    `ifdef USE_POWER_PINS
    inout VPWR,	    /* 1.8V domain */
    inout VGND,
    `endif
    input   wire                CLK,    // FO: 2
    input   wire [WSIZE-1:0]     WE0,     // FO: 2
    input                        EN0,     // FO: 2
    input   wire [7:0]           A0,      // FO: 5
    input   wire [(WSIZE*8-1):0] Di0,     // FO: 2
    output  wire [(WSIZE*8-1):0] Do0

);

    wire [1:0]             SEL0;
    wire [(WSIZE*8-1):0]    Do0_pre[1:0]; 

    // 1x2 DEC
    // DEC1x2 DEC0 (.EN(EN0), .A(A0[7]), .SEL(SEL0));
    assign SEL0[0] = EN0 && (~A0[7]);
    assign SEL0[1] = EN0 && ( A0[7]);

    generate
        genvar i;
        for (i=0; i< 2; i=i+1) begin : BANK128
            RAM128 RAM128 (`ifdef USE_POWER_PINS .VPWR(VPWR), .VGND(VGND),  `endif .CLK(CLK), .EN0(SEL0[i]), .WE0(WE0), .Di0(Di0), .Do0(Do0_pre[i]), .A0(A0[6:0]) );        
        end
     endgenerate

    // Output MUX    
    // MUX2x1 #(.WIDTH(WSIZE*8)) Do0MUX ( .A0(Do0_pre[0]), .A1(Do0_pre[1]), .S(A0[7]), .X(Do0) );
    assign Do0 = A0[7]? Do0_pre[1]:Do0_pre[0];
    
endmodule
module RAM256 #( parameter COLS=1)
(
`ifdef USE_POWER_PINS
    VPWR,
    VGND,
`endif
    CLK,
    WE0,
    EN0,
    Di0,
    Do0,
    A0
);
    localparam A_WIDTH = 8+$clog2(COLS);

    input   wire            VPWR;
    input   wire            VGND;
    input   wire            CLK;
    input   wire    [3:0]   WE0;
    input   wire            EN0;
    input   wire    [31:0]  Di0;
    output  reg     [31:0]  Do0;
    input   wire    [(A_WIDTH - 1): 0]   A0;

    reg [31:0] RAM[(256*COLS)-1 : 0];

    always @(posedge CLK)
        if(EN0) begin
            Do0 <= RAM[A0];
            if(WE0[0]) RAM[A0][ 7: 0] <= Di0[7:0];
            if(WE0[1]) RAM[A0][15:8] <= Di0[15:8];
            if(WE0[2]) RAM[A0][23:16] <= Di0[23:16];
            if(WE0[3]) RAM[A0][31:24] <= Di0[31:24];
        end
        else
            Do0 <= 32'b0;

endmodule
module RAM128 #( parameter COLS=1)
(
`ifdef USE_POWER_PINS
    VPWR,
    VGND,
`endif
    CLK,
    WE0,
    EN0,
    Di0,
    Do0,
    A0
);
    localparam A_WIDTH = 7+$clog2(COLS);

    `ifdef USE_POWER_PINS
        input   wire            VPWR;
        input   wire            VGND;
    `endif
    input   wire            CLK;
    input   wire    [3:0]   WE0;
    input   wire            EN0;
    input   wire    [31:0]  Di0;
    output  reg     [31:0]  Do0;
    input   wire    [(A_WIDTH - 1): 0]   A0;

    reg [31:0] RAM[(256*COLS)-1 : 0];

    always @(posedge CLK)
        if(EN0) begin
            Do0 <= RAM[A0];
            if(WE0[0]) RAM[A0][ 7: 0] <= Di0[7:0];
            if(WE0[1]) RAM[A0][15:8] <= Di0[15:8];
            if(WE0[2]) RAM[A0][23:16] <= Di0[23:16];
            if(WE0[3]) RAM[A0][31:24] <= Di0[31:24];
        end
        else
            Do0 <= 32'b0;

endmodule
module wb_rw_test(
    input wire rx,
    output wire tx,
    input wire start
);

//parameter BTIME = 8680;
parameter BTIME = 2175;
//parameter BTIME = 2177;
reg TX;
wire RX;

reg [31:0] data;

assign RX = rx;
assign tx = TX;

initial begin
    TX <= 1'b1;
    #10000;
    $display("Executing SRAM write");
    wb_write(30'h00400024, 32'h775555ab);
    $display("Executing SRAM read");
    wb_read (32'h00400024, data);
    $display("output: %h", data);

    if (data != 32'h775555ab) begin
        $display("SRAM write failed");
        $finish;
    end else begin
        $display("SRAM write succeeded");
    end
end

task uart_put(input [7:0] b);
    integer i;
    begin
        TX = 1'b0;
        #BTIME;
        for(i=0; i<8; i=i+1) begin
            TX = b[i];
            #BTIME;
        end
        TX = 1'b1;
        #(BTIME);
    end
endtask

task uart_put_ns(input [7:0] b);
    integer i;
    begin
        TX = 1'b0;
        #BTIME;
        for(i=0; i<8; i=i+1) begin
            TX = b[i];
            #BTIME;
        end
        TX = 1'b1;
//        #(BTIME);
    end
endtask

task uart_get(output [7:0] b);
    integer i;
    begin
        @(negedge RX);
        #BTIME;
        for(i=0; i<8; i=i+1) begin
            #(BTIME/2);
            b[i] <= RX;
            #(BTIME/2);
        end
        #(BTIME);
    end
endtask

task wb_read (input [31:0] addr, output [31:0] word);
    begin
        uart_put(8'h2);     // read cmd
        uart_put(8'h1);      // size
        uart_put(addr[31:24]);
        uart_put(addr[23:16]);
        uart_put(addr[15:8]);
        uart_put_ns(addr[7:0]);
        uart_get(word[31:24]);
        uart_get(word[23:16]);
        uart_get(word[15:8]);
        uart_get(word[7:0]);
    end
endtask

task wb_write (input [31:0] addr, input [31:0] word);
    begin
        uart_put(8'h1);     // write cmd
        uart_put(8'h1);      // size
        uart_put(addr[31:24]);
        uart_put(addr[23:16]);
        uart_put(addr[15:8]);
        uart_put(addr[7:0]);
        uart_put(word[31:24]);
        uart_put(word[23:16]);
        uart_put(word[15:8]);
        uart_put(word[7:0]);
    end
endtask

endmodule
module tbuart (
	input  ser_rx,
	output  ser_tx
);
	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 #2650 clk <= (clk === 1'b0);  // working for 9600 baud
//	always #125 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 [15:0] checkbits;
	wire [37:0] mprj_io;
	wire flash_csb;
	wire flash_clk;
	wire flash_io0;
	wire flash_io1;
	wire uart_tx;
	wire uart_loopback;
	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
	
	
	`ifdef ENABLE_SDF
		initial begin
			$sdf_annotate("../../../../sdf/DFFRAM.sdf", uut.soc.DFFRAM_0 );
			$sdf_annotate("../../../../sdf/mgmt_core.sdf", uut.soc.core);
			$sdf_annotate("../../../../sdf/mgmt_core_wrapper.sdf", uut.soc);
		end
	`endif 


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

		$display("Wait for UART o/p");
		repeat (450) begin
			repeat (1000) @(posedge clock);
			// Diagnostic. . . interrupts output pattern.
		end
        $display("%c[1;31m",27);
		`ifdef GL
			$display ("Monitor: Timeout, Test UART (GL) Failed");
		`else
			$display ("Monitor: Timeout, Test UART (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
		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.
	assign mprj_io[0] = 1'b0;  // Disable debug mode

	caravel uut (
		.vddio	  (VDD3V3),
		.vddio_2  (VDD3V3),		
		.vssio	  (VSS),
		.vssio_2  (VSS),
		.vdda	  (VDD3V3),
		.vssa	  (VSS),
		.vccd	  (VDD1V8),
		.vssd	  (VSS),
		.vdda1    (VDD3V3),
		.vdda1_2  (VDD3V3),
		.vdda2    (VDD3V3),
		.vssa1	  (VSS),
		.vssa1_2  (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 ibex_counter (
	clk_i,
	rst_ni,
	counter_inc_i,
	counterh_we_i,
	counter_we_i,
	counter_val_i,
	counter_val_o,
	counter_val_upd_o
);
	parameter signed [31:0] CounterWidth = 32;
	parameter [0:0] ProvideValUpd = 0;
	input wire clk_i;
	input wire rst_ni;
	input wire counter_inc_i;
	input wire counterh_we_i;
	input wire counter_we_i;
	input wire [31:0] counter_val_i;
	output wire [63:0] counter_val_o;
	output wire [63:0] counter_val_upd_o;
	wire [63:0] counter;
	wire [CounterWidth - 1:0] counter_upd;
	reg [63:0] counter_load;
	reg we;
	reg [CounterWidth - 1:0] counter_d;
	assign counter_upd = counter[CounterWidth - 1:0] + {{CounterWidth - 1 {1'b0}}, 1'b1};
	always @(*) begin
		we = counter_we_i | counterh_we_i;
		counter_load[63:32] = counter[63:32];
		counter_load[31:0] = counter_val_i;
		if (counterh_we_i) begin
			counter_load[63:32] = counter_val_i;
			counter_load[31:0] = counter[31:0];
		end
		if (we)
			counter_d = counter_load[CounterWidth - 1:0];
		else if (counter_inc_i)
			counter_d = counter_upd[CounterWidth - 1:0];
		else
			counter_d = counter[CounterWidth - 1:0];
	end
	reg [CounterWidth - 1:0] counter_q;
	always @(posedge clk_i or negedge rst_ni)
		if (!rst_ni)
			counter_q <= 1'sb0;
		else
			counter_q <= counter_d;
	generate
		if (CounterWidth < 64) begin : g_counter_narrow
			wire [63:CounterWidth] unused_counter_load;
			assign counter[CounterWidth - 1:0] = counter_q;
			assign counter[63:CounterWidth] = 1'sb0;
			if (ProvideValUpd) begin : g_counter_val_upd_o
				assign counter_val_upd_o[CounterWidth - 1:0] = counter_upd;
			end
			else begin : g_no_counter_val_upd_o
				assign counter_val_upd_o[CounterWidth - 1:0] = 1'sb0;
			end
			assign counter_val_upd_o[63:CounterWidth] = 1'sb0;
			assign unused_counter_load = counter_load[63:CounterWidth];
		end
		else begin : g_counter_full
			assign counter = counter_q;
			if (ProvideValUpd) begin : g_counter_val_upd_o
				assign counter_val_upd_o = counter_upd;
			end
			else begin : g_no_counter_val_upd_o
				assign counter_val_upd_o = 1'sb0;
			end
		end
	endgenerate
	assign counter_val_o = counter;
endmodule
module prim_clock_gating (
  input  clk_i,
  input  en_i,
  input  test_en_i,
  output clk_o
);
/*
  reg en_latch;

  always @* begin
    if (!clk_i) begin
      en_latch = en_i | test_en_i;
    end
  end
  assign clk_o = en_latch & clk_i;
*/
  assign clk_o = clk_i;
endmodule
module ibex_register_file_latch (
	clk_i,
	rst_ni,
	test_en_i,
	dummy_instr_id_i,
	raddr_a_i,
	rdata_a_o,
	raddr_b_i,
	rdata_b_o,
	waddr_a_i,
	wdata_a_i,
	we_a_i
);
	parameter [0:0] RV32E = 0;
	parameter [31:0] DataWidth = 32;
	parameter [0:0] DummyInstructions = 0;
	input wire clk_i;
	input wire rst_ni;
	input wire test_en_i;
	input wire dummy_instr_id_i;
	input wire [4:0] raddr_a_i;
	output wire [DataWidth - 1:0] rdata_a_o;
	input wire [4:0] raddr_b_i;
	output wire [DataWidth - 1:0] rdata_b_o;
	input wire [4:0] waddr_a_i;
	input wire [DataWidth - 1:0] wdata_a_i;
	input wire we_a_i;
	localparam [31:0] ADDR_WIDTH = (RV32E ? 4 : 5);
	localparam [31:0] NUM_WORDS = 2 ** ADDR_WIDTH;
	reg [DataWidth - 1:0] mem [0:NUM_WORDS - 1];
	reg [NUM_WORDS - 1:1] waddr_onehot_a;
	wire [NUM_WORDS - 1:1] mem_clocks;
	reg [DataWidth - 1:0] wdata_a_q;
	wire [ADDR_WIDTH - 1:0] raddr_a_int;
	wire [ADDR_WIDTH - 1:0] raddr_b_int;
	wire [ADDR_WIDTH - 1:0] waddr_a_int;
	assign raddr_a_int = raddr_a_i[ADDR_WIDTH - 1:0];
	assign raddr_b_int = raddr_b_i[ADDR_WIDTH - 1:0];
	assign waddr_a_int = waddr_a_i[ADDR_WIDTH - 1:0];
	wire clk_int;
	assign rdata_a_o = mem[raddr_a_int];
	assign rdata_b_o = mem[raddr_b_int];
	prim_clock_gating cg_we_global(
		.clk_i(clk_i),
		.en_i(we_a_i),
		.test_en_i(test_en_i),
		.clk_o(clk_int)
	);
	always @(posedge clk_int or negedge rst_ni) begin : sample_wdata
		if (!rst_ni)
			wdata_a_q <= 1'sb0;
		else if (we_a_i)
			wdata_a_q <= wdata_a_i;
	end
	function automatic signed [4:0] sv2v_cast_5_signed;
		input reg signed [4:0] inp;
		sv2v_cast_5_signed = inp;
	endfunction
	always @(*) begin : wad
		begin : sv2v_autoblock_1
			reg signed [31:0] i;
			for (i = 1; i < NUM_WORDS; i = i + 1)
				begin : wad_word_iter
					if (we_a_i && (waddr_a_int == sv2v_cast_5_signed(i)))
						waddr_onehot_a[i] = 1'b1;
					else
						waddr_onehot_a[i] = 1'b0;
				end
		end
	end
	genvar x;
	generate
		for (x = 1; x < NUM_WORDS; x = x + 1) begin : gen_cg_word_iter
			prim_clock_gating cg_i(
				.clk_i(clk_int),
				.en_i(waddr_onehot_a[x]),
				.test_en_i(test_en_i),
				.clk_o(mem_clocks[x])
			);
		end
	endgenerate
	genvar i;
	generate
		for (i = 1; i < NUM_WORDS; i = i + 1) begin : g_rf_latches
			always @(*)
				if (mem_clocks[i])
					mem[i] = wdata_a_q;
		end
		if (DummyInstructions) begin : g_dummy_r0
			wire we_r0_dummy;
			wire r0_clock;
			reg [DataWidth - 1:0] mem_r0;
			assign we_r0_dummy = we_a_i & dummy_instr_id_i;
			prim_clock_gating cg_i(
				.clk_i(clk_int),
				.en_i(we_r0_dummy),
				.test_en_i(test_en_i),
				.clk_o(r0_clock)
			);
			always @(*) begin : latch_wdata
				if (r0_clock)
					mem_r0 = wdata_a_q;
			end
			wire [DataWidth:1] sv2v_tmp_35384;
			assign sv2v_tmp_35384 = (dummy_instr_id_i ? mem_r0 : {DataWidth {1'sb0}});
			always @(*) mem[0] = sv2v_tmp_35384;
		end
		else begin : g_normal_r0
			wire unused_dummy_instr_id;
			assign unused_dummy_instr_id = dummy_instr_id_i;
			wire [DataWidth:1] sv2v_tmp_450E3;
			assign sv2v_tmp_450E3 = 1'sb0;
			always @(*) mem[0] = sv2v_tmp_450E3;
		end
	endgenerate
endmodule
module ibex_branch_predict (
	clk_i,
	rst_ni,
	fetch_rdata_i,
	fetch_pc_i,
	fetch_valid_i,
	predict_branch_taken_o,
	predict_branch_pc_o
);
	input wire clk_i;
	input wire rst_ni;
	input wire [31:0] fetch_rdata_i;
	input wire [31:0] fetch_pc_i;
	input wire fetch_valid_i;
	output wire predict_branch_taken_o;
	output wire [31:0] predict_branch_pc_o;
	wire [31:0] imm_j_type;
	wire [31:0] imm_b_type;
	wire [31:0] imm_cj_type;
	wire [31:0] imm_cb_type;
	reg [31:0] branch_imm;
	wire [31:0] instr;
	wire instr_j;
	wire instr_b;
	wire instr_cj;
	wire instr_cb;
	wire instr_b_taken;
	assign instr = fetch_rdata_i;
	assign imm_j_type = {{12 {instr[31]}}, instr[19:12], instr[20], instr[30:21], 1'b0};
	assign imm_b_type = {{19 {instr[31]}}, instr[31], instr[7], instr[30:25], instr[11:8], 1'b0};
	assign imm_cj_type = {{20 {instr[12]}}, instr[12], instr[8], instr[10:9], instr[6], instr[7], instr[2], instr[11], instr[5:3], 1'b0};
	assign imm_cb_type = {{23 {instr[12]}}, instr[12], instr[6:5], instr[2], instr[11:10], instr[4:3], 1'b0};
	assign instr_b = instr[6:0] == 7'h63;
	assign instr_j = instr[6:0] == 7'h6f;
	assign instr_cb = (instr[1:0] == 2'b01) & ((instr[15:13] == 3'b110) | (instr[15:13] == 3'b111));
	assign instr_cj = (instr[1:0] == 2'b01) & ((instr[15:13] == 3'b101) | (instr[15:13] == 3'b001));
	always @(*) begin
		branch_imm = imm_b_type;
		case (1'b1)
			instr_j: branch_imm = imm_j_type;
			instr_b: branch_imm = imm_b_type;
			instr_cj: branch_imm = imm_cj_type;
			instr_cb: branch_imm = imm_cb_type;
			default:
				;
		endcase
	end
	assign instr_b_taken = (instr_b & imm_b_type[31]) | (instr_cb & imm_cb_type[31]);
	assign predict_branch_taken_o = fetch_valid_i & ((instr_j | instr_cj) | instr_b_taken);
	assign predict_branch_pc_o = fetch_pc_i + branch_imm;
endmodule
module pipeline_registers_set
  #(
    parameter
    BIT_WIDTH         = 10,
    NUMBER_OF_STAGES  = 5
    )
  (
   input                                  clk,
   input                                  reset_n,
   input                                  set,
   input [BIT_WIDTH*NUMBER_OF_STAGES-1:0] set_data,
   input [BIT_WIDTH-1:0]                  pipe_in,
   output reg [BIT_WIDTH-1:0]             pipe_out
   );

  // Main generate function for conditional hardware instantiation
  generate
    genvar                                 i;
    // Pass-through case for the odd event that no pipeline stages are
    // specified.
    if (NUMBER_OF_STAGES == 0) begin
      always @ *
        pipe_out = pipe_in;
    end
    // Single flop case for a single stage pipeline
    else if (NUMBER_OF_STAGES == 1) begin
      always @ (posedge clk or negedge reset_n)
        pipe_out <= (!reset_n) ? 0 : (set) ? set_data : pipe_in;
    end
    // Case for 2 or more pipeline stages
    else begin
      // Create the necessary regs
      reg [BIT_WIDTH*(NUMBER_OF_STAGES-1)-1:0] pipe_gen;
      // Create logic for the initial and final pipeline registers
      always @ (posedge clk or negedge reset_n) begin
        if (!reset_n) begin
          pipe_gen[BIT_WIDTH-1:0] <= 0;
          pipe_out                <= 0;
        end
        else if (set) begin
          pipe_gen[BIT_WIDTH-1:0] <= set_data[BIT_WIDTH-1:0];
          pipe_out                <= set_data[BIT_WIDTH*NUMBER_OF_STAGES-1:BIT_WIDTH*(NUMBER_OF_STAGES-1)];
        end
        else begin
          pipe_gen[BIT_WIDTH-1:0] <= pipe_in;
          pipe_out                <= pipe_gen[BIT_WIDTH*(NUMBER_OF_STAGES-1)-1:BIT_WIDTH*(NUMBER_OF_STAGES-2)];
        end
      end
      // Create the intermediate pipeline registers if there are 3 or
      // more pipeline stages
      for (i = 1; i < NUMBER_OF_STAGES-1; i = i + 1) begin : pipeline
        always @ (posedge clk or negedge reset_n)
          pipe_gen[BIT_WIDTH*(i+1)-1:BIT_WIDTH*i] <= (!reset_n) ? 0 : (set) ? set_data[BIT_WIDTH*(i+1)-1:BIT_WIDTH*i] : pipe_gen[BIT_WIDTH*i-1:BIT_WIDTH*(i-1)];
      end
    end
  endgenerate

endmodule
module sqrt_generic
  #(parameter
    WIDTH_INPUT = 16,
    WIDTH_OUTPUT = WIDTH_INPUT / 2 + WIDTH_INPUT % 2,
    FLAG_PIPELINE = 1 // Currently unused
    )
  (
   input                      clk,       // clock
   input                      rst_n,     // asynchronous reset
   input                      valid_in,  // optional start signal
   input [WIDTH_INPUT-1:0]    radicand,  // unsigned radicand
   output                     valid_out, // optional data valid signal
   output  [WIDTH_OUTPUT-1:0] root       // unsigned root
   );

  // Pass-though pipe that sends the input valid signal to the
  // output valid signal
  pipeline_registers
    #(.BIT_WIDTH(1),
      .NUMBER_OF_STAGES(WIDTH_OUTPUT))
  pipe_valid
    (.clk(clk),
     .reset_n(rst_n),
     .pipe_in(valid_in),
     .pipe_out(valid_out)
     );

  reg [WIDTH_INPUT-1:0] root_gen [WIDTH_OUTPUT-1:0];
  reg [WIDTH_INPUT-1:0] radicand_gen [WIDTH_OUTPUT-1:0];
  wire [WIDTH_INPUT-1:0] mask_gen [WIDTH_OUTPUT-1:0];

  generate
    genvar i;
    // Generate all the masks
    for (i = 0; i < WIDTH_OUTPUT; i = i + 1) begin: mask
      if (i % 2)
        assign mask_gen[WIDTH_OUTPUT-i-1] = 4 << 4 * (i/2);
      else
        assign mask_gen[WIDTH_OUTPUT-i-1] = 1 << 4 * (i/2);
    end

    // Handle the operations of each pipeline stage
    for (i = 0; i < WIDTH_OUTPUT; i = i + 1) begin: pipe_sqrt
      always @ (posedge clk or negedge rst_n) begin: pipe_stage
        // Reset condition
        if (!rst_n) begin
          radicand_gen[i] <= 0;
          root_gen[i] <= 0;
        end
        else begin
          // Logic for any stage which is not the first stage
          if (i > 0) begin
            if (root_gen[i-1] + mask_gen[i] <= radicand_gen[i-1]) begin
              radicand_gen[i] <= radicand_gen[i-1] - mask_gen[i] - root_gen[i-1];
              root_gen[i] <= (root_gen[i-1] >> 1) + mask_gen[i];
            end
            else begin
              radicand_gen[i] <= radicand_gen[i-1];
              root_gen[i] <= root_gen[i-1] >> 1;
            end
          end

          // Logic specific to the first stage
          if (i == 0) begin
            if (mask_gen[i] <= radicand) begin
              radicand_gen[i] <= radicand - mask_gen[i];
              root_gen[i] <= mask_gen[i];
            end
            else begin
              radicand_gen[i] <= radicand;
              root_gen[i] <= 0;
            end
          end
        end
      end
    end
  endgenerate

  assign root = root_gen[WIDTH_OUTPUT-1];

endmodule
module button_debounce
  #(
    parameter
    CLK_FREQUENCY  = 10_000_000,
    DEBOUNCE_HZ    = 2
    // These parameters are specified such that you can choose any power
    // of 2 frequency for a debouncer between 1 Hz and
    // CLK_FREQUENCY. Note, that this will throw errors if you choose a
    // non power of 2 frequency (i.e. count_value evaluates to some
    // number / 3 which isn't interpreted as a logical right shift). I'm
    // assuming this will not work for DEBOUNCE_HZ values less than 1,
    // however, I'm uncertain of the value of a debouncer for fractional
    // hertz button presses.
    )
  (
   input      clk,     // clock
   input      reset_n, // asynchronous reset
   input      button,  // bouncy button
   output reg debounce // debounced 1-cycle signal
   );

  localparam
    COUNT_VALUE  = CLK_FREQUENCY / DEBOUNCE_HZ,
    WAIT         = 0,
    FIRE         = 1,
    COUNT        = 2;

  reg [1:0]   state, next_state;
  reg [25:0]  count;

  always @ (posedge clk or negedge reset_n)
    state <= (!reset_n) ? WAIT : next_state;

  always @ (posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      debounce <= 0;
      count    <= 0;
    end
    else begin
      debounce <= 0;
      count    <= 0;
      case (state)
        WAIT: begin
        end
        FIRE: begin
          debounce <= 1;
        end
        COUNT: begin
          count <= count + 1;
        end
      endcase
    end
  end

  always @ * begin
    case (state)
      WAIT:    next_state = (button)                  ? FIRE : state;
      FIRE:    next_state = COUNT;
      COUNT:   next_state = (count > COUNT_VALUE - 1) ? WAIT : state;
      default: next_state = WAIT;
    endcase
  end

endmodule
module pipeline_registers
  #(
    parameter
    BIT_WIDTH         = 10,
    NUMBER_OF_STAGES  = 5
    )
  (
   input                      clk,
   input                      reset_n,
   input [BIT_WIDTH-1:0]      pipe_in,
   output reg [BIT_WIDTH-1:0] pipe_out
   );

  // Main generate function for conditional hardware instantiation
  generate
    genvar                                 i;
    // Pass-through case for the odd event that no pipeline stages are
    // specified.
    if (NUMBER_OF_STAGES == 0) begin
      always @ *
        pipe_out = pipe_in;
    end
    // Single flop case for a single stage pipeline
    else if (NUMBER_OF_STAGES == 1) begin
      always @ (posedge clk or negedge reset_n)
        pipe_out <= (!reset_n) ? 0 : pipe_in;
    end
    // Case for 2 or more pipeline stages
    else begin
      // Create the necessary regs
      reg [BIT_WIDTH*(NUMBER_OF_STAGES-1)-1:0] pipe_gen;
      // Create logic for the initial and final pipeline registers
      always @ (posedge clk or negedge reset_n) begin
        if (!reset_n) begin
          pipe_gen[BIT_WIDTH-1:0] <= 0;
          pipe_out                <= 0;
        end
        else begin
          pipe_gen[BIT_WIDTH-1:0] <= pipe_in;
          pipe_out                <= pipe_gen[BIT_WIDTH*(NUMBER_OF_STAGES-1)-1:BIT_WIDTH*(NUMBER_OF_STAGES-2)];
        end
      end
      // Create the intermediate pipeline registers if there are 3 or
      // more pipeline stages
      for (i = 1; i < NUMBER_OF_STAGES-1; i = i + 1) begin : pipeline
        always @ (posedge clk or negedge reset_n)
          pipe_gen[BIT_WIDTH*(i+1)-1:BIT_WIDTH*i] <= (!reset_n) ? 0 : pipe_gen[BIT_WIDTH*i-1:BIT_WIDTH*(i-1)];
      end
    end
  endgenerate

endmodule
module uart_tx
  #(
    parameter
    CLK_FREQUENCY = 66_000_000,         // fpga clock frequency
    UART_FREQUENCY = 921_600            // UART clock frequency
    )
  (
   input       user_clk, // 66 MHz
   input       rst_n,
   input       start_tx,
   input [7:0] data,
   output reg  tx_bit,
   output reg  ready,
   output reg  chipscope_clk
   );

  localparam
    TICKS_PER_BIT  = CLK_FREQUENCY / UART_FREQUENCY;
  localparam IDLE = 2'd0,
    INIT = 2'd1,
    TX   = 2'd2,
    DONE = 2'd3;

  reg [ 1:0]                state, next_state;
  reg [ 2:0]                bit_count;
  reg [ 7:0]                data_buf;
  reg [11:0]                clk_count;

  always @ (posedge user_clk or negedge rst_n) begin
    if (!rst_n)
      chipscope_clk <= 0;
    else if ((clk_count == TICKS_PER_BIT-1) |
             (clk_count == TICKS_PER_BIT>>1))
      chipscope_clk <= ~chipscope_clk;
    else
      chipscope_clk <= chipscope_clk;
  end

  always @ (posedge user_clk or negedge rst_n) begin
    state <= (!rst_n) ? IDLE : next_state;
  end

  always @ (posedge user_clk or negedge rst_n) begin
    if (!rst_n) begin
      tx_bit    <= 1; // should be pulled up on reset
      ready     <= 1;
      data_buf  <= 0;
      bit_count <= 0;
      clk_count <= 0;
    end
    else begin
      case (state)
        IDLE: begin
          tx_bit    <= 1;
          ready     <= 1;
          data_buf  <= data;
          bit_count <= 0;
          clk_count <= 0;
        end
        INIT: begin
          tx_bit    <= 0;
          ready     <= 0;
          data_buf  <= data_buf;
          bit_count <= 0;
          clk_count <= (clk_count == TICKS_PER_BIT-1) ? 12'b0 : clk_count + 12'b1;
        end
        TX: begin
          tx_bit    <= data_buf[bit_count];
          ready     <= 0;
          data_buf  <= data_buf;
          bit_count <= (clk_count == TICKS_PER_BIT-1) ? bit_count+3'b1 : bit_count;
          clk_count <= (clk_count == TICKS_PER_BIT-1) ? 12'b0          : clk_count + 12'b1;
        end
        DONE: begin
          tx_bit    <= 1;
          ready     <= 0;
          data_buf  <= data_buf;
          bit_count <= 0;
          clk_count <= (clk_count == TICKS_PER_BIT-1) ? 12'b0 : clk_count + 12'b1;
        end
        default: begin
          tx_bit    <= 1'bx;
          ready     <= 1'bx;
          data_buf  <= 8'bx;
          bit_count <= 3'bx;
          clk_count <= 12'bx;
        end
      endcase
    end
  end

  always @ * begin
    case (state)
      IDLE:    next_state <= (start_tx)                     ? INIT : state;
      INIT:    next_state <= (clk_count == TICKS_PER_BIT-1) ? TX   : state;
      TX:      next_state <= ((bit_count == 7) & (clk_count
                                                  == TICKS_PER_BIT-1))         ? DONE : state;
      DONE:    next_state <= (clk_count == TICKS_PER_BIT-1) ? IDLE : state;
      default: next_state <= IDLE;
    endcase
  end

endmodule
module reset
  (
   input clk,       // input clock
   input rst_n_in,  // asynchronous reset from userland
   output rst_n_out // asynchronous assert/synchronous deassert chip broadcast
   );

  // You have two DFFs in series (a two stage pipe) with the input to
  // the first DFF tied to 1. When the input active low reset is
  // deasserted this asynchronously resets the DFFs. This causes the
  // second DFF to broadcast an asynchronous reset out to the whole
  // chip. However, when the input rest is asserted, the flip flops
  // are enabled, and you get a synchronous assert of the active low
  // reset to the entire chip.

  pipeline_registers
    #(
      .BIT_WIDTH(1),
      .NUMBER_OF_STAGES(2)
      )
  reset_flops
    (
     .clk(clk),           // input clk
     .reset_n(rst_n_in),  // convert to active low
     .pipe_in(1'b1),      // input is always 1
     .pipe_out(rst_n_out) // asynchronous reset output
     );

endmodule
module sign_extender
  #(
    parameter
    INPUT_WIDTH = 8,
    OUTPUT_WIDTH = 16
    )
  (
   input [INPUT_WIDTH-1:0] original,
   output reg [OUTPUT_WIDTH-1:0] sign_extended_original
   );

  wire [OUTPUT_WIDTH-INPUT_WIDTH-1:0] sign_extend;

  generate
    genvar                           i;
    for (i = 0; i < OUTPUT_WIDTH-INPUT_WIDTH; i = i + 1) begin : gen_sign_extend
      assign sign_extend[i]  = (original[INPUT_WIDTH-1]) ? 1'b1 : 1'b0;
    end
  endgenerate

  always @ * begin
    sign_extended_original  = {sign_extend,original};
  end

endmodule
module ram_infer
  #(
    parameter
    WIDTH = 8,
    DEPTH = 64,
    LG_DEPTH = 6,
    INIT_VAL = 8'd0
    )
  (
   input                  clka, clkb, wea, web, ena, enb,
   input [LG_DEPTH-1:0]   addra, addrb,
   input [WIDTH-1:0]      dina, dinb,
   output reg [WIDTH-1:0] douta, doutb
   );

  reg [WIDTH-1:0]         ram [DEPTH-1:0];
  reg [WIDTH-1:0]         doa, dob;

  genvar                  i;

  generate
    for (i=0; i<DEPTH; i=i+1) begin: gen_init
      initial begin
        ram[i]  = INIT_VAL;
      end
    end
  endgenerate

  always @(posedge clka) begin
    if (ena) begin
      if (wea)
        ram[addra] <= dina;
      douta <= ram[addra];
    end
  end

  always @(posedge clkb) begin
    if (enb) begin
      if (web)
        ram[addrb] <= dinb;
      doutb <= ram[addrb];
    end
  end

endmodule
module t_sqrt_pipelined();

  parameter
    INPUT_BITS  = 4;
  localparam
    OUTPUT_BITS  = INPUT_BITS / 2 + INPUT_BITS % 2;

  reg [INPUT_BITS-1:0] radicand;
  reg                  clk, start, reset_n;

  wire [OUTPUT_BITS-1:0] root;
  wire                   data_valid;
//  wire [7:0] root_good;

  sqrt_pipelined
    #(
      .INPUT_BITS(INPUT_BITS)
      )
    sqrt_pipelined
      (
       .clk(clk),
       .reset_n(reset_n),
       .start(start),
       .radicand(radicand),
       .data_valid(data_valid),
       .root(root)
       );

  initial begin
    radicand     = 16'bx; clk = 1'bx; start = 1'bx; reset_n = 1'bx;;
    #10 reset_n  = 0; clk = 0;
    #50 reset_n  = 1; radicand = 0;
//    #40 radicand  = 81; start = 1;
//    #10 radicand  = 16'bx; start = 0;
    #10000 $finish;
  end

  always
    #5 clk = ~clk;

  always begin
    #10 radicand  = radicand + 1; start = 1;
    #10 start     = 0;
  end


//  always begin
//    #80 start  = 1;
//    #10 start  = 0;
//  end

endmodule
module t_button_debounce();

  parameter
    CLK_FREQUENCY  = 10_000_000,
    DEBOUNCE_HZ    = 2;

  reg clk, reset_n, button;
  wire debounce;

  button_debounce
    #(
      .CLK_FREQUENCY(CLK_FREQUENCY),
      .DEBOUNCE_HZ(DEBOUNCE_HZ)
      )
  button_debounce
    (
     .clk(clk),
     .reset_n(reset_n),
     .button(button),
     .debounce(debounce)
     );

  initial begin
    clk          = 1'bx; reset_n = 1'bx; button = 1'bx;
    #10 reset_n  = 1;
    #10 reset_n  = 0; clk = 0;
    #10 reset_n  = 1;
    #10 button   = 0;
  end

  always
    #5 clk  = ~clk;

  always begin
    #100 button  = ~button;
    #0.1 button  = ~button;
    #0.1 button  = ~button;
    #0.1 button  = ~button;
    #0.1 button  = ~button;
    #0.1 button  = ~button;
    #0.1 button  = ~button;
    #0.1 button  = ~button;
    #0.1 button  = ~button;
  end

endmodule
module t_sqrt_generic();
  localparam
    WIDTH_INPUT = 16,
    WIDTH_OUTPUT = WIDTH_INPUT / 2 + WIDTH_INPUT % 2;

  reg clk, rst_n, valid_in;
  wire valid_out;
  reg [WIDTH_INPUT-1:0] radicand;
  wire [WIDTH_INPUT-1:0] radicand_d;
  wire [WIDTH_OUTPUT-1:0] root;

  sqrt_generic
    #(.WIDTH_INPUT(WIDTH_INPUT),
      .WIDTH_OUTPUT(WIDTH_OUTPUT))
  u_sqrt_generic
    (.clk(clk),
     .rst_n(rst_n),
     .valid_in(valid_in),
     .radicand(radicand),
     .valid_out(valid_out),
     .root(root));

  pipeline_registers
    #(.BIT_WIDTH(WIDTH_INPUT),
      .NUMBER_OF_STAGES(WIDTH_OUTPUT))
  u_pipe_radicand
    (.clk(clk),
     .reset_n(rst_n),
     .pipe_in(radicand),
     .pipe_out(radicand_d));


  always
    #1 clk = ~clk;

  initial begin
    clk = 0; rst_n = 0;
    #5 rst_n = 1;
  end

  always @(posedge clk) begin
    radicand <= radicand + 1;
    valid_in <= 1;
    if (valid_out) begin
      if ($itor(root) - $floor($itor(radicand_d)) > 0)
        $error("Bad square root value:\n  sqrt(%0d) = %0d (correct: %0.0f)",
                 radicand_d, root, $floor($itor(radicand_d)));
      // $display("%8d %8d", root, radicand_d);
    end

    if (radicand_d >= (1 << WIDTH_INPUT) - 1) begin
      $stop;
    end

    // Reset case
    if (!rst_n) begin
      radicand <= '0;
      valid_in <= 0;
    end
  end

endmodule
module display_tb();
reg       clk;
reg       data_valid;
reg [7:0] data_out;

display UUT(clk, data_valid, data_out);

initial
begin
 clk = 0;
 data_valid = 0;
 #2;
 data_valid = 1;
 data_out = 8'h34;
 #2;
 data_out = 8'h57;
 #2;
 data_out = 8'h9B;
 #2;
 data_valid = 0;
 data_out = 8'h11;
 #2;
 data_out = 8'h13;
 #2;
 $finish;
end
always
begin
 clk = ~clk;
 #1;
end
endmodule
module top_tb();

reg  clk, rst_n, l_start, r_start, l_clear, r_clear;

top TOP(clk, rst_n, l_start, r_start, l_clear, r_clear);

initial
begin
 clk = 0;
 $dumpfile("../vcd/interface_tb.vcd");
 $dumpvars(0, top_tb);

 rst_n = 0;
 l_clear = 0;
 r_clear = 0;
 l_start = 0;
 r_start = 0;
 #2;
 rst_n = 1;
 l_start = 1;
 r_start = 1;
 #2;
 l_start = 0;
 r_start = 0;
 #10860050;
 $finish;
end

always
begin
 clk = ~clk;
 #1;
end

endmodule
module filter5x5_tb;

reg [7:0]     Din;
reg           rst, clk, data_valid;
wire          fill_now;
wire [1:0]    state;
wire [15:0]   Dout;

filter5x5 UUT (Din, data_valid, rst, clk, fill_now, Dout);

initial
begin
 clk = 0;
 $dumpfile("vcd/filter5x5.vcd");
 $dumpvars(0, filter5x5_tb);
 rst = 1;
 Din = 8'h00;
 data_valid = 0;
 #2;
 rst = 0;
 data_valid = 1;
 Din = 8'h23;
 #2;
 Din = 8'h55;
 #2;
 Din = 8'h14;
 #2;
 Din = 8'hf5;
 #2;
 Din = 8'h4c;
 #2;
 Din = 8'h56;
 #2;
 Din = 8'h11;
 #2;
 Din = 8'haa;
 #2;
 Din = 8'hae;
 #2;
 Din = 8'hcd;
 #2;
 Din = 8'hc6;
 #2;
 Din = 8'h44;
 #2;
 Din = 8'he7;
 #2;
 Din = 8'hd9;
 #2;
 Din = 8'hf0;
 #2;
 #1000;
 $finish;
end

always
begin
 clk = ~clk;
 #1;
end

endmodule
module BRWM_tb();

reg         clk, on_off, clear, rw, pause;
reg [7:0]   data_in;
wire [7:0]  data_out;
wire        done;

BRWM DUT (clk, on_off, rw, clear, pause, data_in, data_out, done);

initial
begin
 $dumpfile("../vcd/BRWM_tb.vcd");
 $dumpvars(0, BRWM_tb);

 data_in = 8'h00;
 pause = 0;
 on_off = 0;
 #150;
 clear = 0;
 on_off = 1;
 rw = 1;
 #150;
 rw = 0;
 #150;
 clear = 1;
 #150;
 on_off = 0;
 clear = 0;
 #30;
 $finish;
end

always
begin
 clk = 1'b0;
 #1;
 clk = 1'b1;
 #1;
end

endmodule
module image_tb();

reg           clk;
reg           camera_en;
wire          data_valid;
wire [7:0]    data_out;

image UUT(clk, camera_en, data_valid, data_out);

initial
begin
 clk = 0;
 $dumpfile("vcd/image.vcd");
 $dumpvars(0, image_tb);
 camera_en = 0;
 #2;
 camera_en = 1;
 #1000;
 $finish;
end

always
begin
 clk = ~clk;
 #1;
end
endmodule
module image(
input               clk,
input               camera_en,
output reg          data_valid,
output reg [7:0]    data_out);


parameter N = 450, M = 450;

reg [7:0] mem[3*N*M:0];
integer ptr;

initial
begin
 $readmemh("../res/left.txt", mem);
 ptr <= 0;
end

always @(posedge clk)
begin
 if (camera_en)
 begin
  data_valid <= 1'b1;
  data_out <= mem[ptr];
  ptr <= ptr + 1;
 end
 else
 begin
  data_valid <= 0;
  ptr <= 0;
  data_out <= 8'hzz;
 end
 if (ptr == ((N*M*3) - 1))
 begin
  ptr <= 0;
 end
end
endmodule
module RWM_1(
input           clk,                      // clock
input           rst_n,                    // external asynchronous active low reset
input           RWM_enable,               // to enable or disable the R/W memory. Driven by controller
input           rw,                       // rw = 0: read, rw = 1: write. Driven by controller
input           clear,                    // an active high signal to clear all the contents of the R/W memory. Driven by controller
input           pause,                    // an active high signal that tells the module to pause whatever operation it is doing. Driven by Grayscaler
input [7:0]     data_in,                  // input data bus. Comes from the camera
output [7:0]    data_out,                 // ouput data bus. Connected to Grayscaling module
output          RWM_valid,                // an active high signal indicating the presence of desired data at the output data bus
output reg      RWM_done                  // after the completion of an operation done is set to 1. It is a status signal to drive the controller
);

parameter N = 450, M = 450;

reg [7:0] DATA[0:(3*N*M - 1)];            // RWM register array

reg [2:0] CS, NS;                         // RWM state variables

//RWM states
parameter INACTIVE = 3'b000, READ = 3'b001, WRITE = 3'b010, WAIT = 3'b011, CLEANUP = 3'b100;

integer i, j, k = 0;                      // Loop variable for addressing the RWM register array

// Sequential Logic
always @(posedge clk or negedge rst_n)
begin
  if (~rst_n)
    CS <= INACTIVE;
  else
  begin
   CS <= NS;
   k = (CS == READ) ? k + 1 : 0;
  end
end

always @(posedge clk)
begin
 case (CS)
 INACTIVE: i <= 0;                        // Keep the memory address pointer at 0
 WRITE:
 begin
  DATA[i] <= data_in;                     // Writing into RWM
  i <= (i == 3*N*M - 1) ? 0 : i + 1;
 end
 READ:
 begin                                    // Reading from RWM
  i <= (i == 3*N*M - 1) ? 0 : i + 1;
 end
 WAIT: i <= i;                            // Preserve the address location
 CLEANUP:
 begin
  for(j = 0; j < N*M*3; j = j+1)
  begin
   DATA[j] <= 8'h00;                      // Clearing RWM registers
  end
 end
 endcase
end

// Combinatorial Logic
always @(RWM_enable, rw, i, pause)
begin
  case (CS)
  INACTIVE:
  begin
   RWM_done = 1'b0;
   if (RWM_enable == 1'b0)
    NS = INACTIVE;
   else if (clear == 1'b1)
    NS = CLEANUP;
   else NS = (rw == 1) ? WRITE : READ;
  end
  WRITE:
  begin
   NS = (i == 3*N*M - 1) ? INACTIVE : WRITE;
   RWM_done = (i == 3*N*M - 1) ? 1'b1 : 1'b0;
  end
  READ:
  begin
   if (k == 2 && i != 3*N*M - 1)
    NS = WAIT;
   else NS = (i == 3*N*M - 1) ? INACTIVE : READ;
   RWM_done = (i == 3*N*M - 1) ? 1'b1 : 1'b0;
  end
  WAIT:
  begin
   RWM_done = 1'b0;
   if (k == 3)
    NS = READ;
   else NS = WAIT;
  end
  CLEANUP:
  begin
   NS = (j == 3*N*M - 1) ? INACTIVE : CLEANUP;
   RWM_done = (j == 3*N*M - 1) ? 1'b1 : 1'b0;
  end
  default: NS = INACTIVE;
  endcase
end

assign data_out = (CS == READ) ? DATA[i] : 8'hzz;
assign RWM_valid = (CS == READ) ? 1'b1 : 1'b0;

endmodule
module Grayscaler(
 input          clk,                     //clock
 input          rst_n,                   //external asynchronous active low reset
 input          GS_enable,               //to enable or disable this module. Driven by controller
 input          RWM_valid,               //an active high signal indicating the presence of desired data at the output data bus
 input [7:0]    Din,                     //input data bus. Connected to RWM_1 module
 output [7:0]   Dout,                    //output data bus. Connected to RWM_2 module
 output         GS_valid,                //an active high signal that tells the RWM_2 module that desired data bytes is present in the output data bus
 output         pause,                   //an active high signal that tells the RWM_1 module to pause whatever operation it is doing.
 output reg     GS_done                  //after the completion of an operation done is set to 1. It is a status signal to drive the controller
);

parameter N = 450, M = 450;

reg [7:0] red, green, blue, result;
integer c, d, k=0;

parameter IDLE = 2'b00, FILL = 2'b01, CALCULATE = 2'b10;
reg [1:0] CS, NS;

always @(posedge clk or negedge rst_n)
begin
if(~rst_n)
  CS <= IDLE;
 else
 begin
  CS <= NS;
  k = (RWM_valid) ?  k + 1 : 0;
  d = (k == 2) ? d + 1 : d;
 end
end


always @(*)
begin
 case (CS)
 IDLE:
 begin
  d = 0;
  c = 0;
  red = 8'h00;
  green = 8'h00;
  blue = 8'h00;
  GS_done = 1'b0;
  if(GS_enable)
  begin
   NS = FILL;
  end
  else NS = IDLE;
 end
 FILL:
 begin
  GS_done = 1'b0;
  c = (c != 3) ? c + 1 : 1;
  red = (k == 0) ? Din : red;
  green = (k == 1) ? Din : green;
  blue = (k == 2) ? Din : blue;
  NS = (k == 2) ? CALCULATE : FILL;
 end
 CALCULATE:
 begin
  result = (red>>2) + (red>>5) + (green>>1) + (green>>4) + (blue>>4) + (blue>>5);
  NS = (d == N*M) ? IDLE : FILL;
  GS_done = (d == N*M) ? 1'b1 : 1'b0;
 end
 default: NS = IDLE;
 endcase
end

assign pause = ((CS == FILL) && (c == 3) && (d != N*M)) ? 1'b1 : 1'b0;
assign Dout = (CS == CALCULATE) ? result : 8'hzz;
assign GS_valid = ((CS == FILL) && (k == 2)) ? 1'b1 : 1'b0;

endmodule
module image2(
input               clk,
input               camera_en,
output reg          data_valid,
output reg [7:0]    data_out);


parameter N = 450, M = 450;

reg [7:0] mem[3*N*M:0];
integer ptr;

initial
begin
 $readmemh("../res/right.txt", mem);
 ptr <= 0;
end

always @(posedge clk)
begin
 if (camera_en)
 begin
  data_valid <= 1'b1;
  data_out <= mem[ptr];
  ptr <= ptr + 1;
 end
 else
 begin
  data_valid <= 0;
  ptr <= 0;
  data_out <= 8'hzz;
 end
 if (ptr == ((N*M*3) - 1))
 begin
  ptr <= 0;
 end
end
endmodule
module RWM_2(
input           clk,                      // clock
input           rst_n,                    // external asynchronous active low reset
input           RWM_enable,               // to enable or disable the R/W memory. Driven by controller
input           rw,                       // rw = 0: read, rw = 1: write. Driven by controller
input           clear,                    // an active high signal to clear all the contents of the R/W memory. Driven by controller
input           GS_valid,                 // an active high signal that indicates the presence of desired data bytes in the input data bus. Driven by Grayscaling module
input [7:0]     data_in,                  // input data bus. Comes from the Grayscaling module
output [7:0]    data_out,                 // ouput data bus.
output          RWM_valid,                // an active high signal indicating the presence of desired data at the output data bus
output reg      RWM_done                  // after the completion of an operation done is set to 1. It is a status signal to drive the controller
);

parameter N = 450, M = 450;
//parameter N = 480, M = 320;

reg [7:0] DATA[0:(N*M - 1)];              // RWM register array

reg [2:0] CS, NS;                         // RWM state variables

//RWM states
parameter INACTIVE = 3'b000, READ = 3'b001, WRITE = 3'b010, WAIT = 3'b011, CLEANUP = 3'b100;

integer i, j;                             // Loop variable for addressing the RWM register array

// Sequential Logic
always @(posedge clk or negedge rst_n)
begin
  if (~rst_n)
    CS <= INACTIVE;
  else CS <= NS;
end

always @(posedge clk)
begin
 case (CS)
 INACTIVE: i <= 0;                        // Keep the memory address pointer at 0
 WRITE:
 begin
  DATA[i] <= data_in;                     // Writing into RWM
  i <= (i == N*M - 1) ? 0 : i + 1;
 end
 READ:
 begin                                    // Reading from RWM
  i <= (i == N*M-1) ? 0 : i + 1;
 end
 WAIT: i <= i;                            // Preserve the address location
 CLEANUP:
 begin
  for(j = 0; j < N*M; j = j+1)
  begin
   DATA[j] <= 8'h00;                      // Clearing RWM registers
  end
 end
 endcase
end

// Combinatorial Logic
always @(RWM_enable, rw, i, GS_valid)
begin
  case (CS)
  INACTIVE:
  begin
   RWM_done = 1'b0;
   if (RWM_enable == 1'b0)
    NS = INACTIVE;
   else if (clear == 1'b1)
    NS = CLEANUP;
   else if (rw == 1'b0)
    NS = READ;
   else NS = (GS_valid == 1'b1) ? WRITE : WAIT;
  end
  READ:
  begin
   NS = (i == N*M-1) ? INACTIVE : READ;
   RWM_done = (i == N*M-1) ? 1'b1 : 1'b0;
  end
  WRITE:
  begin
   if ((GS_valid == 1'b0) && (i != N*M - 1))
    NS = WAIT;
   else NS = (i == N*M - 1) ? INACTIVE : WRITE;
   RWM_done = (i == N*M - 1) ? 1'b1 : 1'b0;
  end
  WAIT:
  begin
   RWM_done = 1'b0;
   if (GS_valid == 1'b1)
    NS = WRITE;
   else NS = WAIT;
  end
  CLEANUP:
  begin
   NS = (j == N*M) ? INACTIVE : CLEANUP;
   RWM_done = (j == N*M) ? 1'b1 : 1'b0;
  end
  default: NS = INACTIVE;
  endcase
end

assign data_out = (CS == READ) ? DATA[i] : 8'hzz;
assign RWM_valid = (CS == READ) ? 1'b1 : 1'b0;

endmodule
module display(
input           clk,
input           data_valid,
input [7:0]     data_out);

integer file_id;
initial
begin
 file_id = $fopen("../res/out.txt", "w");
 $fclose(file_id);
end
always @(posedge clk)
begin
 if (data_valid)
 begin
  file_id = $fopen("../res/out.txt", "a");
  $fwrite(file_id, "%h\n", data_out);
  $fclose(file_id);
 end
end
endmodule