dakies/OSS_Verilog huggingface dataset:
module hps_reset (
	probe,
	source_clk,
	source);

	input	  probe;
	input	  source_clk;
	output	[2:0]  source;

	wire [2:0] sub_wire0;
	wire [2:0] source = sub_wire0[2:0];

	altsource_probe	altsource_probe_component (
				.probe (probe),
				.source_clk (source_clk),
				.source (sub_wire0)
				// synopsys translate_off
				,
				.clr (),
				.ena (),
				.ir_in (),
				.ir_out (),
				.jtag_state_cdr (),
				.jtag_state_cir (),
				.jtag_state_e1dr (),
				.jtag_state_sdr (),
				.jtag_state_tlr (),
				.jtag_state_udr (),
				.jtag_state_uir (),
				.raw_tck (),
				.source_ena (),
				.tdi (),
				.tdo (),
				.usr1 ()
				// synopsys translate_on
				);
	defparam
		altsource_probe_component.enable_metastability = "YES",
		altsource_probe_component.instance_id = "RST",
		altsource_probe_component.probe_width = 0,
		altsource_probe_component.sld_auto_instance_index = "YES",
		altsource_probe_component.sld_instance_index = 0,
		altsource_probe_component.source_initial_value = " 0",
		altsource_probe_component.source_width = 3;


endmodule
module debounce (
  clk,
  reset_n,
  data_in,
  data_out
);

  parameter WIDTH = 32;           // set to be the width of the bus being debounced
  parameter POLARITY = "HIGH";    // set to be "HIGH" for active high debounce or "LOW" for active low debounce
  parameter TIMEOUT = 50000;      // number of input clock cycles the input signal needs to be in the active state
  parameter TIMEOUT_WIDTH = 16;   // set to be ceil(log2(TIMEOUT))
  
  input wire clk;
  input wire reset_n;
  
  input wire [WIDTH-1:0] data_in;
  output wire [WIDTH-1:0] data_out;
  
  reg [TIMEOUT_WIDTH-1:0] counter [0:WIDTH-1];
  wire counter_reset [0:WIDTH-1];
  wire counter_enable [0:WIDTH-1];
  
  // need one counter per input to debounce
  genvar i;
  generate for (i = 0; i < WIDTH; i = i+1)
  begin:  debounce_counter_loop
    always @ (posedge clk or negedge reset_n)
    begin
      if (reset_n == 0)
      begin
        counter[i] <= 0;
      end
      else
      begin
        if (counter_reset[i] == 1)  // resetting the counter needs to win
        begin
          counter[i] <= 0;
        end
        else if (counter_enable[i] == 1)
        begin
          counter[i] <= counter[i] + 1'b1;
        end
      end
    end
 
    if (POLARITY == "HIGH")
    begin
      assign counter_reset[i] = (data_in[i] == 0);
      assign counter_enable[i] = (data_in[i] == 1) & (counter[i] < TIMEOUT);
      assign data_out[i] = (counter[i] == TIMEOUT) ? 1'b1 : 1'b0;
    end
    else
    begin
      assign counter_reset[i] = (data_in[i] == 1);
      assign counter_enable[i] = (data_in[i] == 0) & (counter[i] < TIMEOUT);
      assign data_out[i] = (counter[i] == TIMEOUT) ? 1'b0 : 1'b1;    
    end
    
  end  
  endgenerate
  
endmodule
module MY_DESIGN ( Cin1, Cin2, Cout, data1, data2, sel, clk, out1, out2, out3);
  input [4:0] Cin1, Cin2, data1, data2;
  input sel, clk;
  output [4:0] Cout, out1, out2, out3;
  reg   [4:0] R1, R2, R3, R4, out1, out2, out3;
  wire   [4:0] arth_o;

  ARITH U1_ARITH ( .a(data1), .b(data2), .sel(sel), .out1(arth_o) );
  COMBO U_COMBO ( .Cin1(Cin1), .Cin2(Cin2), .sel(sel), .Cout(Cout) );


always @ (posedge clk)
  begin
    R1 <= arth_o;
    R2 <= data1 & data2;
    R3 <= data1 + data2;
    R4 <= R2 + R3;
  end

always @ (out2, R1, R3, R4)
  begin
    out1 <= R1 + R3;
    out2 <= R3 & R4;
    out3 <= out2 - R3;
  end

endmodule
module ARITH ( a, b, sel, out1 );
  input [4:0] a, b;
  input sel;
  output [4:0] out1;
  reg [4:0] out1;

always @(sel, a, b)

  begin
    case({sel})
        1'b0: out1 <= a + b;
        1'b1: out1 <= a - b;
    endcase
  end



endmodule
module COMBO ( Cin1, Cin2, sel, Cout );
  input [4:0] Cin1, Cin2;
  input sel;
  output [4:0] Cout;
  reg [4:0] Cout;

  wire   [4:0] arth_o;

  ARITH U2_ARITH ( .a(Cin1), .b(Cin2), .sel(sel), .out1(arth_o) );

always @ (Cin1, arth_o)
  begin
    Cout <= arth_o + Cin1;
  end

endmodule
module led_1second(
             clk,
             reset,
             led_a
             );
input  clk;
input  reset;
output led_a;   

reg reg_led_a;


reg reg_1s_flag;
reg reg_ms_flag;
reg reg_us_flag;
//reg reg_1m_flag;
//reg [5:0] reg_s_count;
reg [9:0] reg_ms_count;
reg [9:0] reg_us_count;
reg [5:0] reg_clk_count;

//¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ªbegin ÒÔÏÂ´úÂëµÄ¹¦ÄÜ£ºÊµÏÖ1·ÖÖÓ¼ÆÊý£¬²¢²úÉúÒ»¸öÒ»·ÖÖÓ±êÖ¾¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª¡ª

//clk¼ÆÊýÆ÷£¬µ±¼Æµ½50 ¸öÊ±ÖÓ£¨50MHZµÄÊ±ÖÓ£¬ÖÜÆÚÊÇ20ns£©Ê±ÇåÁã£¬Ò²¾ÍÊÇ1000ms = 1Î¢Ãë
always @(posedge clk or negedge reset)
begin
  if (~reset)
     reg_clk_count <= 6'b00000;
  else  if( reg_clk_count == 49) reg_clk_count <= 6'b00000;
  else  reg_clk_count <= reg_clk_count + 1;
end

//²úÉú1us±êÖ¾ reg_us_flag
always @(posedge clk or negedge reset)
begin
  if (~reset)
     reg_us_flag <= 0;
  else  if( reg_clk_count == 49) reg_us_flag <= 1;
  else  reg_us_flag <= 0;
end
//us ¼ÆÊýÆ÷£¬µ±¼Æµ½1000us Ê±ÇåÁã£¬Ò²¾ÍÊÇ1ºÁÃë
always @(posedge clk or negedge reset)
begin
  if (~reset)
     reg_us_count <= 0;
  else  if( reg_us_count == 999) reg_us_count <= 10'h000;
  else  if( reg_us_flag) reg_us_count <= reg_us_count + 1;
end

//²úÉú1ms±êÖ¾ reg_ms_flag
always @(posedge clk or negedge reset)
begin
  if (~reset)
     reg_ms_flag <= 0;
  else  if( reg_us_count == 999) reg_ms_flag <= 1;
  else  reg_ms_flag <= 0;
end
//ms ¼ÆÊýÆ÷£¬µ±¼Æµ½1000ms Ê±ÇåÁã£¬Ò²¾ÍÊÇ1ÃëÖÓ
always @(posedge clk or negedge reset)
begin
  if (~reset)
     reg_ms_count <= 0;
  else  if( reg_ms_count == 999) reg_ms_count <= 10'h000;
  else  if( reg_ms_flag) reg_ms_count <= reg_ms_count + 1;
end

//²úÉú1s ±êÖ¾reg_1s_flag
always @(posedge clk or negedge reset)
begin
  if (~reset)
     reg_1s_flag <= 0;
  else  if( reg_ms_count == 999) reg_1s_flag <= 1;
  else  reg_1s_flag <= 0;
end


always @(posedge clk or negedge reset)
begin
  if (~reset)
     reg_led_a <= 0;
  else  if( reg_1s_flag == 1) reg_led_a <= ~reg_led_a;
  else  reg_led_a <= reg_led_a;
end

assign led_a = reg_led_a ;


endmodule
module fpga_ram_top #(
// --------------------------------------------------------------------------
// Parameter Declarations
// --------------------------------------------------------------------------
  parameter AW = 16,
  parameter filename = ""
)
 (
  // Inputs
  input  wire          CLK,
  input  wire [AW-1:2] ADDR,
  input  wire [31:0]   WDATA,
  input  wire [3:0]    WREN,
  input  wire          CS,

  // Outputs
  output wire [31:0]   RDATA
 );

blk_mem_zed //#(
  //.filename("mem0.coe"))
  blk_mem0 
  (
  .clka (CLK),
  .ena  (CS),
  .wea  (WREN[0]),
  .addra(ADDR[15:2]),
  .dina (WDATA[7:0]),
  .douta(RDATA[7:0])
);
blk_mem_zed// #(
 // .filename("mem1.coe"))
  blk_mem1 (
  .clka (CLK),
  .ena  (CS),
  .wea  (WREN[1]),
  .addra(ADDR[15:2]),
  .dina (WDATA[15:8]),
  .douta(RDATA[15:8])
);
blk_mem_zed //#(
 // .filename("mem2.coe"))
  blk_mem2 (
  .clka (CLK),
  .ena  (CS),
  .wea  (WREN[2]),
  .addra(ADDR[15:2]),
  .dina (WDATA[23:16]),
  .douta(RDATA[23:16])
);
blk_mem_zed //#(
  //.filename("mem3.coe"))
  blk_mem3 (
  .clka (CLK),
  .ena  (CS),
  .wea  (WREN[3]),
  .addra(ADDR[15:2]),
  .dina (WDATA[31:24]),
  .douta(RDATA[31:24])
);

endmodule
module blk_mem_zed #(
  parameter filename = "mem0.mif")
  (
  clka,
  ena,
  wea,
  addra,
  dina,
  douta
);

input clka;
input ena;
input [0 : 0] wea;
input [13 : 0] addra;
input [7 : 0] dina;
output [7 : 0] douta;

// synthesis translate_off

  BLK_MEM_GEN_V7_1 #(
    .C_ADDRA_WIDTH(14),
    .C_ADDRB_WIDTH(14),
    .C_ALGORITHM(1),
    .C_AXI_ID_WIDTH(4),
    .C_AXI_SLAVE_TYPE(0),
    .C_AXI_TYPE(1),
    .C_BYTE_SIZE(9),
    .C_COMMON_CLK(0),
    .C_DEFAULT_DATA(""),
    .C_DISABLE_WARN_BHV_COLL(0),
    .C_DISABLE_WARN_BHV_RANGE(0),
    .C_ENABLE_32BIT_ADDRESS(0),
    .C_FAMILY("zynq"),
    .C_HAS_AXI_ID(0),
    .C_HAS_ENA(1),
    .C_HAS_ENB(0),
    .C_HAS_INJECTERR(0),
    .C_HAS_MEM_OUTPUT_REGS_A(0),
    .C_HAS_MEM_OUTPUT_REGS_B(0),
    .C_HAS_MUX_OUTPUT_REGS_A(0),
    .C_HAS_MUX_OUTPUT_REGS_B(0),
    .C_HAS_REGCEA(0),
    .C_HAS_REGCEB(0),
    .C_HAS_RSTA(0),
    .C_HAS_RSTB(0),
    .C_HAS_SOFTECC_INPUT_REGS_A(0),
    .C_HAS_SOFTECC_OUTPUT_REGS_B(0),
    .C_INIT_FILE_NAME(filename),
    //.C_INIT_FILE_NAME(""),
    .C_INITA_VAL(""),
    .C_INITB_VAL(""),
    .C_INTERFACE_TYPE(0),
    .C_LOAD_INIT_FILE(1),
    //.C_LOAD_INIT_FILE(0),
    .C_MEM_TYPE(0),
    .C_MUX_PIPELINE_STAGES(0),
    .C_PRIM_TYPE(1),
    .C_READ_DEPTH_A(16384),
    .C_READ_DEPTH_B(16384),
    .C_READ_WIDTH_A(8),
    .C_READ_WIDTH_B(8),
    .C_RST_PRIORITY_A("CE"),
    .C_RST_PRIORITY_B("CE"),
    .C_RST_TYPE("SYNC"),
    .C_RSTRAM_A(0),
    .C_RSTRAM_B(0),
    .C_SIM_COLLISION_CHECK("ALL"),
    .C_USE_BYTE_WEA(0),
    .C_USE_BYTE_WEB(0),
    .C_USE_DEFAULT_DATA(0),
    .C_USE_ECC(0),
    .C_USE_SOFTECC(0),
    .C_WEA_WIDTH(1),
    .C_WEB_WIDTH(1),
    .C_WRITE_DEPTH_A(16384),
    .C_WRITE_DEPTH_B(16384),
    .C_WRITE_MODE_A("READ_FIRST"),
    .C_WRITE_MODE_B("WRITE_FIRST"),
    .C_WRITE_WIDTH_A(8),
    .C_WRITE_WIDTH_B(8),
    .C_XDEVICEFAMILY("zynq")
  )
  inst (
    .CLKA(clka),
    .ENA(ena),
    .WEA(wea),
    .ADDRA(addra),
    .DINA(dina),
    .DOUTA(douta),
    .RSTA(),
    .REGCEA(),
    .CLKB(),
    .RSTB(),
    .ENB(),
    .REGCEB(),
    .WEB(),
    .ADDRB(),
    .DINB(),
    .DOUTB(),
    .INJECTSBITERR(),
    .INJECTDBITERR(),
    .SBITERR(),
    .DBITERR(),
    .RDADDRECC(),
    .S_ACLK(),
    .S_ARESETN(),
    .S_AXI_AWID(),
    .S_AXI_AWADDR(),
    .S_AXI_AWLEN(),
    .S_AXI_AWSIZE(),
    .S_AXI_AWBURST(),
    .S_AXI_AWVALID(),
    .S_AXI_AWREADY(),
    .S_AXI_WDATA(),
    .S_AXI_WSTRB(),
    .S_AXI_WLAST(),
    .S_AXI_WVALID(),
    .S_AXI_WREADY(),
    .S_AXI_BID(),
    .S_AXI_BRESP(),
    .S_AXI_BVALID(),
    .S_AXI_BREADY(),
    .S_AXI_ARID(),
    .S_AXI_ARADDR(),
    .S_AXI_ARLEN(),
    .S_AXI_ARSIZE(),
    .S_AXI_ARBURST(),
    .S_AXI_ARVALID(),
    .S_AXI_ARREADY(),
    .S_AXI_RID(),
    .S_AXI_RDATA(),
    .S_AXI_RRESP(),
    .S_AXI_RLAST(),
    .S_AXI_RVALID(),
    .S_AXI_RREADY(),
    .S_AXI_INJECTSBITERR(),
    .S_AXI_INJECTDBITERR(),
    .S_AXI_SBITERR(),
    .S_AXI_DBITERR(),
    .S_AXI_RDADDRECC()
  );

// synthesis translate_on

endmodule
module fpga_rom_top #(
// --------------------------------------------------------------------------
// Parameter Declarations
// --------------------------------------------------------------------------
  parameter AW = 16,
  parameter filename = "image.hex"
)
 (
  // Inputs
  input  wire          CLK,
  input  wire [AW-1:2] ADDR,
  input  wire [31:0]   WDATA,
  input  wire [3:0]    WREN,
  input  wire          CS,

  // Outputs
  output wire [31:0]   RDATA
 );

blk_mem_zed 
#(
  .filename("mem0.mif"))
  blk_mem0 
  (
  .clka (CLK),
  .ena  (1'b1),
  .wea  (WREN[0]),
  .addra(ADDR[15:2]),
  .dina (WDATA[7:0]),
  .douta(RDATA[7:0])
);
blk_mem_zed 
#(
  .filename("mem1.mif"))
  blk_mem1 (
  .clka (CLK),
  .ena  (1'b1),
  .wea  (WREN[1]),
  .addra(ADDR[15:2]),
  .dina (WDATA[15:8]),
  .douta(RDATA[15:8])
);
blk_mem_zed 
#(
  .filename("mem2.mif"))
  blk_mem2 (
  .clka (CLK),
  .ena  (1'b1),
  .wea  (WREN[2]),
  .addra(ADDR[15:2]),
  .dina (WDATA[23:16]),
  .douta(RDATA[23:16])
);
blk_mem_zed 
#(
  .filename("mem3.mif"))
  blk_mem3 (
  .clka (CLK),
  .ena  (1'b1),
  .wea  (WREN[3]),
  .addra(ADDR[15:2]),
  .dina (WDATA[31:24]),
  .douta(RDATA[31:24])
);

endmodule
module buffer_cell (
    input wire in,
    output wire out
    );
    assign out = in;
endmodule
module and_cell (
    input wire a,
    input wire b,
    output wire out
    );

    assign out = a & b;
endmodule
module or_cell (
    input wire a,
    input wire b,
    output wire out
    );

    assign out = a | b;
endmodule
module xor_cell (
    input wire a,
    input wire b,
    output wire out
    );

    assign out = a ^ b;
endmodule
module nand_cell (
    input wire a,
    input wire b,
    output wire out
    );

    assign out = !(a&b);
endmodule
module not_cell (
    input wire in,
    output wire out
    );

    assign out = !in;
endmodule
module mux_cell (
    input wire a,
    input wire b,
    input wire sel,
    output wire out
    );

    assign out = sel ? b : a;
endmodule
module dff_cell (
    input wire clk,
    input wire d,
    output reg q,
    output wire notq
    );

    assign notq = !q;
    always @(posedge clk)
        q <= d;

endmodule
module dffsr_cell (
    input wire clk,
    input wire d,
    input wire s,
    input wire r,
    output reg q,
    output wire notq
    );

    assign notq = !q;

    always @(posedge clk or posedge s or posedge r) begin
        if (r)
            q <= '0;
        else if (s)
            q <= '1;
        else
            q <= d;
    end
endmodule
module frontEnd (

	input lsu_fencei_valid,

	//to MEM
	output [31:0] IL1_ARADDR,
	output [7:0] IL1_ARLEN,
	output [1:0] IL1_ARBURST,
	output IL1_ARVALID,
	input IL1_ARREADY,

	input [63:0] IL1_RDATA,
	input [1:0] IL1_RRESP,
	input IL1_RLAST,
	input IL1_RVALID,
	output IL1_RREADY,

	input instrFifo_reject,
	output instrFifo_push,
	output [`DECODE_INFO_DW-1:0] decode_microInstr,

	input bru_res_valid,
	input bru_takenBranch,
	input jalr_valid,
	input [63:0] jalr_pc,

	input [63:0] privileged_pc,
	input privileged_valid,

	output flush,
	input CLK,
	input RSTn
	
);


	wire branch_pc_valid;
	wire [63:0] branch_pc;
	wire [63:0] pc_ic_addr;
	wire pc_ic_ready;
	wire [63:0] ic_iq_pc;
	wire [63:0] ic_iq_instr;
	wire ic_iq_valid;
	wire ic_iq_ready;
	wire iq_id_valid;
	wire [32+64+1-1:0] iq_id_info;
	wire iq_id_ready;
	wire isMisPredict;

	wire fencei_stall;


	assign flush = isMisPredict | privileged_valid;


pcGenerate i_pcGenerate(
	.privileged_pc(privileged_pc),
	.privileged_valid(privileged_valid),

	.branch_pc_valid(branch_pc_valid),
	.branch_pc(branch_pc),

	.fetch_addr_qout(pc_ic_addr),
	.pcGen_fetch_ready(pc_ic_ready),

	.flush(flush|branch_pc_valid),
	.CLK(CLK),
	.RSTn(RSTn)
);



icache i_cache
(
	.IL1_ARADDR   (IL1_ARADDR),
	.IL1_ARLEN    (IL1_ARLEN),
	.IL1_ARBURST  (IL1_ARBURST),
	.IL1_ARVALID  (IL1_ARVALID),
	.IL1_ARREADY  (IL1_ARREADY),
	.IL1_RDATA    (IL1_RDATA),
	.IL1_RRESP    (IL1_RRESP),
	.IL1_RLAST    (IL1_RLAST),
	.IL1_RVALID   (IL1_RVALID),
	.IL1_RREADY   (IL1_RREADY),

	.pc_ic_addr(pc_ic_addr),
	.pc_ic_ready(pc_ic_ready),

	.ic_iq_pc(ic_iq_pc),
	.ic_iq_instr(ic_iq_instr),
	.ic_iq_valid(ic_iq_valid),
	.ic_iq_ready(ic_iq_ready),


	.il1_fence(fencei_stall),

	.flush(flush|branch_pc_valid),
	.CLK(CLK),
	.RSTn(RSTn)


);



iqueue i_iqueue(

	.lsu_fencei_valid(lsu_fencei_valid),

	.fencei_stall    (fencei_stall),
	.ic_iq_pc(ic_iq_pc),
	.ic_iq_instr(ic_iq_instr),
	.ic_iq_valid(ic_iq_valid),
	.ic_iq_ready(ic_iq_ready),

	.branch_pc_valid(branch_pc_valid),
	.branch_pc(branch_pc),

	.jalr_valid(jalr_valid),
	.jalr_pc(jalr_pc),
	.bru_res_valid(bru_res_valid),
	.bru_takenBranch(bru_takenBranch),

	.iq_id_valid(iq_id_valid),
	.iq_id_info(iq_id_info),
	.iq_id_ready(iq_id_ready),

	.isMisPredict(isMisPredict),

	.flush(flush),
	.CLK(CLK),
	.RSTn(RSTn)
);


decoder i_decoder
(
	.iq_id_valid(iq_id_valid),
	.iq_id_ready(iq_id_ready),
	.iq_id_info(iq_id_info),

	.instrFifo_reject(instrFifo_reject),
	.decode_microInstr(decode_microInstr),
	.instrFifo_push(instrFifo_push),

	.flush(flush),
	.CLK(CLK),
	.RSTn(RSTn)

);









endmodule
module instr_fifo # (
	parameter DW = 64,
	parameter AW = 3
) (

	input instrFifo_pop, 
	input instrFifo_push,
	input [DW-1:0] decode_microInstr_push,

	output instrFifo_empty, 
	output instrFifo_reject, 
	output [DW-1:0] decode_microInstr_pop,

	input feflush,
	input CLK,
	input RSTn
);

wire [AW+1-1:0] read_addr;
wire [AW+1-1:0] write_addr;



gen_fifo # (.DW(`DECODE_INFO_DW),.AW(AW)) 
	fifo (
	.fifo_pop(instrFifo_pop),
	.fifo_push(instrFifo_push),

	.data_push(decode_microInstr_push),
	.data_pop(decode_microInstr_pop),

	.fifo_empty(instrFifo_empty),
	.fifo_full(),

	.read_addr(read_addr),
	.write_addr(write_addr),


	.flush(feflush),
	.CLK(CLK),
	.RSTn(RSTn)
);


wire reject_set;
wire reject_rst;

assign reject_set = (write_addr[AW-1:AW-2] == (read_addr[AW-1:AW-2] - 2'b01)) & (write_addr[AW-3:0] == (read_addr[AW-3:0]));
assign reject_rst = feflush 
					| ((write_addr[AW-1:AW-2] == (read_addr[AW-1:AW-2] + 2'b01)) & (write_addr[AW-3:0] == (read_addr[AW-3:0])));

gen_rsffr # (.DW(1)) reject_rsffr ( .set_in(reject_set), .rst_in(reject_rst), .qout(instrFifo_reject), .CLK(CLK), .RSTn(RSTn) );







endmodule
module gen_csrreg #(
	parameter DW = 64,
	parameter rstValue = {DW{1'b0}},
	parameter CSRADDR = 12'b0
)
(

	input [DW-1:0] privi_data,
	input isPrivi,

	input [DW-1:0] csr_op,
	input [11:0] addr,
	input rw,
	input rs,
	input rc,

	output [DW-1:0] qout,

	input CLK,
	input RSTn
);


wire enb;
wire [DW-1:0] dnxtb;

assign enb = (addr == CSRADDR) & (rw | rs | rc);
assign dnxtb = 	  ({DW{rw}} & csr_op)
				| ({DW{rs}} & ( qout |   csr_op ) )
				| ({DW{rc}} & ( qout & (~csr_op)) );



gen_dpdffren  #( .DW(DW), .rstValue(rstValue) ) dpdffren
(
	.dnxta(privi_data),
	.ena(isPrivi),

	.dnxtb(dnxtb),
	.enb(enb),

	.qout(qout),

	.CLK(CLK),
	.RSTn(RSTn)
);







//ASSERT
always @( posedge CLK ) begin
	if ( (rw & rs) | (rs & rc) | (rw & rc) ) begin
		$display("Assert Fail at gen_csrreg");
		$finish;
	end
end


endmodule
module lfsr
(
	output [15:0] random,

	input CLK
);





reg [15:0] shiftReg;

initial begin shiftReg = $random; end

wire tap;

always @(posedge CLK) begin
	shiftReg <= #1 { shiftReg[14:0], tap };
end

assign tap = shiftReg[15] ^ shiftReg[4] ^ shiftReg[2] ^ shiftReg[1];
assign random = shiftReg;




endmodule
module gen_fifo # (
	parameter DW = 64,
	parameter AW = 3
) (

	input fifo_pop, 
	input fifo_push,
	input [DW-1:0] data_push,

	output fifo_empty, 
	output fifo_full, 
	output [DW-1:0] data_pop,

	output [AW+1-1:0] read_addr,
	output [AW+1-1:0] write_addr,

	output [(DW*(2**AW))-1:0] expose_o,
	output [((2**AW)-1):0] valid,

	input flush,
	input CLK,
	input RSTn
);

	localparam DP = 2**AW;


	wire [AW+1-1:0] read_addr_dnxt, read_addr_qout;
	wire [AW+1-1:0] write_addr_dnxt, write_addr_qout;
	wire [DP*DW-1:0] fifo_data_dnxt,fifo_data_qout;
	wire [DP-1:0] valid_set, valid_rst, valid_qout, valid_en;



	gen_dffr # (.DW(AW+1)) read_addr_dffr (.dnxt(read_addr_dnxt), .qout(read_addr_qout), .CLK(CLK), .RSTn(RSTn));
	gen_dffr # (.DW(AW+1)) write_addr_dffr (.dnxt(write_addr_dnxt), .qout(write_addr_qout), .CLK(CLK), .RSTn(RSTn));

	assign fifo_empty = (read_addr_qout == write_addr_qout);
	assign fifo_full = (read_addr_qout[AW-1:0] == write_addr_qout[AW-1:0]) & (read_addr_qout[AW] != write_addr_qout[AW]);
	assign read_addr = read_addr_qout;
	assign write_addr = write_addr_qout;

generate
	for ( genvar i = 0; i < DP; i = i + 1 ) begin
		assign fifo_data_dnxt[DW*i+:DW] = (fifo_push & ~fifo_full & (write_addr_qout[AW-1:0] == i) ) ? data_push : fifo_data_qout[DW*i+:DW];


		gen_dffr # (.DW(DW)) fifo_data_dffr (.dnxt(fifo_data_dnxt[DW*i+:DW]), .qout(fifo_data_qout[DW*i+:DW]), .CLK(CLK), .RSTn(RSTn));

	end




endgenerate




	assign data_pop = fifo_data_qout[DW*read_addr_qout[AW-1:0]+:DW];

	assign read_addr_dnxt = flush ? ({(AW+1){1'b0}}) : (( fifo_pop & ~fifo_empty ) ? read_addr_qout + 'd1 : read_addr_qout);
	assign write_addr_dnxt = flush ? ({(AW+1){1'b0}}) : (( fifo_push & ~fifo_full ) ? write_addr_qout + 'd1 :  write_addr_qout);


	assign expose_o = fifo_data_qout;
	generate
		for ( genvar dp = 0; dp < DP; dp = dp + 1 ) begin
			assign valid_set[dp] = (fifo_push & ~fifo_full) & ( dp == write_addr_qout[AW-1:0 ] );
			assign valid_rst[dp] = ((fifo_pop & ~fifo_empty) & ( dp == read_addr_qout[AW-1:0 ] )) | flush;


			gen_rsffr #(.DW(1)) valid_rsffr (.set_in(valid_set[dp]), .rst_in(valid_rst[dp]), .qout(valid_qout[dp]), .CLK(CLK), .RSTn(RSTn));
		end
	endgenerate

endmodule
module gen_dffren # (
	parameter DW = 32,
	parameter rstValue = {DW{1'b0}}
)
(

	input [DW-1:0] dnxt,
	output [DW-1:0] qout,
	input en,

	input CLK,
	input RSTn
);



wire [DW-1:0] dffren_dnxt;
wire [DW-1:0] dffren_qout;


gen_dffr # ( .DW(DW), .rstValue(rstValue) ) dffren
(
	.dnxt(dffren_dnxt),
	.qout(dffren_qout),

	.CLK(CLK),
	.RSTn(RSTn)
);


assign dffren_dnxt = en ? dnxt : dffren_qout;
assign qout = dffren_qout;


endmodule
module gen_rsffr # (
	parameter DW = 1,
	parameter rstValue = {DW{1'b0}}
)
(

	input [DW-1:0] set_in,
	input [DW-1:0] rst_in,

	output [DW-1:0] qout,

	input CLK,
	input RSTn
);

reg [DW-1:0] qout_r;

generate
	for ( genvar i = 0; i < DW; i = i + 1 ) begin

		always @(posedge CLK or negedge RSTn) begin
			if ( ~RSTn ) begin
				qout_r[i] <= #1 rstValue[i];
			end 
			else begin
				qout_r[i] <= #1 qout_r[i];
				if ( set_in[i] ) begin
					qout_r[i] <= #1 1'b1;
				end
				if ( rst_in[i] ) begin
					qout_r[i] <= #1 1'b0;	
				end
			end
		end
	end
endgenerate

assign qout = qout_r;

endmodule
module gen_dffr # (
	parameter DW = 32,
	parameter rstValue = {DW{1'b0}}
)
(

	input [DW-1:0] dnxt,
	output [DW-1:0] qout,

	input CLK,
	input RSTn
);

reg [DW-1:0] qout_r;

always @(posedge CLK or negedge RSTn) begin
	if ( ~RSTn )
		qout_r <= #1 rstValue;
	else                  
		qout_r <= #1 dnxt;
end

assign qout = qout_r;

endmodule
module lzp #(
	parameter CW = 2,
	parameter DW = 2**CW
) (
	input [DW-1:0] in_i,
	output [CW-1:0] pos_o,
	output all1,
	output all0
);

//all 0
assign all0 = &(~in_i);
//all 1
assign all1 = &in_i;





wire [127:0] invert_in = ~ (in_i | ( {{(128-DW){1'b1}} , {DW{1'b0}}} ) );

wire sel_lever0;
wire index_lever0;

wire [1:0] sel_lever1;
wire [1:0] index_lever1;

wire [3:0] sel_lever2;
wire [3:0] index_lever2;

wire [7:0] sel_lever3;
wire [7:0] index_lever3;

wire [15:0] sel_lever4;
wire [15:0] index_lever4;

wire [31:0] sel_lever5;
wire [31:0] index_lever5;

wire [63:0] sel_lever6;
wire [63:0] index_lever6;

wire [6:0] pos;
generate
	for ( genvar i = 0; i < 64; i = i + 1 ) begin
		assign index_lever6[i] = invert_in[i*2] | invert_in[i*2+1];
		assign sel_lever6[i] = ~invert_in[i*2];
	end

	for ( genvar i = 0; i < 32; i = i + 1 ) begin
		assign index_lever5[i] = index_lever6[i*2] | index_lever6[i*2+1];
		assign sel_lever5[i] = ~index_lever6[i*2];
	end

	for ( genvar i = 0; i < 16; i = i + 1 ) begin
		assign index_lever4[i] = index_lever5[i*2] | index_lever5[i*2+1];
		assign sel_lever4[i] = ~index_lever5[i*2];
	end	

	for ( genvar i = 0; i < 8; i = i + 1 ) begin
		assign index_lever3[i] = index_lever4[i*2] | index_lever4[i*2+1];
		assign sel_lever3[i] = ~index_lever4[i*2];
	end	

	for ( genvar i = 0; i < 4; i = i + 1 ) begin
		assign index_lever2[i] = index_lever3[i*2] | index_lever3[i*2+1];
		assign sel_lever2[i] = ~index_lever3[i*2];
	end	

	for ( genvar i = 0; i < 2; i = i + 1 ) begin
		assign index_lever1[i] = index_lever2[i*2] | index_lever2[i*2+1];
		assign sel_lever1[i] = ~index_lever2[i*2];
	end	


	assign index_lever0 = index_lever1[0] | index_lever1[1];
	assign sel_lever0 = ~index_lever1[0];
	

endgenerate

	assign pos[6] = sel_lever0;
	assign pos[5] = sel_lever1[pos[6]];
	assign pos[4] = sel_lever2[pos[6:5]];
	assign pos[3] = sel_lever3[pos[6:4]];
	assign pos[2] = sel_lever4[pos[6:3]];
	assign pos[1] = sel_lever5[pos[6:2]];
	assign pos[0] = sel_lever6[pos[6:1]];

	assign pos_o = pos[CW-1:0];



endmodule
module gen_slffr # (
	parameter DW = 1,
	parameter rstValue = 1'b0
)
(

	input [DW-1:0] set_in,
	input [DW-1:0] rst_in,

	output [DW-1:0] qout,

	input CLK,
	input RSTn
);


wire [DW-1:0] rsffr_qout;
gen_rsffr # ( .DW(DW), .rstValue(rstValue)) rsffr ( .set_in(set_in), .rst_in(rst_in), .qout(rsffr_qout), .CLK(CLK), .RSTn(RSTn));


assign qout = set_in | rsffr_qout;

//ASSERT
always @( posedge CLK ) begin
	if ( set_in & rst_in ) begin
		$display("Assert Fail at gen_slff");
		$finish;
	end
end

endmodule
module gen_suffr # (
	parameter DW = 1,
	parameter rstValue = 1'b0
)
(

	input [DW-1:0] set_in,
	input [DW-1:0] rst_in,

	output [DW-1:0] qout,

	input CLK,
	input RSTn
);


wire [DW-1:0] rsffr_qout;
gen_rsffr # ( .DW(DW), .rstValue(rstValue)) rsffr ( .set_in(set_in), .rst_in(rst_in), .qout(rsffr_qout), .CLK(CLK), .RSTn(RSTn));


assign qout = ~rst_in & rsffr_qout;



//ASSERT
always @( posedge CLK ) begin
	if ( set_in & rst_in ) begin
		$display("Assert Fail at gen_suff");
		$finish;
	end
end

endmodule
module gen_dpdffren  #(
	parameter DW = 32,
	parameter rstValue = {DW{1'b0}}
)
(

	input [DW-1:0] dnxta,
	input ena,

	input [DW-1:0] dnxtb,
	input enb,

	output [DW-1:0] qout,

	input CLK,
	input RSTn
);

wire en;
wire [DW-1:0] dnxt;



assign en = ena | enb;
assign dnxt = 	{DW{ena}} & dnxta
				| 
				{DW{(~ena)&enb}} & dnxtb;


gen_dffren # ( .DW(DW), .rstValue(rstValue) ) dffren
(

	.dnxt(dnxt),
	.qout(qout),
	.en(en),

	.CLK(CLK),
	.RSTn(RSTn)
);




endmodule
module gen_ppbuff #
(
	parameter DW = 100,
	parameter DP = 8
)
(
	input pop,
	input push,
	input [$clog2(DP)-1:0] index,

	input [ DW - 1 : 0] info_i,	
	output [ DW*DP - 1 : 0] info_o,

	output empty,
	output full,
	output [DP - 1 : 0] valid,
	
	input flush,
	input CLK,
	input RSTn
	
);





	wire [ DW*DP - 1 : 0] info_dnxt;
	wire [ DW*DP - 1 : 0] info_qout;
	wire [DP-1 : 0] info_en;


	wire [DP-1:0] valid_dnxt;
	wire [DP-1:0] valid_qout;
	wire [DP-1:0] valid_en;




	generate
		for ( genvar dp = 0; dp < DP; dp = dp + 1 ) begin

			assign info_dnxt[DW*dp +: DW] = info_i;
			assign info_en[dp] = push & (dp == index);
			assign valid_dnxt[dp] = push & (~flush);
			assign valid_en[dp] = (pop | push | flush) & (dp == index);

			gen_dffren #(.DW(DW)) info_dffren
			( 	
				.dnxt(info_dnxt[DW*dp +: DW]),
				.qout(info_qout[DW*dp +: DW]),
				.en(info_en[dp]),
				.CLK(CLK), .RSTn(RSTn)
			);

			gen_dffren #(.DW(1)) valid_dffren
			(
				.dnxt(valid_dnxt[dp]),
				.qout(valid_qout[dp]),
				.en(valid_en[dp]),
				.CLK (CLK),
				.RSTn(RSTn)	
			);

		end
	endgenerate

	assign info_o = info_qout;
	assign valid = valid_qout;

	assign empty =  & (~valid);
	assign full = & valid;














endmodule
module gen_ringStack # (
	parameter DW = 64,
	parameter AW = 3
) (

	input stack_pop, 
	input stack_push,

	output stack_empty,

	output [DW-1:0] data_pop,
	input [DW-1:0] data_push,

	input flush,
	input CLK,
	input RSTn
);

	localparam DP = 2**AW;

	wire stack_full;
	wire [AW+1-1:0] btm_addr_dnxt, btm_addr_qout;
	wire [AW+1-1:0] top_addr_dnxt, top_addr_qout;
	wire [DP*DW-1:0] stack_data_dnxt, stack_data_qout;

	gen_dffr #(.DW(AW+1)) btm_addr   (.dnxt(btm_addr_dnxt), .qout(btm_addr_qout), .CLK(CLK), .RSTn(RSTn));
	gen_dffr #(.DW(AW+1)) top_addr  (.dnxt(top_addr_dnxt), .qout(top_addr_qout), .CLK(CLK), .RSTn(RSTn));

	assign stack_empty = (btm_addr_qout == top_addr_qout);
	assign stack_full = (btm_addr_qout[AW-1:0] == top_addr_qout[AW-1:0]) & (btm_addr_qout[AW] != top_addr_qout[AW]);

	wire [AW-1:0] read_addr = top_addr_qout[AW-1:0] - 'd1;
	wire [AW-1:0] write_addr = top_addr_qout[AW-1:0];


generate
	for ( genvar i = 0; i < DP; i = i + 1 ) begin
		assign stack_data_dnxt[DW*i+:DW] = (stack_push & (write_addr == i) ) ? data_push : stack_data_qout[DW*i+:DW];

		gen_dffr #(.DW(DW)) stack_data  (.dnxt(stack_data_dnxt[DW*i+:DW]), .qout(stack_data_qout[DW*i+:DW]), .CLK(CLK), .RSTn(RSTn));

	end
endgenerate




	assign data_pop = stack_data_qout[DW*read_addr+:DW];

	assign btm_addr_dnxt = flush ? {(AW+1){1'b0}} : ( (stack_push & stack_full) ? btm_addr_qout + 'd1 : btm_addr_qout );
	assign top_addr_dnxt = flush ? {(AW+1){1'b0}} : (({(AW+1){stack_push}} & (top_addr_qout + 'd1 ))
													|
													({(AW+1){stack_pop & ~stack_empty}} & (top_addr_qout - 'd1)) 
													|
													({(AW+1){~stack_push & ~(stack_pop & ~stack_empty)}} & top_addr_qout));

endmodule
module gen_bypassfifo #
(
	parameter DW = 64
)
(
	input valid_i,
	input [DW-1:0] data_i,
	output ready_i,

	output valid_o,
	output [DW-1:0] data_o,
	input ready_o,

	input flush,
	input CLK,
	input RSTn
);

wire fifo_empty;
wire fifo_full;
wire [DW-1:0] data_pop;




wire isLoad_set;
wire isLoad_rst;
wire isLoad_qout;

assign isLoad_set = valid_i & ~ready_o;
assign isLoad_rst = (ready_o & ~fifo_empty) | flush;
assign fifo_empty = ~isLoad_qout;
assign fifo_full = isLoad_qout;
gen_dffren # ( .DW(DW)) fifo_bypass ( .dnxt(data_i), .qout(data_pop), .en(isLoad_set), .CLK(CLK), .RSTn(RSTn));
gen_rsffr # ( .DW(1) ) isLoad ( .set_in(isLoad_set), .rst_in(isLoad_rst), .qout(isLoad_qout), .CLK(CLK), .RSTn(RSTn));





assign data_o = fifo_empty ? data_i : data_pop;
assign ready_i = ~fifo_full | flush;
assign valid_o = valid_i | ~fifo_empty; 






//ASSERT
always @( posedge CLK ) begin
	if ( fifo_full & valid_i ) begin
		$display("Assert Fail at bypass fifo");
		$finish;
	end
end











endmodule
module gen_syn #
(
	parameter lever = 2
)
(

	input data_asyn,
	output data_syn,

	input CLK,
	input RSTn
	
);



wire [lever-1 : 0] syn_dnxt;
wire [lever-1 : 0] syn_qout;

assign syn_dnxt = {syn_qout[lever-2:0], data_asyn};
assign data_syn = syn_qout[lever-1];

gen_dffr # ( .DW(lever) ) syn ( .dnxt(syn_dnxt), .qout(syn_qout), .CLK(CLK), .RSTn(RSTn) );



















endmodule
module dirty_block # 
(
	parameter DW = 32,
	parameter DP = 16 
)
(

	input push,
	input [DW-1:0] addr_i,

	input pop,
	output [DW-1:0] addr_o,

	output empty,
	output full,

	input CLK,
	input RSTn
);

localparam CW = $clog2(DP);


wire [CW-1:0] index;
wire [CW-1:0] index_push;
wire [CW-1:0] index_pop;
wire [DW*DP-1:0] info_o;

wire [DP-1:0] valid;
wire [DP-1:0] addr_chk;
wire push_chk;
wire ppbuff_full;


// push will be block when there is a same record in buff
generate
	for ( genvar i = 0 ; i < DP; i = i + 1 ) begin
		assign addr_chk[i] = valid[i] & (addr_i == (info_o[ DW*i +: DW]));
	end
endgenerate

	assign push_chk = push & ~(| addr_chk);





assign full = ppbuff_full & ~(| addr_chk);







gen_ppbuff # ( .DW(DW), .DP(DP) )
dirty_index
(
	.pop(pop),
	.push(push_chk),
	.index(index),

	.info_i(addr_i),	
	.info_o(info_o),

	.empty(empty),
	.full(ppbuff_full),
	.valid(valid),
	
	.flush(1'b0),
	.CLK(CLK),
	.RSTn(RSTn)
	
);


assign index = 	
		({CW{push_chk & ~pop}} & index_push)
		|
		({CW{pop & ~push_chk}} & index_pop)
		|
		({CW{pop & push_chk}} & index_pop);


assign addr_o = info_o[ DW*index_pop +: DW];


lzp #( .CW(CW) ) buff_push
(
	.in_i(valid),
	.pos_o(index_push),
	.all0(),
	.all1()
);


lzp #( .CW(CW) ) buff_pop
(
	.in_i(~valid),
	.pos_o(index_pop),
	.all0(),
	.all1()
);




endmodule
module cache_mem #
(
	parameter DW = 1024,
	parameter BK = 4,
	parameter CB = 1,
	parameter CL = 256,
	parameter TAG_W = 32

)
(
	input [31:0] cache_addr,
	input [CB-1:0] cache_en_w,
	input [CB-1:0] cache_en_r,
	input [7:0] cache_info_wstrb,
	input [63:0] cache_info_w,
	output [64*CB-1:0] cache_info_r,


	input [31:0] tag_addr,
	input [CB-1:0] tag_en_w,
	input [CB-1:0] tag_en_r,
	input [(TAG_W+7)/8-1:0] tag_info_wstrb,
	input [TAG_W-1:0] tag_info_w,
	output [TAG_W*CB-1:0] tag_info_r,

	input CLK,
	input RSTn
);

	localparam ADDR_LSB = $clog2(DW*BK/8);
	localparam LINE_W = $clog2(CL);


wire [$clog2(BK)-1:0] bank_sel = cache_addr[ ADDR_LSB-1 -: $clog2(BK)];
wire [LINE_W-1:0] cache_address_sel = cache_addr[ADDR_LSB +: LINE_W];
wire [$clog2(DW/8)-1:0] data_sel = cache_addr[ADDR_LSB-$clog2(BK)-1:0];

wire [LINE_W-1:0] tag_address_sel = tag_addr[ADDR_LSB +: LINE_W];
wire [TAG_W-1:0] tag_sel = tag_addr[31 -: TAG_W];

wire [CB*BK-1:0] cache_bank_en_w;
wire [CB*BK-1:0] cache_bank_en_r;
wire [DW*BK*CB-1:0] cache_bank_data_r;
wire [DW/8-1:0] cache_bank_wstrb = cache_info_wstrb << data_sel;


generate
	for ( genvar cb = 0 ; cb < CB; cb = cb + 1 ) begin

		gen_sram # ( .DW((TAG_W)), .AW(LINE_W)) tag_ram
		(
			.data_w(tag_info_w),
			.addr_w(tag_address_sel),
			.data_wstrb(tag_info_wstrb),
			.en_w(tag_en_w[cb]),

			.data_r(tag_info_r[TAG_W*cb +: TAG_W]),
			.addr_r(tag_address_sel),
			.en_r(tag_en_r[cb]),

			.CLK(CLK)		
		);

		for ( genvar bk = 0; bk < BK; bk = bk + 1 ) begin
			assign cache_bank_en_w[BK*cb+bk] = ( bank_sel == bk ) & cache_en_w[cb];
			assign cache_bank_en_r[BK*cb+bk] = ( bank_sel == bk ) & cache_en_r[cb];


			gen_sram # ( .DW(DW), .AW(LINE_W)) cache_bank_ram
			(
				.data_w({(DW/64){cache_info_w}}),
				.addr_w(cache_address_sel),
				.data_wstrb(cache_bank_wstrb),
				.en_w(cache_bank_en_w[cb*BK+bk]),

				.data_r(cache_bank_data_r[DW*(cb*BK+bk) +: DW]),
				.addr_r(cache_address_sel),
				.en_r(cache_bank_en_r[cb*BK+bk]),

				.CLK(CLK)		
			);

		end

	wire [DW*BK-1:0] cache_block_data_r = cache_bank_data_r[DW*BK*cb +: DW*BK];
	wire [DW-1:0] cache_data_r = cache_block_data_r[ DW*bank_sel +: DW ];
	assign cache_info_r[64*cb +: 64] = cache_data_r[ 8*data_sel +: 64];

	end
endgenerate












endmodule
module phyRegister (
	input flush,


	input  [(64*`RP*32)-1:0] regFileX_dnxt,
	output [(64*`RP*32)-1:0] regFileX_qout,


	input [ `RB*32 - 1 :0 ] rnAct_X_dnxt,
	output [ `RB*32 - 1 :0 ] rnAct_X_qout,

	input [32*`RP-1 : 0] rnBufU_rename_set,
	input [32*`RP-1 : 0] rnBufU_commit_rst,
	output [32*`RP-1 : 0] rnBufU_qout,

	input [32*`RP-1 : 0] wbLog_writeb_set,
	input [32*`RP-1 : 0] wbLog_commit_rst,
	output [32*`RP-1 : 0] wbLog_qout,

	input [ `RB*32 - 1 :0 ] archi_X_dnxt,
	output [ `RB*32 - 1 :0 ] archi_X_qout,

	input CLK,
	input RSTn
	
);
















//代表架构寄存器，指向128个寄存器中的地址，完成commit
//指向当前前端可以用的寄存器位置（只会读寄存器），读完不管,32个寄存器，每个可能深度为4
//架构寄存器在commit阶段更新，同时释放rename位置

generate
	for ( genvar i = 0 ; i < 32; i = i + 1 ) begin
		gen_dffr #(.DW(`RB)) archi_X ( .dnxt(archi_X_dnxt[`RB*i +: `RB]), .qout(archi_X_qout[`RB*i +: `RB]), .CLK(CLK), .RSTn(RSTn) );
	end
endgenerate


//读操作不会改变重命名活动指针，
//读操作需要通过重命名活动指针寻找正确的寄存器，
//写操作需要改变重命名活动指针到一个新位置，需要是空的，否则挂起流水线


generate
	for ( genvar i = 0 ; i < 32; i = i + 1 ) begin
		gen_dffr #(.DW(`RB)) 
		rnActive_X 
		( 
			.dnxt( {`RB{~flush}} & rnAct_X_dnxt[`RB*i +: `RB] 
					| {`RB{flush}} & archi_X_qout[`RB*i +: `RB]),
			.qout(rnAct_X_qout[`RB*i +: `RB]),
			.CLK(CLK),
			.RSTn(RSTn)
		);
	end
endgenerate


//指示128-32个寄存器组中哪些被用了
wire [32*`RP-1 : 0] rnBufU_dnxt;

generate
	for ( genvar i = 0; i < 32; i = i + 1 ) begin

		//commit的复位，重命名的置位
		assign rnBufU_dnxt[`RP*i +: `RP] = flush ? 
													(1'b1 << archi_X_qout[`RB*i +: `RB])
													: ( ( rnBufU_qout[`RP*i +: `RP] 
														| rnBufU_rename_set[`RP*i +: `RP] )
														& (~rnBufU_commit_rst[`RP*i +: `RP]));

		gen_dffr #(.DW(`RP), .rstValue(`RP'b1)) rnBufU ( .dnxt(rnBufU_dnxt[`RP*i +: `RP]), .qout(rnBufU_qout[`RP*i +: `RP]), .CLK(CLK), .RSTn(RSTn) );


	end

endgenerate



	//指示乱序写回是否完成,影响真数据冒险
	wire [32*`RP-1 : 0] wbLog_dnxt;

generate
	for ( genvar i = 0; i < 32; i = i + 1 ) begin

		//写回时置1，commit时复位
		assign wbLog_dnxt[`RP*i +: `RP] = flush ? 
											(1'b1 << archi_X_qout[`RB*i +: `RB])
											: 	(
													(wbLog_qout[`RP*i +: `RP] 
													| wbLog_writeb_set[`RP*i +: `RP])
													& ~wbLog_commit_rst[`RP*i +: `RP]);

		gen_dffr #(.DW(`RP), .rstValue(`RP'b1)) wbLog ( .dnxt(wbLog_dnxt[`RP*i +: `RP]), .qout(wbLog_qout[`RP*i +: `RP]), .CLK(CLK), .RSTn(RSTn) );

	end
endgenerate





regFiles i_regFiles
(
	.regFileX_dnxt(regFileX_dnxt),
	.regFileX_qout(regFileX_qout),

	.CLK(CLK),
	.RSTn(RSTn)
);








endmodule
module rename (

	output [ `RB*32 - 1 :0 ] rnAct_X_dnxt,
	input [ `RB*32 - 1 :0 ] rnAct_X_qout,	

	output [32*`RP-1 : 0] rnBufU_rename_set,
	input [32*`RP-1 : 0] rnBufU_qout,

	input [4:0] rs1_raw,
	output [5+`RB-1:0] rs1_reName,

	input [4:0] rs2_raw,
	output [5+`RB-1:0] rs2_reName,
	
	input rd0_raw_valid,
	input [4:0] rd0_raw,
	output [5+`RB-1:0] rd0_reName,
	output rd0_runOut

);


wire [`RB-1:0] rd0_malloc;
assign rd0_reName = {rd0_raw, rd0_malloc};

generate
	for ( genvar i = 0;  i < 32; i = i + 1 )begin
		assign rnAct_X_dnxt[`RB*i +: `RB] = ( (rd0_raw == i) & rd0_raw_valid & ~rd0_runOut ) ? rd0_malloc : rnAct_X_qout[`RB*i +: `RB];
	end
endgenerate
	

assign rs1_reName = {rs1_raw, rnAct_X_qout[rs1_raw*`RB +: `RB]};
assign rs2_reName = {rs2_raw, rnAct_X_qout[rs2_raw*`RB +: `RB]};



wire [`RP-1:0] regX_used = rnBufU_qout[ `RP*rd0_raw +: `RP ];

lzp #(
	.CW(`RB)
) rd0_index(
	.in_i(regX_used),
	.pos_o(rd0_malloc),
	.all0(),
	.all1(rd0_runOut)
);



assign rnBufU_rename_set = (rd0_raw_valid & ~rd0_runOut)
								? {32*`RP{1'b0}} | (1'b1 << rd0_reName)
								: {32*`RP{1'b0}};













endmodule
module regFiles
(

	output [(64*`RP*32)-1:0] regFileX_qout,
	input  [(64*`RP*32)-1:0] regFileX_dnxt,

	input CLK,
	input RSTn
);

assign regFileX_qout[64*`RP-1:0] = {64*`RP{1'b0}};

generate
	
	for ( genvar regNum = 1; regNum < 32; regNum = regNum + 1 ) begin
		for ( genvar depth = 0 ; depth < `RP; depth = depth + 1 ) begin

			localparam  SEL = regNum*4+depth;

			gen_dffr  #(.DW(64)) int_regX ( .dnxt(regFileX_dnxt[64*SEL +: 64]), .qout(regFileX_qout[64*SEL +: 64]), .CLK(CLK), .RSTn(RSTn) );

		end
	end



endgenerate









endmodule
module writeBack (

	//from phyRegister
	input  [(64*`RP*32)-1:0] regFileX_qout,
	output [(64*`RP*32)-1:0] regFileX_dnxt,

	output [32*`RP-1 : 0] wbLog_writeb_set,


	//from adder
	input alu_writeback_valid,
	input [63:0] alu_res,
	input [(5+`RB-1):0] alu_rd0,

	//from bru
	input bru_writeback_valid,
	input [(5+`RB-1):0] bru_rd0,
	input [63:0] bru_res,

	//from lsu
	input lsu_writeback_valid,
	input [(5+`RB-1):0] lsu_rd0,
	input [63:0] lsu_res,

	//from csr
	input csr_writeback_valid,
	input [(5+`RB-1):0] csr_rd0,
	input [63:0] csr_res,

	//from mul
	input mul_writeback_valid,
	input [(5+`RB-1):0] mul_rd0,
	input [63:0] mul_res
);

// alu wb
wire [(64*`RP*32)-1:0] alu_writeback_dnxt;
//bru wb
wire [(64*`RP*32)-1:0] bru_writeback_dnxt;
//lsu wb
wire [(64*`RP*32)-1:0] lsu_writeback_dnxt;
//csr wb
wire [(64*`RP*32)-1:0] csr_writeback_dnxt;
//mul wb
wire [(64*`RP*32)-1:0] mul_writeback_dnxt;

//write back
assign regFileX_dnxt[0 +: 64*`RP] = {64*`RP{1'b0}};
generate
	for ( genvar SEL = `RP; SEL < 32*`RP; SEL = SEL + 1 ) begin
			// localparam  SEL = regNum*`RP+depth;

			assign regFileX_dnxt[64*SEL +: 64] =  
				(
					//adder wb
					({64{alu_writeback_valid & (alu_rd0 == SEL)}} & alu_res)
					|
					//bru wb
					({64{bru_writeback_valid & (bru_rd0 == SEL)}} & bru_res)
					|
					//lsu wb
					({64{lsu_writeback_valid & (lsu_rd0 == SEL)}} & lsu_res)
					|
					//csr wb
					({64{csr_writeback_valid & (csr_rd0 == SEL)}} & csr_res)
					|
					//mul wb
					({64{mul_writeback_valid & (mul_rd0 == SEL)}} & mul_res)
				)
				|
				(
					//nobody wb
					( 
						 
						{64{  ~(alu_writeback_valid & alu_rd0 == SEL)
							& ~(bru_writeback_valid & bru_rd0 == SEL)
							& ~(lsu_writeback_valid & lsu_rd0 == SEL)
							& ~(csr_writeback_valid & csr_rd0 == SEL)
							& ~(mul_writeback_valid & mul_rd0 == SEL) }}
					) 
					& regFileX_qout[64*SEL +: 64]
				);



	end
endgenerate


	assign wbLog_writeb_set = 
		( alu_writeback_valid << alu_rd0 )
		| 
		( bru_writeback_valid << bru_rd0 )
		| 
		( lsu_writeback_valid << lsu_rd0 )
		| 
		( csr_writeback_valid << csr_rd0 )
		| 
		( mul_writeback_valid << mul_rd0 )
		;





endmodule
module iAlign (

	input [63:0] ic_iq_pc,
	input [63:0] ic_iq_instr,

	output [63:0] align_instr,
	output [3:0] align_instr_mask

);

	wire [2:0] pc_lsb = ic_iq_pc[2:0];


	assign align_instr = 
			( {64{pc_lsb == 3'b000}} & ic_iq_instr)
			|
			( {64{pc_lsb == 3'b010}} & {16'b0, ic_iq_instr[63:16]} )
			|
			( {64{pc_lsb == 3'b100}} & {32'b0, ic_iq_instr[63:32]})
			|
			( {64{pc_lsb == 3'b110}} & {48'b0, ic_iq_instr[63:48]});

	assign align_instr_mask = 
			( {4{pc_lsb == 3'b000}} & 4'b1111)
			|
			( {4{pc_lsb == 3'b010}} & 4'b0111 )
			|
			( {4{pc_lsb == 3'b100}} & 4'b0011)
			|
			( {4{pc_lsb == 3'b110}} & 4'b0001);





endmodule
module branch_predict (
	input isFencei,
	input lsu_fencei_valid,
	output fencei_stall,

	input isJal,
	input isJalr,
	input isBranch,
	input isCall,
	input isReturn,
	input [63:0] imm,
	input isRVC,
	input [63:0] pc_load,

	input jalr_valid,
	input [63:0] jalr_pc,
	input bru_res_valid,
	input bru_takenBranch,

	output branch_pc_valid,
	output [63:0] branch_pc,
	output isMisPredict,

	output jalr_stall,
	output bht_stall,
	input iq_id_ready,

	input flush,
	input CLK,
	input RSTn

);




	wire [63:0] next_pc;
	wire [63:0] take_pc;
	wire [63:0] resolve_pc; 

	wire [63+1:0] bht_data_pop;
	wire [63+1:0] bht_data_push;

	wire isTakenBranch;
	wire bht_full;
	wire bht_pop;
	wire bht_push;

	wire jalr_stall;
	wire bht_stall;

	wire [63:0] ras_addr_pop;
	wire [63:0] ras_addr_push;
	wire ras_push;
	wire ras_pop;
	wire ras_empty;
	wire jalr_empty;
	wire jalr_last;
	wire jalr_front;



	assign bht_data_push = 
				{
					isTakenBranch, 
					(({64{~isTakenBranch}} & take_pc) | ({64{isTakenBranch}} & next_pc))
				};


	assign bht_pop = bru_res_valid;
	assign bht_push = isBranch & ~bht_full & iq_id_ready;

	assign isMisPredict = bru_res_valid & ( bru_takenBranch ^ bht_data_pop[64]);
	assign resolve_pc = bht_data_pop[63:0];

	assign jalr_stall = isJalr & ~jalr_last & ( ras_empty | ~isReturn );
	assign bht_stall = (bht_full & isBranch);
	assign fencei_stall = isFencei & ~lsu_fencei_valid;


	assign branch_pc_valid = 
							isMisPredict //mis-predict
							| isTakenBranch // bru jump, jal jump, jalr ras pop
							| jalr_last //jalr return
							| (isFencei & lsu_fencei_valid)
								;


	assign branch_pc = ({64{isMisPredict}} & resolve_pc)
						|
						({64{isTakenBranch& ~isMisPredict}} & take_pc)
						|
						({64{jalr_last}} & jalr_pc )
						|
						({64{isFencei & lsu_fencei_valid}} & next_pc);



	//static predict
	assign isTakenBranch = ( (isBranch) & ( imm[63] == 1'b0) )
							| (isJal | ras_pop); 






	assign ras_push = isCall & ( isJal | isJalr ) & iq_id_ready;
	assign ras_pop = isReturn & ( isJalr ) & ( !ras_empty ) & iq_id_ready;

	assign next_pc = pc_load + ( isRVC ? 64'd2 : 64'd4 );
	assign take_pc = ( {64{isJal | isBranch}} & (pc_load + imm) )
						| ( {64{ras_pop}} & ras_addr_pop );

	assign ras_addr_push = next_pc;





	gen_fifo # ( .DW(64+1), .AW(4) ) bht(
		.fifo_pop(bht_pop), .fifo_push(bht_push),
		.data_push(bht_data_push), .data_pop(bht_data_pop),
		.fifo_empty(), .fifo_full(bht_full), 
		
		.flush(flush),
		.CLK(CLK),
		.RSTn(RSTn)
	);




	assign jalr_last = jalr_valid & jalr_empty;
	assign jalr_front = jalr_valid & ~jalr_empty;


	gen_ringStack # (.DW(64), .AW(4)) ras(
		.stack_pop(ras_pop), .stack_push(ras_push),
		.stack_empty(ras_empty),
		.data_pop(ras_addr_pop), .data_push(ras_addr_push),

		.flush(flush),
		.CLK(CLK),
		.RSTn(RSTn)
	);

	gen_fifo # ( .DW(1), .AW(4) ) ras_cnt(
		.fifo_pop(jalr_front), .fifo_push(ras_pop),
		.data_push(1'b0), .data_pop(),
		.fifo_empty(jalr_empty), .fifo_full(), 
		
		.flush(flush),
		.CLK(CLK),
		.RSTn(RSTn)
	);








endmodule
module preDecode (
	input [255:0] instr_load,
	input [15:0] iq_instr_mask_load,

	output instr_buf_empty,
	output isJal,
	output isJalr,
	output isBranch,
	output isCall,
	output isReturn,
	output isRVC,
	output isFencei,
	output [63:0] imm
);

	assign instr_buf_empty = ((iq_instr_mask_load[1] != 1'b1) & instr_load[1:0] == 2'b11)
							|
							((iq_instr_mask_load[0] != 1'b1) );

	wire [31:0] instr = instr_load[31:0];

	assign isRVC = ~instr_buf_empty & (instr[1:0] != 2'b11);

	wire isIJal = ~isRVC & (instr[6:0] == 7'b1101111);			
	wire isCJal =	 instr[1:0] == 2'b01 & instr[15:13] == 3'b101;

	wire isIJalr = ~isRVC & (instr[6:0] == 7'b1100111);
	wire isCJalr = (instr[1:0] == 2'b10 & instr[15:13] == 3'b100)
					&
					(
						(~instr[12] & (instr[6:2] == 0)) 
						| 
						( instr[12] & (|instr[11:7]) & (&(~instr[6:2])))
					);

	wire isIBranch = ~isRVC & (instr[6:0] == 7'b1100011);
	wire isCBranch = instr[1:0] == 2'b01 & instr[15:14] == 2'b11;

	wire isICall = (isIJalr | isIJal) & ((instr[11:7] == 5'd1) | instr[11:7] == 5'd5);
	wire isCCall = isCJalr & instr[12];

	wire isIReturn = isIJalr & ((instr[19:15] == 5'd1) | instr[19:15] == 5'd5)
									& (instr[19:15] != instr[11:7]);

	wire isCReturn = isCJalr & ~instr[12]
							& ((instr[11:7] == 5'd1) | (instr[11:7] == 5'd5));


	wire [63:0] Iimm = 
		({64{isIJal}} & {{44{instr[31]}},instr[19:12],instr[20],instr[30:21],1'b0})
		|
		({64{isIJalr}} & {{52{instr[31]}},instr[31:20]})
		|
		({64{isIBranch}} & {{52{instr[31]}},instr[7],instr[30:25],instr[11:8],1'b0});

	wire [63:0] Cimm = 
		({64{isCJal}} & {{52{instr[12]}}, instr[12], instr[8], instr[10:9], instr[6], instr[7], instr[2], instr[11], instr[5:3], 1'b0})
		|
		({64{isCJalr}} & 64'b0)
		|
		({64{isCBranch}} & {{55{instr[12]}}, instr[12], instr[6:5], instr[2], instr[11:10], instr[4:3], 1'b0});

	assign isJal = ~instr_buf_empty & (isIJal | isCJal); 
	assign isJalr = ~instr_buf_empty & (isIJalr | isCJalr);
	assign isBranch = ~instr_buf_empty & (isIBranch | isCBranch);
	assign isCall = ~instr_buf_empty & (isICall | isCCall);
	assign isReturn = ~instr_buf_empty & (isIReturn | isCReturn);

	assign isFencei = (instr[6:0] == 7'b0001111) & (instr[14:12] == 3'b001);

	assign imm = isRVC ? Cimm : Iimm;


endmodule
module decoder
(
	input iq_id_valid,
	output iq_id_ready,
	input [32+64+1-1:0] iq_id_info,

	input instrFifo_reject,
	output [`DECODE_INFO_DW-1:0] decode_microInstr,
	output instrFifo_push,

	input flush,
	input CLK,
	input RSTn

);







	wire [`DECODE_INFO_DW-1:0] decode_microInstr_16;
	wire [`DECODE_INFO_DW-1:0] decode_microInstr_32;


	wire bp_valid_i;
	wire bp_valid_o;
	wire bp_ready_i;
	wire bp_ready_o;

	wire [32+64+1-1:0] bp_data_i;
	wire [32+64+1-1:0] bp_data_o;

	assign iq_id_ready = ~instrFifo_reject & bp_ready_i;

	assign bp_valid_i = iq_id_valid;
	assign bp_ready_o = ~instrFifo_reject;
	assign bp_data_i = iq_id_info;

gen_bypassfifo #( .DW(32+64+1) ) bp_fifo
(
	.valid_i(bp_valid_i),
	.data_i(bp_data_i),
	.ready_i(bp_ready_i),

	.valid_o(bp_valid_o),
	.data_o(bp_data_o),
	.ready_o(bp_ready_o),

	.flush(flush),
	.CLK(CLK),
	.RSTn(RSTn)
);


	wire privil_accessFault;
	wire [`DECODE_INFO_DW-1:0] accessFault_info;

	wire [63:0] id_pc = bp_data_o[64:1];
	wire [31:0] id_instr32 = bp_data_o[96:65];
	wire [15:0] id_instr16 = bp_data_o[80:65];
	wire isRVC = bp_data_o[0];

	assign privil_accessFault = bp_valid_o & bp_ready_o & ( |id_pc[63:32] );



	assign accessFault_info = { 1'b0, 1'b0, 1'b0, 1'b0,
		1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 
		1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0,
		1'b0, 1'b0, 1'b0, 1'b0,
		1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0,
		1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0,
		1'b0, 1'b0,
		1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0,
		1'b0, 1'b0, 1'b0,
		1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0,
		1'b1, 1'b0,
		1'b0,
		id_pc, 64'b0, 6'b0, 5'd0,5'b0,5'b0
		};







decoder16 i_decoder16
(
	.instr(id_instr16),
	.pc(id_pc),
	.is_rvc(isRVC),

	.decode_microInstr(decode_microInstr_16)
);



decoder32 i_decoder32
(
	.instr(id_instr32),
	.pc(id_pc),
	.is_rvc(isRVC),

	.decode_microInstr(decode_microInstr_32)
);


	assign decode_microInstr = (~privil_accessFault) ? 
								(isRVC ? decode_microInstr_16 : decode_microInstr_32)
								: accessFault_info;
	assign instrFifo_push = bp_valid_o & ~instrFifo_reject;






endmodule
module pcGenerate (

	// from expection 	
	input [63:0] privileged_pc,
	input privileged_valid,

	//from instr_queue,
	input branch_pc_valid,
	input [63:0] branch_pc,

	//to ifetch
	output [63:0] fetch_addr_qout,
	input pcGen_fetch_ready,

	input flush,
	input CLK,
	input RSTn

);


	wire [63:0] fetch_addr_dnxt;






	assign fetch_addr_dnxt = 
				privileged_valid ? privileged_pc : 
					(branch_pc_valid ?  branch_pc :  ( (fetch_addr_qout&(~64'b111)) + 64'd8));






	gen_dffren # (.DW(64), .rstValue(64'h8000_0000)) fetch_addr_en ( .dnxt(fetch_addr_dnxt), .qout(fetch_addr_qout), .en(pcGen_fetch_ready|flush), .CLK(CLK), .RSTn(RSTn));













endmodule