dakies/OSS_Verilog huggingface dataset:
module shift_register #(
  parameter gp_data_width = 8,                   // Input & output bit-width
  parameter gp_nr_stages  = 4                    // Number of shift registers
) (
  input  wire                     i_rst_an,      // Asynchronous active low reset
  input  wire                     i_ena,         // Synchronous active high enable
  input  wire                     i_clk,         // Rising-edge clock
  input  wire [gp_data_width-1:0] i_data,        // Input data with p_data_width bits MSB:LSB, signed
  output wire [gp_data_width-1:0] o_data,        // Output data with p_data_width bits MSB:LSB, signed
  output wire                     o_shift_done   // Flag indicates inital shift operation is done 
);
// -------------------------------------------------------------------
  // CONSTANT DECLARATION
  localparam c_cnt_width = $clog2(gp_nr_stages);
  // REGISTER DECLARATION
  reg [c_cnt_width-1:0]                 r_cnt;
  reg                                   r_shift_done; 
  // WIRE DECLARATION
  wire                                  w_shift_done;
  wire [gp_nr_stages*gp_data_width-1:0] w_data;
// -------------------------------------------------------------------  
  
  always @(posedge i_clk or negedge i_rst_an)
    begin: p_count_done
      if (!i_rst_an)
        begin
	  r_cnt        <= 'd0;
	  r_shift_done <= 1'b0;
	end
      else if (i_ena)
        begin
	  if (r_cnt<gp_nr_stages)
	    r_cnt <= r_cnt + 1'b1;
	    
	  if (w_shift_done)
	    r_shift_done <= 1'b1;	    
	end
    end

  genvar i;  
  generate
    for (i=0; i<gp_nr_stages; i=i+1)
      begin: g_shift_register_loop
        if (i==0)
          begin: g_shift_register_0
            dff #(
	    .gp_data_width (gp_data_width)
	    ) REG_COMMUTATOR_INP_DATA  (
	    .i_rst_an (i_rst_an),
	    .i_ena    (i_ena),
	    .i_clk    (i_clk),
	    .i_data   (i_data),
	    .o_data   (w_data[(i+1)*gp_data_width-1 -: gp_data_width])
	    );
          end
        else
          begin: g_shift_register_1_n
            dff #(
	    .gp_data_width (gp_data_width)
	    ) REG_COMMUTATOR_INP_DATA  (
	    .i_rst_an (i_rst_an),
	    .i_ena    (i_ena),
	    .i_clk    (i_clk),
	    .i_data   (w_data[(i)*gp_data_width-1 -: gp_data_width]),
	    .o_data   (w_data[(i+1)*gp_data_width-1 -: gp_data_width])
	    );  	  
          end
        end
  endgenerate
    
assign w_shift_done = (r_cnt == gp_nr_stages) ? 1'b1 : r_shift_done;
assign o_shift_done = w_shift_done;
assign o_data       = w_data[gp_nr_stages*gp_data_width-1 -: gp_data_width];  

endmodule
module shift_register #(
  parameter gp_data_width = 8,                   // Input & output bit-width
  parameter gp_nr_stages  = 4                    // Number of shift registers
) (
  input  wire                     i_rst_an,      // Asynchronous active low reset
  input  wire                     i_ena,         // Synchronous active high enable
  input  wire                     i_clk,         // Rising-edge clock
  input  wire [gp_data_width-1:0] i_data,        // Input data with p_data_width bits MSB:LSB, signed
  output wire [gp_data_width-1:0] o_data,        // Output data with p_data_width bits MSB:LSB, signed
  output wire                     o_shift_done   // Flag indicates inital shift operation is done 
);
// -------------------------------------------------------------------
  // CONSTANT DECLARATION
  localparam c_cnt_width = $clog2(gp_nr_stages);
  // REGISTER DECLARATION
  reg [c_cnt_width-1:0]                 r_cnt;
  reg                                   r_shift_done; 
  // WIRE DECLARATION
  wire                                  w_shift_done;
  wire [gp_nr_stages*gp_data_width-1:0] w_data;
// -------------------------------------------------------------------  
  genvar i;  
  generate
    for (i=0; i<gp_nr_stages; i=i+1)
      begin: g_shift_register
        if (i==0)
          begin: g_shift_register_0
            dff #(
	    .gp_data_width (gp_data_width)
	    ) REG_COMMUTATOR_INP_DATA  (
	    .i_rst_an (i_rst_an),
	    .i_ena    (i_ena),
	    .i_clk    (i_clk),
	    .i_data   (i_data),
	    .o_data   (w_data[(i+1)*gp_data_width-1 -: gp_data_width])
	    );
          end
        else
          begin: g_shift_register_1_n
            dff #(
	    .gp_data_width (gp_data_width)
	    ) REG_COMMUTATOR_INP_DATA  (
	    .i_rst_an (i_rst_an),
	    .i_ena    (i_ena),
	    .i_clk    (i_clk),
	    .i_data   (w_data[(i)*gp_data_width-1 -: gp_data_width]),
	    .o_data   (w_data[(i+1)*gp_data_width-1 -: gp_data_width])
	    );  	  
          end
        end
  endgenerate
  
  always @(posedge i_clk or negedge i_rst_an)
    begin: p_count_done
      if (!i_rst_an)
        begin
	  r_cnt        <= 'd0;
	  r_shift_done <= 1'b0;
	end
      else if (i_ena)
        begin
	  if (r_cnt<gp_nr_stages)
	    r_cnt <= r_cnt + 1'b1;
	    
	  if (w_shift_done)
	    r_shift_done <= 1'b1;	    
	end
    end
    
assign w_shift_done = (r_cnt == gp_nr_stages) ? 1'b1 : r_shift_done;
assign o_shift_done = w_shift_done;
assign o_data       = w_data[gp_nr_stages*gp_data_width-1 -: gp_data_width];  

endmodule
module CPU_TEST;
  
  /* CPU Signals */
  reg RESET;
  reg CLOCK;
  
  /* Connect CPU to Instruction Memory */
  wire [63:0] PC_wire;
  wire [31:0] IC_wire;
  
  /* Connect CPU to Data Memory */
  wire [63:0] mem_address;
  wire [63:0] mem_data_in;
  wire control_memwrite;
  wire control_memread;
  wire [63:0] mem_data_out;
  
  ARM_CPU core (RESET, CLOCK, IC_wire, mem_data_out, PC_wire, mem_address, mem_data_in, control_memwrite, control_memread);
  IC mem1 (PC_wire, IC_wire);
  Data_Memory mem2 (mem_address, mem_data_in, control_memwrite, control_memread, mem_data_out);
  
  /* Setup the clock */
  initial begin
    CLOCK = 1'b0;
    RESET = 1'b1;
    #30 $finish;
  end
  
  /* Toggle the clock */
  always begin
    #1 CLOCK = ~CLOCK; RESET = 1'b0;
  end
  
endmodule
module ForwardingUnit
(
	input [4:0] EX_Rn_in,
	input [4:0] EX_Rm_in,
	input [4:0] MEM_Rd_in,
	input [4:0] WB_Rd_in,
	input MEM_regwrite_in,
	input WB_regwrite_in,
	output reg [1:0] A_out,
	output reg [1:0] B_out
);
  always @(*) begin
		if ((WB_regwrite_in == 1'b1) &&
				(WB_Rd_in !== 31) &&
			/*	(!((MEM_regwrite_in == 1'b1) && (MEM_Rd_in !== 31) && (MEM_Rd_in !== EX_Rn_in))) && */
				(WB_Rd_in === EX_Rn_in)) begin
			A_out <= 2'b01;
		end else if ((MEM_regwrite_in == 1'b1) &&
				(MEM_Rd_in !== 31) &&
				(MEM_Rd_in === EX_Rn_in)) begin
			A_out <= 2'b10;
		end else begin
			A_out <= 2'b00;
		end

		if ((WB_regwrite_in == 1'b1) &&
				(WB_Rd_in !== 31) &&
			/*	(!((MEM_regwrite_in == 1'b1) && (MEM_Rd_in !== 31) && (MEM_Rd_in !== EX_Rm_in))) && */
				(WB_Rd_in === EX_Rm_in)) begin
			B_out <= 2'b01;
		end else if ((MEM_regwrite_in == 1'b1) &&
				(MEM_Rd_in !== 31) &&
				(MEM_Rd_in === EX_Rm_in)) begin
			B_out <= 2'b10;
		end else begin
			B_out <= 2'b00;
		end
  end
endmodule
module HazardDetection
(
	input EX_memRead_in,
	input [4:0] EX_write_reg,
	input [63:0] ID_PC,
	input [31:0] ID_IC,
	output reg IFID_write_out,
	output reg PC_Write_out,
	output reg Control_mux_out
);
	always @(*) begin
		if (EX_memRead_in == 1'b1 && ((EX_write_reg === ID_IC[9:5]) || (EX_write_reg === ID_IC[20:16]))) begin
			IFID_write_out <= 1'b1;
			PC_Write_out <= 1'b1;
			Control_mux_out <= 1'b1;

		end else begin
			IFID_write_out <= 1'b0;
			PC_Write_out <= 1'b0;
			Control_mux_out <= 1'b0;
		end

	end
endmodule
module IFID
(
  input CLOCK,
  input [63:0] PC_in,
  input [31:0] IC_in,
  input Hazard_in,
  output reg [63:0] PC_out,
  output reg [31:0] IC_out
);
	always @(negedge CLOCK) begin
		if (Hazard_in !== 1'b1) begin
			PC_out <= PC_in;
			IC_out <= IC_in;
		end
  end
endmodule
module IDEX
(
  input CLOCK,
  input [1:0] aluop_in,
  input alusrc_in,
  input isZeroBranch_in,
  input isUnconBranch_in,
  input memRead_in,
  input memwrite_in,
  input regwrite_in,
  input mem2reg_in,
  input [63:0] PC_in,
  input [63:0] regdata1_in,
  input [63:0] regdata2_in,
  input [63:0] sign_extend_in,
  input [10:0] alu_control_in,
  input [4:0] write_reg_in,
  input [4:0] forward_reg_1_in,		// Forwarding
  input [4:0] forward_reg_2_in,		// Forwarding
  output reg [1:0] aluop_out,
  output reg alusrc_out,
  output reg isZeroBranch_out,
  output reg isUnconBranch_out,
  output reg memRead_out,
  output reg memwrite_out,
  output reg regwrite_out,
  output reg mem2reg_out,
  output reg [63:0] PC_out,
  output reg [63:0] regdata1_out,
  output reg [63:0] regdata2_out,
  output reg [63:0] sign_extend_out,
  output reg [10:0] alu_control_out,
  output reg [4:0] write_reg_out,
  output reg [4:0] forward_reg_1_out,		// Forwarding
  output reg [4:0] forward_reg_2_out		// Forwarding
);
  always @(negedge CLOCK) begin
    /* Values for EX */
    aluop_out <= aluop_in;
	  alusrc_out <= alusrc_in;

    /* Values for M */
  	isZeroBranch_out <= isZeroBranch_in;
    isUnconBranch_out <= isUnconBranch_in;
  	memRead_out <= memRead_in;
 	  memwrite_out <= memwrite_in;

    /* Values for WB */
    regwrite_out <= regwrite_in;
  	mem2reg_out <= mem2reg_in;

    /* Values for all Stages */
    PC_out <= PC_in;
    regdata1_out <= regdata1_in;
    regdata2_out <= regdata2_in;

    /* Values for variable stages */
    sign_extend_out <= sign_extend_in;
  	alu_control_out <= alu_control_in;
  	write_reg_out <= write_reg_in;
	  forward_reg_1_out <= forward_reg_1_in;
	  forward_reg_2_out <= forward_reg_2_in;
  end
endmodule
module EXMEM
(
  input CLOCK,
  input isZeroBranch_in, 	// M Stage
  input isUnconBranch_in, 	// M Stage
  input memRead_in, 		// M Stage
  input memwrite_in, 		// M Stage
  input regwrite_in, 		// WB Stage
  input mem2reg_in, 		// WB Stage
  input [63:0] shifted_PC_in,
  input alu_zero_in,
  input [63:0] alu_result_in,
  input [63:0] write_data_mem_in,
  input [4:0] write_reg_in,
  output reg isZeroBranch_out, 	// M Stage
  output reg isUnconBranch_out, // M Stage
  output reg memRead_out, 		// M Stage
  output reg memwrite_out, 		// M Stage
  output reg regwrite_out,		// WB Stage
  output reg mem2reg_out,		// WB Stage
  output reg [63:0] shifted_PC_out,
  output reg alu_zero_out,
  output reg [63:0] alu_result_out,
  output reg [63:0] write_data_mem_out,
  output reg [4:0] write_reg_out
);
	always @(negedge CLOCK) begin
		/* Values for M */
		isZeroBranch_out <= isZeroBranch_in;
		isUnconBranch_out <= isUnconBranch_in;
		memRead_out <= memRead_in;
		memwrite_out <= memwrite_in;

		/* Values for WB */
		regwrite_out <= regwrite_in;
		mem2reg_out <= mem2reg_in;

		/* Values for all Stages */
		shifted_PC_out <= shifted_PC_in;
		alu_zero_out <= alu_zero_in;
		alu_result_out <= alu_result_in;
		write_data_mem_out <= write_data_mem_in;
		write_reg_out <= write_reg_in;
	end
endmodule
module MEMWB
(
  input CLOCK,
  input [63:0] mem_address_in,
  input [63:0] mem_data_in,
  input [4:0] write_reg_in,
  input regwrite_in,
  input mem2reg_in,
  output reg [63:0] mem_address_out,
  output reg [63:0] mem_data_out,
  output reg [4:0] write_reg_out,
  output reg regwrite_out,
  output reg mem2reg_out
);
  always @(negedge CLOCK) begin
    regwrite_out <= regwrite_in;
    mem2reg_out <= mem2reg_in;
    mem_address_out <= mem_address_in;
    mem_data_out <= mem_data_in;
    write_reg_out <= write_reg_in;
  end
endmodule
module Registers
(
  input CLOCK,
  input [4:0] read1,
  input [4:0] read2,
  input [4:0] writeReg,
  input [63:0] writeData,
  input CONTROL_REGWRITE,
  output reg [63:0] data1,
  output reg [63:0] data2
);
  reg [63:0] Data[31:0];
  integer initCount;

  initial begin
    for (initCount = 0; initCount < 31; initCount = initCount + 1) begin
      Data[initCount] = initCount;
    end

    Data[31] = 64'h00000000;
  end

  always @(posedge CLOCK) begin
    if (CONTROL_REGWRITE == 1'b1) begin
      Data[writeReg] = writeData;
    end

    data1 = Data[read1];
    data2 = Data[read2];

    // Debug use only
    for (initCount = 0; initCount < 32; initCount = initCount + 1) begin
      $display("REGISTER[%0d] = %0d", initCount, Data[initCount]);
    end
  end
endmodule
module IC
(
  input [63:0] PC_in,
  output reg [31:0] instruction_out
);

  reg [8:0] Data[63:0];

  initial begin
    // LDUR x0, [x2, #3]
    Data[0] = 8'hf8; Data[1] = 8'h40; Data[2] = 8'h30; Data[3] = 8'h40;

    // ADD x9, x0, x5
    Data[4] = 8'h8b; Data[5] = 8'h05; Data[6] = 8'h00; Data[7] = 8'h09;

    // ORR x10, x1, x9
    Data[8] = 8'haa; Data[9] = 8'h09; Data[10] = 8'h00; Data[11] = 8'h2a;

    // AND x11, x9, x0
    Data[12] = 8'h8a; Data[13] = 8'h00; Data[14] = 8'h01; Data[15] = 8'h2b;

    // SUB x12 x0 x11
    Data[16] = 8'hcb; Data[17] = 8'h0b; Data[18] = 8'h00; Data[19] = 8'h0c;

    // STUR x9, [x3, #6]
    Data[20] = 8'hf8; Data[21] = 8'h00; Data[22] = 8'h60; Data[23] = 8'h69;

    // STUR x10, [x4, #6]
    Data[24] = 8'hf8; Data[25] = 8'h00; Data[26] = 8'h60; Data[27] = 8'h8a;

    // STUR x11, [x5, #6]
    Data[28] = 8'hf8; Data[29] = 8'h00; Data[30] = 8'h60; Data[31] = 8'hab;

    // STUR x12, [x6, #6]
    Data[32] = 8'hf8; Data[33] = 8'h00; Data[34] = 8'h60; Data[35] = 8'hcc;

    // B #10
    Data[36] = 8'h14; Data[37] = 8'h00; Data[38] = 8'h00; Data[39] = 8'h0a;
  end

  always @(PC_in) begin
    instruction_out[8:0] = Data[PC_in + 3];
    instruction_out[16:8] = Data[PC_in + 2];
    instruction_out[24:16] = Data[PC_in + 1];
    instruction_out[31:24] = Data[PC_in];
  end
endmodule
module Data_Memory
(
  input [63:0] inputAddress,
  input [63:0] inputData,
  input CONTROL_MemWrite,
  input CONTROL_MemRead,
  output reg [63:0] outputData
);
	reg [63:0] Data[31:0];
	integer initCount;

	initial begin
		for (initCount = 0; initCount < 32; initCount = initCount + 1) begin
			Data[initCount] = initCount * 5;
		end
	end
	always @(*) begin
		if (CONTROL_MemWrite == 1'b1) begin
        Data[inputAddress] = inputData;
      end else if (CONTROL_MemRead == 1'b1) begin
        outputData = Data[inputAddress];
      end else begin
        outputData = 64'hxxxxxxxx;
      end

      // Debug use only
        for (initCount = 0; initCount < 32; initCount = initCount + 1) begin
            $display("RAM[%0d] = %0d", initCount, Data[initCount]);
        end

    end
endmodule
module ALU
(
  input [63:0] A,
  input [63:0] B,
  input [3:0] CONTROL,
  output reg [63:0] RESULT,
  output reg ZEROFLAG
);
  always @(*) begin
    case (CONTROL)
      4'b0000 : RESULT = A & B;
      4'b0001 : RESULT = A | B;
      4'b0010 : RESULT = A + B;
      4'b0110 : RESULT = A - B;
      4'b0111 : RESULT = B;
      4'b1100 : RESULT = ~(A | B);
      default : RESULT = 64'hxxxxxxxx;
    endcase

    if (RESULT == 0) begin
      ZEROFLAG = 1'b1;
    end else if (RESULT != 0) begin
      ZEROFLAG = 1'b0;
    end else begin
      ZEROFLAG = 1'bx;
    end
  end
endmodule
module ALU_Control
(
  input [1:0] ALU_Op,
  input [10:0] ALU_INSTRUCTION,
  output reg [3:0] ALU_Out
);
  always @(ALU_Op or ALU_INSTRUCTION) begin
    case (ALU_Op)
      2'b00 : ALU_Out <= 4'b0010;
      2'b01 : ALU_Out <= 4'b0111;
      2'b10 : begin

        case (ALU_INSTRUCTION)
          11'b10001011000 : ALU_Out <= 4'b0010; // ADD
          11'b11001011000 : ALU_Out <= 4'b0110; // SUB
          11'b10001010000 : ALU_Out <= 4'b0000; // AND
          11'b10101010000 : ALU_Out <= 4'b0001; // ORR
        endcase
      end
      default : ALU_Out = 4'bxxxx;
    endcase
  end
endmodule
module Control_Mux
(
  input [1:0] CONTROL_aluop_in,
  input CONTROL_alusrc_in,
  input CONTROL_isZeroBranch_in,
  input CONTROL_isUnconBranch_in,
  input CONTROL_memRead_in,
  input CONTROL_memwrite_in,
  input CONTROL_regwrite_in,
  input CONTROL_mem2reg_in,
  input mux_control_in,
  output reg [1:0] CONTROL_aluop_out,
  output reg CONTROL_alusrc_out,
  output reg CONTROL_isZeroBranch_out,
  output reg CONTROL_isUnconBranch_out,
  output reg CONTROL_memRead_out,
  output reg CONTROL_memwrite_out,
  output reg CONTROL_regwrite_out,
  output reg CONTROL_mem2reg_out
);
	always @(*) begin
		if (mux_control_in === 1'b1) begin
		  CONTROL_aluop_out <= 2'b00;
		  CONTROL_alusrc_out <= 1'b0;
		  CONTROL_isZeroBranch_out <= 1'b0;
		  CONTROL_isUnconBranch_out <= 1'b0;
		  CONTROL_memRead_out <= 1'b0;
		  CONTROL_memwrite_out <= 1'b0;
		  CONTROL_regwrite_out <= 1'b0;
		  CONTROL_mem2reg_out <= 1'b0;
		end else begin
		  CONTROL_aluop_out <= CONTROL_aluop_in;
		  CONTROL_alusrc_out <= CONTROL_alusrc_in;
		  CONTROL_isZeroBranch_out <= CONTROL_isZeroBranch_in;
		  CONTROL_isUnconBranch_out <= CONTROL_isUnconBranch_in;
		  CONTROL_memRead_out <= CONTROL_memRead_in;
		  CONTROL_memwrite_out <= CONTROL_memwrite_in;
		  CONTROL_regwrite_out <= CONTROL_regwrite_in;
		  CONTROL_mem2reg_out <= CONTROL_mem2reg_in;
		end
	end
endmodule
module Forward_ALU_Mux
(
  input [63:0] reg_ex_in,
  input [63:0] reg_wb_in,
  input [63:0] reg_mem_in,
  input [1:0] forward_control_in,
  output reg [63:0] reg_out
);
	always @(*) begin
		case (forward_control_in)
        2'b01 : reg_out <= reg_wb_in;
        2'b10 : reg_out <= reg_mem_in;
        default : reg_out <= reg_ex_in;
      endcase
	end
endmodule
module ALU_Mux
(
  input [63:0] input1,
  input [63:0] input2,
  input CONTROL_ALUSRC,
  output reg [63:0] out
);
  always @(input1, input2, CONTROL_ALUSRC, out) begin
    if (CONTROL_ALUSRC === 0) begin
      out <= input1;
    end

    else begin
      out <= input2;
    end
  end
endmodule
module ID_Mux
(
  input [4:0] read1_in,
  input [4:0] read2_in,
  input reg2loc_in,
  output reg [4:0] reg_out
);
  always @(read1_in, read2_in, reg2loc_in) begin
    case (reg2loc_in)
        1'b0 : begin
            reg_out <= read1_in;
        end
        1'b1 : begin
            reg_out <= read2_in;
        end
        default : begin
            reg_out <= 1'bx;
        end
    endcase
  end
endmodule
module WB_Mux
(
  input [63:0] input1,
  input [63:0] input2,
  input mem2reg_control,
  output reg [63:0] out
);
  always @(*) begin
    if (mem2reg_control == 0) begin
      out <= input1;
    end

    else begin
      out <= input2;
    end
  end
endmodule
module Shift_Left
(
  input [63:0] data_in,
  output reg [63:0] data_out
);
  always @(data_in) begin
    data_out <= data_in << 2;
  end
endmodule
module SignExtend
(
  input [31:0] inputInstruction,
  output reg [63:0] outImmediate
);
  always @(inputInstruction) begin
    if (inputInstruction[31:26] == 6'b000101) begin // B
        outImmediate[25:0] = inputInstruction[25:0];
        outImmediate[63:26] = {64{outImmediate[25]}};

    end else if (inputInstruction[31:24] == 8'b10110100) begin // CBZ
        outImmediate[19:0] = inputInstruction[23:5];
        outImmediate[63:20] = {64{outImmediate[19]}};

    end else begin // D Type, ignored if R type
        outImmediate[9:0] = inputInstruction[20:12];
        outImmediate[63:10] = {64{outImmediate[9]}};
    end
  end
endmodule
module Branch
(
  input unconditional_branch_in,
  input conditional_branch_in,
  input alu_main_is_zero,
  output reg PC_src_out
);

	reg conditional_branch_temp;

  always @(unconditional_branch_in, conditional_branch_in, alu_main_is_zero) begin
    conditional_branch_temp <= conditional_branch_in & alu_main_is_zero;
    PC_src_out <= unconditional_branch_in | conditional_branch_temp;
  end
endmodule
module ARM_Control
(
  input [10:0] instruction,
  output reg [1:0] control_aluop,
  output reg control_alusrc,
  output reg control_isZeroBranch,
  output reg control_isUnconBranch,
  output reg control_memRead,
  output reg control_memwrite,
  output reg control_regwrite,
  output reg control_mem2reg
);

  always @(instruction) begin
    if (instruction[10:5] == 6'b000101) begin // B
      control_mem2reg <= 1'bx;
      control_memRead <= 1'b0;
      control_memwrite <= 1'b0;
      control_alusrc <= 1'b0;
      control_aluop <= 2'b01;
      control_isZeroBranch <= 1'b0;
      control_isUnconBranch <= 1'b1;
      control_regwrite <= 1'b0;

    end else if (instruction[10:3] == 8'b10110100) begin // CBZ
      control_mem2reg <= 1'bx;
      control_memRead <= 1'b0;
      control_memwrite <= 1'b0;
      control_alusrc <= 1'b0;
      control_aluop <= 2'b01;
      control_isZeroBranch <= 1'b1;
      control_isUnconBranch <= 1'b0;
      control_regwrite <= 1'b0;

    end else begin // R-Type Instructions
      control_isZeroBranch <= 1'b0;
      control_isUnconBranch <= 1'b0;

      case (instruction[10:0])
        11'b11111000010 : begin // LDUR
          control_mem2reg <= 1'b1;
          control_memRead <= 1'b1;
          control_memwrite <= 1'b0;
          control_alusrc <= 1'b1;
          control_aluop <= 2'b00;
          control_regwrite <= 1'b1;
        end

        11'b11111000000 : begin // STUR
          control_mem2reg <= 1'bx;
          control_memRead <= 1'b0;
          control_memwrite <= 1'b1;
          control_alusrc <= 1'b1;
          control_aluop <= 2'b00;
          control_regwrite <= 1'b0;
        end

        11'b10001011000 : begin // ADD
          control_mem2reg <= 1'b0;
          control_memRead <= 1'b0;
          control_memwrite <= 1'b0;
          control_alusrc <= 1'b0;
          control_aluop <= 2'b10;
          control_regwrite <= 1'b1;
        end

        11'b11001011000 : begin // SUB
          control_mem2reg <= 1'b0;
          control_memRead <= 1'b0;
          control_memwrite <= 1'b0;
          control_alusrc <= 1'b0;
          control_aluop <= 2'b10;
          control_regwrite <= 1'b1;
        end

        11'b10001010000 : begin // AND
          control_mem2reg <= 1'b0;
          control_memRead <= 1'b0;
          control_memwrite <= 1'b0;
          control_alusrc <= 1'b0;
          control_aluop <= 2'b10;
          control_regwrite <= 1'b1;
        end

        11'b10101010000 : begin // ORR
          control_mem2reg <= 1'b0;
          control_memRead <= 1'b0;
          control_memwrite <= 1'b0;
          control_alusrc <= 1'b0;
          control_aluop <= 2'b10;
          control_regwrite <= 1'b1;
        end

        default : begin // NOP
          control_isZeroBranch <= 1'bx;
      	 control_isUnconBranch <= 1'bx;
          control_mem2reg <= 1'bx;
          control_memRead <= 1'bx;
          control_memwrite <= 1'bx;
          control_alusrc <= 1'bx;
          control_aluop <= 2'bxx;
          control_regwrite <= 1'bx;
        end
      endcase
    end
  end
endmodule
module CPU_TEST;

  /* CPU Signals */
  reg RESET;
  reg CLOCK;

  /* Connect CPU to Instruction Memory */
  wire [63:0] PC_wire;
  wire [31:0] IC_wire;

  /* Connect CPU to Data Memory */
  wire [63:0] mem_address;
  wire [63:0] mem_data_in;
  wire control_memwrite;
  wire control_memread;
  wire [63:0] mem_data_out;

  ARM_CPU core (RESET, CLOCK, IC_wire, mem_data_out, PC_wire, mem_address, mem_data_in, control_memwrite, control_memread);
  IC mem1 (PC_wire, IC_wire);
  Data_Memory mem2 (mem_address, mem_data_in, control_memwrite, control_memread, mem_data_out);

  /* Setup the clock */
  initial begin
    CLOCK = 1'b0;
    RESET = 1'b1;
    #18 $finish;
  end

  /* Toggle the clock */
  always begin
    #1 CLOCK = ~CLOCK; RESET = 1'b0;
  end
endmodule
module IFID
(
  input CLOCK,
  input [63:0] PC_in,
  input [31:0] IC_in,
  output reg [63:0] PC_out,
  output reg [31:0] IC_out
);

  always @(negedge CLOCK) begin
    PC_out <= PC_in;
    IC_out <= IC_in;
  end
endmodule
module IDEX
(
  input CLOCK,
  input [1:0] aluop_in, 	       // EX Stage
  input alusrc_in, 			         // EX Stage
  input isZeroBranch_in, 	       // M Stage
  input isUnconBranch_in, 	     // M Stage
  input memRead_in, 		         // M Stage
  input memwrite_in, 		         // M Stage
  input regwrite_in, 		         // WB Stage
  input mem2reg_in, 		         // WB Stage
  input [63:0] PC_in,
  input [63:0] regdata1_in,
  input [63:0] regdata2_in,
  input [63:0] sign_extend_in,
  input [10:0] alu_control_in,
  input [4:0] write_reg_in,
  output reg [1:0] aluop_out, 	// EX Stage
  output reg alusrc_out, 		    // EX Stage
  output reg isZeroBranch_out, 	// M Stage
  output reg isUnconBranch_out, // M Stage
  output reg memRead_out, 		  // M Stage
  output reg memwrite_out, 		  // M Stage
  output reg regwrite_out,		  // WB Stage
  output reg mem2reg_out,		    // WB Stage
  output reg [63:0] PC_out,
  output reg [63:0] regdata1_out,
  output reg [63:0] regdata2_out,
  output reg [63:0] sign_extend_out,
  output reg [10:0] alu_control_out,
  output reg [4:0] write_reg_out
);

  always @(negedge CLOCK) begin
    /* Values for EX */
    aluop_out <= aluop_in;
    alusrc_out <= alusrc_in;

    /* Values for M */
  	isZeroBranch_out <= isZeroBranch_in;
    isUnconBranch_out <= isUnconBranch_in;
  	memRead_out <= memRead_in;
 	  memwrite_out <= memwrite_in;

    /* Values for WB */
    regwrite_out <= regwrite_in;
  	mem2reg_out <= mem2reg_in;

    /* Values for all Stages */
    PC_out <= PC_in;
    regdata1_out <= regdata1_in;
    regdata2_out <= regdata2_in;

    /* Values for variable stages */
    sign_extend_out <= sign_extend_in;
  	alu_control_out <= alu_control_in;
  	write_reg_out <= write_reg_in;
  end
endmodule
module EXMEM
(
  input CLOCK,
  input isZeroBranch_in, 	// M Stage
  input isUnconBranch_in, 	// M Stage
  input memRead_in, 		// M Stage
  input memwrite_in, 		// M Stage
  input regwrite_in, 		// WB Stage
  input mem2reg_in, 		// WB Stage
  input [63:0] shifted_PC_in,
  input alu_zero_in,
  input [63:0] alu_result_in,
  input [63:0] write_data_mem_in,
  input [4:0] write_reg_in,
  output reg isZeroBranch_out, 	// M Stage
  output reg isUnconBranch_out, // M Stage
  output reg memRead_out, 		// M Stage
  output reg memwrite_out, 		// M Stage
  output reg regwrite_out,		// WB Stage
  output reg mem2reg_out,		// WB Stage
  output reg [63:0] shifted_PC_out,
  output reg alu_zero_out,
  output reg [63:0] alu_result_out,
  output reg [63:0] write_data_mem_out,
  output reg [4:0] write_reg_out
);

  always @(negedge CLOCK) begin
    /* Values for M */
  	isZeroBranch_out <= isZeroBranch_in;
    isUnconBranch_out <= isUnconBranch_in;
  	memRead_out <= memRead_in;
 	memwrite_out <= memwrite_in;

    /* Values for WB */
    regwrite_out <= regwrite_in;
  	mem2reg_out <= mem2reg_in;

    /* Values for all Stages */
    shifted_PC_out <= shifted_PC_in;
    alu_zero_out <= alu_zero_in;
    alu_result_out <= alu_result_in;
    write_data_mem_out <= write_data_mem_in;
  write_reg_out <= write_reg_in;
  end
endmodule
module MEMWB
(
  input CLOCK,
  input [63:0] mem_address_in,
  input [63:0] mem_data_in,
  input [4:0] write_reg_in,
  input regwrite_in,
  input mem2reg_in,
  output reg [63:0] mem_address_out,
  output reg [63:0] mem_data_out,
  output reg [4:0] write_reg_out,
  output reg regwrite_out,
  output reg mem2reg_out
);

  always @(negedge CLOCK) begin
    regwrite_out <= regwrite_in;
    mem2reg_out <= mem2reg_in;
    mem_address_out <= mem_address_in;
    mem_data_out <= mem_data_in;
    write_reg_out <= write_reg_in;
  end
endmodule
module Registers
(
  input CLOCK,
  input [4:0] read1,
  input [4:0] read2,
  input [4:0] writeReg,
  input [63:0] writeData,
  input CONTROL_REGWRITE,
  output reg [63:0] data1,
  output reg [63:0] data2
);

  reg [63:0] Data[31:0];

  integer initCount;

  initial begin
    for (initCount = 0; initCount < 31; initCount = initCount + 1) begin
      Data[initCount] = initCount;
    end

    Data[31] = 64'h00000000;
  end

  always @(posedge CLOCK) begin

    data1 = Data[read1];
    data2 = Data[read2];

    if (CONTROL_REGWRITE == 1'b1) begin
      Data[writeReg] = writeData;
    end

    // Debug use only
    for (initCount = 0; initCount < 32; initCount = initCount + 1) begin
      $display("REGISTER[%0d] = %0d", initCount, Data[initCount]);
    end
  end
endmodule
module IC
(
  input [63:0] PC_in,
  output reg [31:0] instruction_out
);

  reg [8:0] Data[63:0];

  initial begin
    // CBZ x31 #5 (Set PC = (5*4) = 20)
   /*
    Data[0] = 8'hb4;
    Data[1] = 8'h00;
    Data[2] = 8'h00;
    Data[3] = 8'hbf;
    /*

    // B #1 (Set PC = (1*4) = 8)
   /*
    Data[0] = 8'h14;
    Data[1] = 8'h00;
    Data[2] = 8'h00;
    Data[3] = 8'h01;
    */

  	// LDUR x2, [x9, #1]
    Data[0] = 8'hf8;
    Data[1] = 8'h40;
    Data[2] = 8'h11;
    Data[3] = 8'h22;

    // ADD x3, x10, x5
    Data[4] = 8'h8b;
    Data[5] = 8'h05;
    Data[6] = 8'h01;
    Data[7] = 8'h43;

    // SUB x4, x10, x5
    Data[8] = 8'hcb;
    Data[9] = 8'h05;
    Data[10] = 8'h01;
    Data[11] = 8'h44;

    // ORR x5, x30, x10
    Data[12] = 8'haa;
    Data[13] = 8'h0a;
    Data[14] = 8'h03;
    Data[15] = 8'hc5;

    // AND x6, x30, x10
    Data[16] = 8'h8a;
    Data[17] = 8'h0a;
    Data[18] = 8'h03;
    Data[19] = 8'hc6;

    // STUR x2, [x31]
    Data[20] = 8'hf8;
    Data[21] = 8'h00;
    Data[22] = 8'h03;
    Data[23] = 8'he2;

  end

  always @(PC_in) begin
    instruction_out[8:0] = Data[PC_in + 3];
    instruction_out[16:8] = Data[PC_in + 2];
    instruction_out[24:16] = Data[PC_in + 1];
    instruction_out[31:24] = Data[PC_in];
  end
endmodule
module Data_Memory
(
  input [63:0] inputAddress,
  input [63:0] inputData,
  input CONTROL_MemWrite,
  input CONTROL_MemRead,
  output reg [63:0] outputData
);

  reg [63:0] Data[31:0];

  integer initCount;

  initial begin
    for (initCount = 0; initCount < 32; initCount = initCount + 1) begin
      Data[initCount] = initCount * 100;
    end

   Data[10] = 1540;
   Data[11] = 2117;
  end

    always @(*) begin
      if (CONTROL_MemWrite == 1'b1) begin
        Data[inputAddress] = inputData;
      end else if (CONTROL_MemRead == 1'b1) begin
        outputData = Data[inputAddress];
      end else begin
        outputData = 64'hxxxxxxxx;
      end

      // Debug use only
      for (initCount = 0; initCount < 32; initCount = initCount + 1) begin
        $display("RAM[%0d] = %0d", initCount, Data[initCount]);
      end
    end
endmodule
module ALU
(
  input [63:0] A,
  input [63:0] B,
  input [3:0] CONTROL,
  output reg [63:0] RESULT,
  output reg ZEROFLAG
);

  always @(*) begin
    case (CONTROL)
      4'b0000 : RESULT = A & B;
      4'b0001 : RESULT = A | B;
      4'b0010 : RESULT = A + B;
      4'b0110 : RESULT = A - B;
      4'b0111 : RESULT = B;
      4'b1100 : RESULT = ~(A | B);
      default : RESULT = 64'hxxxxxxxx;
    endcase

    if (RESULT == 0) begin
      ZEROFLAG = 1'b1;
    end else if (RESULT != 0) begin
      ZEROFLAG = 1'b0;
    end else begin
      ZEROFLAG = 1'bx;
    end
  end
endmodule
module ALU_Control
(
  input [1:0] ALU_Op,
  input [10:0] ALU_INSTRUCTION,
  output reg [3:0] ALU_Out
);

  always @(ALU_Op or ALU_INSTRUCTION) begin
    case (ALU_Op)
      2'b00 : ALU_Out = 4'b0010;
      2'b01 : ALU_Out = 4'b0111;
      2'b10 : begin

        case (ALU_INSTRUCTION)
          11'b10001011000 : ALU_Out = 4'b0010; // ADD
          11'b11001011000 : ALU_Out = 4'b0110; // SUB
          11'b10001010000 : ALU_Out = 4'b0000; // AND
          11'b10101010000 : ALU_Out = 4'b0001; // ORR
        endcase
      end
      default : ALU_Out = 4'bxxxx;
    endcase
  end
endmodule
module ALU_Mux
(
  input [63:0] input1,
  input [63:0] input2,
  input CONTROL_ALUSRC,
  output reg [63:0] out
);

  always @(input1, input2, CONTROL_ALUSRC, out) begin
    if (CONTROL_ALUSRC == 0) begin
      out <= input1;
    end

    else begin
      out <= input2;
    end
  end
endmodule
module ID_Mux
(
  input [4:0] read1_in,
  input [4:0] read2_in,
  input reg2loc_in,
  output reg [4:0] reg_out
);

  always @(read1_in, read2_in, reg2loc_in) begin
    case (reg2loc_in)
        1'b0 : begin
            reg_out <= read1_in;
        end
        1'b1 : begin
            reg_out <= read2_in;
        end
        default : begin
            reg_out <= 1'bx;
        end
    endcase
  end
endmodule
module WB_Mux
(
  input [63:0] input1,
  input [63:0] input2,
  input mem2reg_control,
  output reg [63:0] out
);

  always @(*) begin
    if (mem2reg_control == 0) begin
      out <= input1;
    end

    else begin
      out <= input2;
    end
  end
endmodule
module Shift_Left
(
  input [63:0] data_in,
  output reg [63:0] data_out
);

  always @(data_in) begin
    data_out = data_in << 2;
  end
endmodule
module SignExtend
(
  input [31:0] inputInstruction,
  output reg [63:0] outImmediate
);

  always @(inputInstruction) begin
    if (inputInstruction[31:26] == 6'b000101) begin // B
      outImmediate[25:0] = inputInstruction[25:0];
      outImmediate[63:26] = {64{outImmediate[25]}};

    end else if (inputInstruction[31:24] == 8'b10110100) begin // CBZ
      outImmediate[19:0] = inputInstruction[23:5];
      outImmediate[63:20] = {64{outImmediate[19]}};

    end else begin // D Type, ignored if R type
      outImmediate[9:0] = inputInstruction[20:12];
      outImmediate[63:10] = {64{outImmediate[9]}};
    end
  end
endmodule
module Branch
(
  input unconditional_branch_in,
  input conditional_branch_in,
  input alu_main_is_zero,
  output reg PC_src_out
);

  reg conditional_branch_temp;

  always @(unconditional_branch_in, conditional_branch_in, alu_main_is_zero) begin
    conditional_branch_temp = conditional_branch_in & alu_main_is_zero;
    PC_src_out = unconditional_branch_in | conditional_branch_temp;
  end
endmodule
module ARM_Control
(
  input [10:0] instruction,
  output reg [1:0] control_aluop,
  output reg control_alusrc,
  output reg control_isZeroBranch,
  output reg control_isUnconBranch,
  output reg control_memRead,
  output reg control_memwrite,
  output reg control_regwrite,
  output reg control_mem2reg
);

  always @(instruction) begin
    /* B */
    if (instruction[10:5] == 6'b000101) begin
      control_mem2reg <= 1'bx;
      control_memRead <= 1'b0;
      control_memwrite <= 1'b0;
      control_alusrc <= 1'b0;
      control_aluop <= 2'b01;
      control_isZeroBranch <= 1'b0;
      control_isUnconBranch <= 1'b1;
      control_regwrite <= 1'b0;
    end

    /* CBZ */
    else if (instruction[10:3] == 8'b10110100) begin
      control_mem2reg <= 1'bx;
      control_memRead <= 1'b0;
      control_memwrite <= 1'b0;
      control_alusrc <= 1'b0;
      control_aluop <= 2'b01;
      control_isZeroBranch <= 1'b1;
      control_isUnconBranch <= 1'b0;
      control_regwrite <= 1'b0;
    end

    /* R-Type Instructions */
    else begin
      control_isZeroBranch <= 1'b0;
      control_isUnconBranch <= 1'b0;

      case (instruction[10:0])

        /* LDUR */
        11'b11111000010 : begin
          control_mem2reg <= 1'b1;
          control_memRead <= 1'b1;
          control_memwrite <= 1'b0;
          control_alusrc <= 1'b1;
          control_aluop <= 2'b00;
          control_regwrite <= 1'b1;
        end

        /* STUR */
        11'b11111000000 : begin
          control_mem2reg <= 1'bx;
          control_memRead <= 1'b0;
          control_memwrite <= 1'b1;
          control_alusrc <= 1'b1;
          control_aluop <= 2'b00;
          control_regwrite <= 1'b0;
        end

        /* ADD */
        11'b10001011000 : begin
          control_mem2reg <= 1'b0;
          control_memRead <= 1'b0;
          control_memwrite <= 1'b0;
          control_alusrc <= 1'b0;
          control_aluop <= 2'b10;
          control_regwrite <= 1'b1;
        end

        /* SUB */
        11'b11001011000 : begin
          control_mem2reg <= 1'b0;
          control_memRead <= 1'b0;
          control_memwrite <= 1'b0;
          control_alusrc <= 1'b0;
          control_aluop <= 2'b10;
          control_regwrite <= 1'b1;
        end

        /* AND */
        11'b10001010000 : begin
          control_mem2reg <= 1'b0;
          control_memRead <= 1'b0;
          control_memwrite <= 1'b0;
          control_alusrc <= 1'b0;
          control_aluop <= 2'b10;
          control_regwrite <= 1'b1;
        end

        /* ORR */
        11'b10101010000 : begin
          control_mem2reg <= 1'b0;
          control_memRead <= 1'b0;
          control_memwrite <= 1'b0;
          control_alusrc <= 1'b0;
          control_aluop <= 2'b10;
          control_regwrite <= 1'b1;
        end

        default : begin
          control_isZeroBranch <= 1'bx;
      	  control_isUnconBranch <= 1'bx;
          control_mem2reg <= 1'bx;
          control_memRead <= 1'bx;
          control_memwrite <= 1'bx;
          control_alusrc <= 1'bx;
          control_aluop <= 2'bxx;
          control_regwrite <= 1'bx;
        end
      endcase
    end
  end
endmodule
module CPU_TEST;

  /* Clock Signal */
  reg CLOCK;

  /* Wires to connect instruction memory to CPU */
  wire [63:0] instructionPC;
  wire [31:0] instructionOut;

  /* Wires to connect registers to CPU */
  wire [4:0] READ_REG_1;
  wire [4:0] READ_REG_2;
  wire [4:0] WRITE_REG;
  wire [63:0] WRITE_DATA;
  wire [63:0] DATA_OUT_1;
  wire [63:0] DATA_OUT_2;

  /* Wires to connect Data Memory to CPU */
  wire [63:0] data_memory_out;
  wire [63:0] ALU_Result_Out;

  /* Wires to connect CPU Control Lines to Memories */
  wire CONTROL_REG2LOC;
  wire CONTROL_REGWRITE;
  wire CONTROL_MEMREAD;
  wire CONTROL_MEMWRITE;
  wire CONTROL_BRANCH;

  /* Instruction Memory Module */
  Instruction_Memory mem1
  (
    instructionPC,
    instructionOut
  );

  /* Registers Module */
  Registers mem2
  (
    READ_REG_1,
    READ_REG_2,
    WRITE_REG,
    WRITE_DATA,
    CONTROL_REGWRITE,
    DATA_OUT_1,
    DATA_OUT_2
  );

  /* Data Memory Module */
  Data_Memory mem3
  (
    ALU_Result_Out,
    DATA_OUT_2,
    CONTROL_MEMREAD,
    CONTROL_MEMWRITE,
    data_memory_out
  );

  /* CPU Module */
  ARM_CPU core
  (
    .CLOCK(CLOCK),
    .INSTRUCTION(instructionOut),
    .PC(instructionPC),
    .CONTROL_REG2LOC(CONTROL_REG2LOC),
    .CONTROL_REGWRITE(CONTROL_REGWRITE),
    .CONTROL_MEMREAD(CONTROL_MEMREAD),
    .CONTROL_MEMWRITE(CONTROL_MEMWRITE),
    .CONTROL_BRANCH(CONTROL_BRANCH),
    .READ_REG_1(READ_REG_1),
    .READ_REG_2(READ_REG_2),
    .WRITE_REG(WRITE_REG),
    .REG_DATA1(DATA_OUT_1),
    .REG_DATA2(DATA_OUT_2),
    .ALU_Result_Out(ALU_Result_Out),
    .data_memory_out(data_memory_out),
    .WRITE_REG_DATA(WRITE_DATA)
  );

  /* Setup the clock */
  initial begin
    CLOCK = 1'b0;
    #30 $finish;
  end

  /* Toggle the clock */
  always begin
    #1 CLOCK = ~CLOCK;
  end
endmodule
module tri_st_add_csmux(
   sum_0,
   sum_1,
   ci_b,
   sum
);
   input [0:7]  sum_0;		// after xor
   input [0:7]  sum_1;
   input        ci_b;
   output [0:7] sum;

   wire [0:7]   sum0_b;
   wire [0:7]   sum1_b;
   wire         int_ci;
   wire         int_ci_t;
   wire         int_ci_b;

   assign int_ci = (~ci_b);
   assign int_ci_t = (~ci_b);
   assign int_ci_b = (~int_ci_t);

   assign sum0_b[0] = (~(sum_0[0] & int_ci_b));
   assign sum0_b[1] = (~(sum_0[1] & int_ci_b));
   assign sum0_b[2] = (~(sum_0[2] & int_ci_b));
   assign sum0_b[3] = (~(sum_0[3] & int_ci_b));
   assign sum0_b[4] = (~(sum_0[4] & int_ci_b));
   assign sum0_b[5] = (~(sum_0[5] & int_ci_b));
   assign sum0_b[6] = (~(sum_0[6] & int_ci_b));
   assign sum0_b[7] = (~(sum_0[7] & int_ci_b));

   assign sum1_b[0] = (~(sum_1[0] & int_ci));
   assign sum1_b[1] = (~(sum_1[1] & int_ci));
   assign sum1_b[2] = (~(sum_1[2] & int_ci));
   assign sum1_b[3] = (~(sum_1[3] & int_ci));
   assign sum1_b[4] = (~(sum_1[4] & int_ci));
   assign sum1_b[5] = (~(sum_1[5] & int_ci));
   assign sum1_b[6] = (~(sum_1[6] & int_ci));
   assign sum1_b[7] = (~(sum_1[7] & int_ci));

   assign sum[0] = (~(sum0_b[0] & sum1_b[0]));
   assign sum[1] = (~(sum0_b[1] & sum1_b[1]));
   assign sum[2] = (~(sum0_b[2] & sum1_b[2]));
   assign sum[3] = (~(sum0_b[3] & sum1_b[3]));
   assign sum[4] = (~(sum0_b[4] & sum1_b[4]));
   assign sum[5] = (~(sum0_b[5] & sum1_b[5]));
   assign sum[6] = (~(sum0_b[6] & sum1_b[6]));
   assign sum[7] = (~(sum0_b[7] & sum1_b[7]));

endmodule
module tri_st_cntlz_8b(
   a,
   y,
   z_b
);
   input [0:7]  a;
   output [0:2] y;
   output       z_b;

   wire [0:7]   a0;
   wire [0:7]   a1;
   wire [0:7]   a2;
   wire [0:6]   ax;

   assign a0[1:7] = ~( a[0:6] | a[1:7]);
   assign a1[2:7] = ~(a0[0:5] & a0[2:7]);
   assign a2[4:7] = ~(a1[0:3] | a1[4:7]);

   assign a0[0:0] = (~a[0:0]);
   assign a1[0:1] = (~a0[0:1]);
   assign a2[0:3] = (~a1[0:3]);

   assign ax[0:6] = ~(a2[0:6] & a[1:7]);

   assign z_b = (~a2[7]);

   assign y[0] = ~(ax[3] & ax[4]) | ~(ax[5] & ax[6]);
   assign y[1] = ~(ax[1] & ax[2]) | ~(ax[5] & ax[6]);
   assign y[2] = ~(ax[0] & ax[2]) | ~(ax[4] & ax[6]);

endmodule
module tri_nlat_scan(
   vd,
   gd,
   d1clk,
   d2clk,
   lclk,
   din,
   scan_in,
   q,
   q_b,
   scan_out
);
   parameter                      OFFSET = 0;
   parameter                      WIDTH = 1;
   parameter                      INIT = 0;
   parameter                      RESET_INVERTS_SCAN = 1'b1;
   parameter                      SYNTHCLONEDLATCH = "";
   parameter                      L2_LATCH_TYPE = 2;            //L2_LATCH_TYPE = slave_latch;
                                                                //0=master_latch,1=L1,2=slave_latch,3=L2,4=flush_latch,5=L4
   parameter                      NEEDS_SRESET = 1;		// for inferred latches
   parameter                      DOMAIN_CROSSING = 0;		// 0 - Internal Flop, 1 - Domain Crossing Input Flop (requires extra logic for ASICs)

   inout                          vd;
   inout                          gd;
   input                          d1clk;
   input                          d2clk;
   input [0:`NCLK_WIDTH-1]        lclk;
   input [OFFSET:OFFSET+WIDTH-1]  din;
   input [OFFSET:OFFSET+WIDTH-1]  scan_in;
   output [OFFSET:OFFSET+WIDTH-1] q;
   output [OFFSET:OFFSET+WIDTH-1] q_b;
   output [OFFSET:OFFSET+WIDTH-1] scan_out;

   // tri_nlat_scan

   parameter [0:WIDTH-1]          init_v = INIT;
   parameter [0:WIDTH-1]          ZEROS = {WIDTH{1'b0}};

   generate
   begin
      wire                          sreset;
      wire [0:WIDTH-1]              int_din;
      reg [0:WIDTH-1]               int_dout;
      wire [0:WIDTH-1]              vact;
      wire [0:WIDTH-1]              vact_b;
      wire [0:WIDTH-1]              vsreset;
      wire [0:WIDTH-1]              vsreset_b;
      wire [0:WIDTH-1]              vthold;
      wire [0:WIDTH-1]              vthold_b;
       (* analysis_not_referenced="true" *)
      wire                          unused;

      if (NEEDS_SRESET == 1)
      begin : rst
        assign sreset = lclk[1];
      end
      if (NEEDS_SRESET != 1)
      begin : no_rst
        assign sreset = 1'b0;
      end

      assign vsreset = {WIDTH{sreset}};
      assign vsreset_b = {WIDTH{~sreset}};
      assign int_din = (vsreset_b & din) | (vsreset & init_v);

      assign vact = {WIDTH{d1clk}};
      assign vact_b = {WIDTH{~d1clk}};

      assign vthold_b = {WIDTH{d2clk}};
      assign vthold = {WIDTH{~d2clk}};


      always @(posedge lclk[0])
      begin: l
        int_dout <= (((vact & vthold_b) | vsreset) & int_din) | (((vact_b | vthold) & vsreset_b) & int_dout);
      end
      assign q = int_dout;
      assign q_b = (~int_dout);
      assign scan_out = ZEROS;

      assign unused = | {vd, gd, lclk, scan_in};
   end
   endgenerate
endmodule
module tri_nand2(
   y,
   a,
   b
);
   parameter                      WIDTH = 1;
   parameter                      BTR = "NAND2_X2M_NONE";  //Specify full BTR name, else let tool select
   output [0:WIDTH-1]  y;
   input [0:WIDTH-1]   a;
   input [0:WIDTH-1]   b;

   // tri_nand2
   genvar 	       i;

   generate
      begin : t
	 for (i = 0; i < WIDTH; i = i + 1)
	   begin : w

	      nand I0(y[i], a[i], b[i]);

	   end // block: w
      end

   endgenerate
endmodule
module tri_xnor2(
   y,
   a,
   b
);
   parameter                      WIDTH = 1;
   parameter                      BTR = "XNOR2_X2M_NONE";  //Specify full BTR name, else let tool select
   output [0:WIDTH-1]  y;
   input [0:WIDTH-1]   a;
   input [0:WIDTH-1]   b;

   genvar 	       i;

   generate
      begin : t
	 for (i = 0; i < WIDTH; i = i + 1)
	   begin : w

	      xnor I0(y[i], a[i], b[i]);

	   end // block: w
      end

   endgenerate
endmodule
module tri_xor2(
   y,
   a,
   b
);
   parameter                      WIDTH = 1;
   parameter                      BTR = "XOR2_X2M_NONE";  //Specify full BTR name, else let tool select
   output [0:WIDTH-1]  y;
   input [0:WIDTH-1]   a;
   input [0:WIDTH-1]   b;

   genvar 	       i;

   generate
      begin : t
	 for (i = 0; i < WIDTH; i = i + 1)
	   begin : w

	      xor I0(y[i], a[i], b[i]);

	   end // block: w
      end

   endgenerate
endmodule
module tri_aoi21(
   y,
   a0,
   a1,
   b0
);
   parameter                      WIDTH = 1;
   parameter                      BTR = "AOI21_X2M_NONE";  //Specify full BTR name, else let tool select
   output [0:WIDTH-1]  y;
   input [0:WIDTH-1]   a0;
   input [0:WIDTH-1]   a1;
   input [0:WIDTH-1]   b0;

   // tri_aoi21
   genvar 	       i;
   wire [0:WIDTH-1]    outA;

   generate
      begin : t
	 for (i = 0; i < WIDTH; i = i + 1)
	   begin : w

	      and I0(outA[i], a0[i], a1[i]);
	      nor I2(y[i], outA[i], b0[i]);

	   end // block: w
      end

   endgenerate
endmodule
module tri_nor3(
   y,
   a,
   b,
   c
);
   parameter                      WIDTH = 1;
   parameter                      BTR = "NOR3_X2M_NONE";  //Specify full BTR name, else let tool select
   output [0:WIDTH-1]  y;
   input [0:WIDTH-1]   a;
   input [0:WIDTH-1]   b;
   input [0:WIDTH-1]   c;

   // tri_nor3
   genvar 	       i;

   generate
      begin : t
	 for (i = 0; i < WIDTH; i = i + 1)
	   begin : w

	      nor I0(y[i], a[i], b[i], c[i]);

	   end // block: w
      end

   endgenerate
endmodule
module tri_lcbor(clkoff_b, thold, sg, act_dis, force_t, thold_b);
   input      clkoff_b;
   input      thold;
   input      sg;
   input      act_dis;
   output     force_t;
   output     thold_b;

   (* analysis_not_referenced="true" *)
   wire       unused;

   assign unused = clkoff_b | sg | act_dis;

   assign force_t = 1'b0;
   assign thold_b = (~thold);
endmodule
module tri_aoi22(
   y,
   a0,
   a1,
   b0,
   b1
);
   parameter                      WIDTH = 1;
   parameter                      BTR = "AOI22_X2M_NONE";  //Specify full BTR name, else let tool select
   output [0:WIDTH-1]  y;
   input [0:WIDTH-1]   a0;
   input [0:WIDTH-1]   a1;
   input [0:WIDTH-1]   b0;
   input [0:WIDTH-1]   b1;

   // tri_aoi22
   genvar 	       i;
   wire [0:WIDTH-1]    outA;
   wire [0:WIDTH-1]    outB;

   generate
      begin : t
	 for (i = 0; i < WIDTH; i = i + 1)
	   begin : w

	      and I0(outA[i], a0[i], a1[i]);
	      and I1(outB[i], b0[i], b1[i]);
	      nor I2(y[i], outA[i], outB[i]);


	   end // block: w
      end

   endgenerate
endmodule
module tri_nand2_nlats(
   vd,
   gd,
   lclk,
   d1clk,
   d2clk,
   scanin,
   scanout,
   a1,
   a2,
   qb
);
   parameter                      OFFSET = 0;
   parameter                      WIDTH = 1;
   parameter                      INIT = 0;
   parameter                      L2_LATCH_TYPE = 2;            //L2_LATCH_TYPE = slave_latch;
                                                                //0=master_latch,1=L1,2=slave_latch,3=L2,4=flush_latch,5=L4
   parameter                      SYNTHCLONEDLATCH = "";
   parameter                      BTR = "NLA0001_X1_A12TH";
   parameter                      NEEDS_SRESET = 1;		// for inferred latches

   inout                          vd;
   inout                          gd;
   input [0:`NCLK_WIDTH-1]        lclk;
   input                          d1clk;
   input                          d2clk;
   input [OFFSET:OFFSET+WIDTH-1]  scanin;
   output [OFFSET:OFFSET+WIDTH-1] scanout;
   input [OFFSET:OFFSET+WIDTH-1]  a1;
   input [OFFSET:OFFSET+WIDTH-1]  a2;
   output [OFFSET:OFFSET+WIDTH-1] qb;

   // tri_nand2_nlats

   parameter [0:WIDTH-1]          init_v = INIT;
   parameter [0:WIDTH-1]          ZEROS = {WIDTH{1'b0}};

   generate
   begin
      wire                          sreset;
      wire [0:WIDTH-1]              int_din;
      reg [0:WIDTH-1]               int_dout;
      wire [0:WIDTH-1]              vact;
      wire [0:WIDTH-1]              vact_b;
      wire [0:WIDTH-1]              vsreset;
      wire [0:WIDTH-1]              vsreset_b;
      wire [0:WIDTH-1]              vthold;
      wire [0:WIDTH-1]              vthold_b;
      wire [0:WIDTH-1]              din;
       (* analysis_not_referenced="true" *)
      wire                          unused;

      if (NEEDS_SRESET == 1)
      begin : rst
        assign sreset = lclk[1];
      end
      if (NEEDS_SRESET != 1)
      begin : no_rst
        assign sreset = 1'b0;
      end

      assign vsreset = {WIDTH{sreset}};
      assign vsreset_b = {WIDTH{~sreset}};
      assign din = a1 & a2;		// Output is inverted, so just AND2 here
      assign int_din = (vsreset_b & din) | (vsreset & init_v);

      assign vact = {WIDTH{d1clk}};
      assign vact_b = {WIDTH{~d1clk}};

      assign vthold_b = {WIDTH{d2clk}};
      assign vthold = {WIDTH{~d2clk}};


      always @(posedge lclk[0])
      begin: l
        int_dout <= (((vact & vthold_b) | vsreset) & int_din) | (((vact_b | vthold) & vsreset_b) & int_dout);
      end
      assign qb = (~int_dout);
      assign scanout = ZEROS;

      assign unused = | {vd, gd, lclk, scanin};
   end
   endgenerate
endmodule