dakies/OSS_Verilog huggingface dataset:
module itlb_mr_blk_cm2(
	clka,
	ena,
	wea,
	addra,
	dina,
	clkb,
	addrb,
	doutb);


input clka;
input ena;
input [0 : 0] wea;
input [6 : 0] addra;
input [13 : 0] dina;
input clkb;
input [6 : 0] addrb;
output [13 : 0] doutb;

`ifdef BLK_MEM_GEN

// synthesis translate_off

      BLK_MEM_GEN_V3_1 #(
		.C_ADDRA_WIDTH(7),
		.C_ADDRB_WIDTH(7),
		.C_ALGORITHM(1),
		.C_BYTE_SIZE(9),
		.C_COMMON_CLK(0),
		.C_DEFAULT_DATA("0"),
		.C_DISABLE_WARN_BHV_COLL(0),
		.C_DISABLE_WARN_BHV_RANGE(0),
		.C_FAMILY("virtex5"),
		.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_INITA_VAL("0"),
		.C_INITB_VAL("0"),
		.C_INIT_FILE_NAME("no_coe_file_loaded"),
		.C_LOAD_INIT_FILE(0),
		.C_MEM_TYPE(1),
		.C_MUX_PIPELINE_STAGES(0),
		.C_PRIM_TYPE(1),
		.C_READ_DEPTH_A(128),
		.C_READ_DEPTH_B(128),
		.C_READ_WIDTH_A(14),
		.C_READ_WIDTH_B(14),
		.C_RSTRAM_A(0),
		.C_RSTRAM_B(0),
		.C_RST_PRIORITY_A("CE"),
		.C_RST_PRIORITY_B("CE"),
		.C_RST_TYPE("SYNC"),
		.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_WEA_WIDTH(1),
		.C_WEB_WIDTH(1),
		.C_WRITE_DEPTH_A(128),
		.C_WRITE_DEPTH_B(128),
		.C_WRITE_MODE_A("READ_FIRST"),
		.C_WRITE_MODE_B("READ_FIRST"),
		.C_WRITE_WIDTH_A(14),
		.C_WRITE_WIDTH_B(14),
		.C_XDEVICEFAMILY("virtex5"))
	inst (
		.CLKA(clka),
		.ENA(ena),
		.WEA(wea),
		.ADDRA(addra),
		.DINA(dina),
		.CLKB(clkb),
		.ADDRB(addrb),
		.DOUTB(doutb),
		.RSTA(),
		.REGCEA(),
		.DOUTA(),
		.RSTB(),
		.ENB(),
		.REGCEB(),
		.WEB(),
		.DINB(),
		.INJECTSBITERR(),
		.INJECTDBITERR(),
		.SBITERR(),
		.DBITERR(),
		.RDADDRECC());


// synthesis translate_on

`else

reg	[6:0]	addrb_reg;		// RAM address register

always @(posedge clka)
		addrb_reg <= #1 addrb;


//
// Generic RAM's registers and wires
//
reg	[13:0]	mem [(1<<7)-1:0];	// RAM content

//
// Data output drivers
//
assign doutb = mem[addrb_reg];

//
// RAM write
//
always @(posedge clka)
	if (ena && wea)
		mem[addra] <= #1 dina;

`endif


endmodule
module rf_sub_cm2(
		cmls,
		
	a,
	d,
	dpra,
	clk,
	we,
	spo,
	dpo);


input cmls;




input [4 : 0] a;
input [31 : 0] d;
input [4 : 0] dpra;
input clk;
input we;
output [31 : 0] spo;
output [31 : 0] dpo;

rf_dist_cm2 rf_disti(
	.a({cmls, a}),
	.d(d),
	.dpra({cmls, dpra}),
	.clk(clk),
	.we(we),
	.spo(spo),
	.dpo(dpo));


endmodule
module ic_ram_blk_cm2(
	clka,
	ena,
	wea,
	addra,
	dina,
	clkb,
	addrb,
	doutb);


input clka;
input ena;
input [0 : 0] wea;
input [11 : 0] addra;
input [31 : 0] dina;
input clkb;
input [11 : 0] addrb;
output [31 : 0] doutb;

`ifdef BLK_MEM_GEN

// synthesis translate_off

      BLK_MEM_GEN_V3_1 #(
		.C_ADDRA_WIDTH(12),
		.C_ADDRB_WIDTH(12),
		.C_ALGORITHM(1),
		.C_BYTE_SIZE(9),
		.C_COMMON_CLK(0),
		.C_DEFAULT_DATA("0"),
		.C_DISABLE_WARN_BHV_COLL(0),
		.C_DISABLE_WARN_BHV_RANGE(0),
		.C_FAMILY("virtex5"),
		.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_INITA_VAL("0"),
		.C_INITB_VAL("0"),
		.C_INIT_FILE_NAME("no_coe_file_loaded"),
		.C_LOAD_INIT_FILE(0),
		.C_MEM_TYPE(1),
		.C_MUX_PIPELINE_STAGES(0),
		.C_PRIM_TYPE(1),
		.C_READ_DEPTH_A(4096),
		.C_READ_DEPTH_B(4096),
		.C_READ_WIDTH_A(32),
		.C_READ_WIDTH_B(32),
		.C_RSTRAM_A(0),
		.C_RSTRAM_B(0),
		.C_RST_PRIORITY_A("CE"),
		.C_RST_PRIORITY_B("CE"),
		.C_RST_TYPE("SYNC"),
		.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_WEA_WIDTH(1),
		.C_WEB_WIDTH(1),
		.C_WRITE_DEPTH_A(4096),
		.C_WRITE_DEPTH_B(4096),
		.C_WRITE_MODE_A("READ_FIRST"),
		.C_WRITE_MODE_B("READ_FIRST"),
		.C_WRITE_WIDTH_A(32),
		.C_WRITE_WIDTH_B(32),
		.C_XDEVICEFAMILY("virtex5"))
	inst (
		.CLKA(clka),
		.ENA(ena),
		.WEA(wea),
		.ADDRA(addra),
		.DINA(dina),
		.CLKB(clkb),
		.ADDRB(addrb),
		.DOUTB(doutb),
		.RSTA(),
		.REGCEA(),
		.DOUTA(),
		.RSTB(),
		.ENB(),
		.REGCEB(),
		.WEB(),
		.DINB(),
		.INJECTSBITERR(),
		.INJECTDBITERR(),
		.SBITERR(),
		.DBITERR(),
		.RDADDRECC());


// synthesis translate_on

`else

reg	[11:0]	addrb_reg;		// RAM address register

always @(posedge clka)
		addrb_reg <= #1 addrb;

//
// Generic RAM's registers and wires
//
reg	[31:0]	mem [(1<<12)-1:0];	// RAM content

//
// Data output drivers
//
assign doutb = mem[addrb_reg];

//
// RAM write
//
always @(posedge clka)
	if (ena && wea)
		mem[addra] <= #1 dina;

`endif

endmodule
module itlb_tr_blk_cm2(
	clka,
	ena,
	wea,
	addra,
	dina,
	clkb,
	addrb,
	doutb);


input clka;
input ena;
input [0 : 0] wea;
input [6 : 0] addra;
input [21 : 0] dina;
input clkb;
input [6 : 0] addrb;
output [21 : 0] doutb;

`ifdef BLK_MEM_GEN

// synthesis translate_off

      BLK_MEM_GEN_V3_1 #(
		.C_ADDRA_WIDTH(7),
		.C_ADDRB_WIDTH(7),
		.C_ALGORITHM(1),
		.C_BYTE_SIZE(9),
		.C_COMMON_CLK(0),
		.C_DEFAULT_DATA("0"),
		.C_DISABLE_WARN_BHV_COLL(0),
		.C_DISABLE_WARN_BHV_RANGE(0),
		.C_FAMILY("virtex5"),
		.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_INITA_VAL("0"),
		.C_INITB_VAL("0"),
		.C_INIT_FILE_NAME("no_coe_file_loaded"),
		.C_LOAD_INIT_FILE(0),
		.C_MEM_TYPE(1),
		.C_MUX_PIPELINE_STAGES(0),
		.C_PRIM_TYPE(1),
		.C_READ_DEPTH_A(128),
		.C_READ_DEPTH_B(128),
		.C_READ_WIDTH_A(22),
		.C_READ_WIDTH_B(22),
		.C_RSTRAM_A(0),
		.C_RSTRAM_B(0),
		.C_RST_PRIORITY_A("CE"),
		.C_RST_PRIORITY_B("CE"),
		.C_RST_TYPE("SYNC"),
		.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_WEA_WIDTH(1),
		.C_WEB_WIDTH(1),
		.C_WRITE_DEPTH_A(128),
		.C_WRITE_DEPTH_B(128),
		.C_WRITE_MODE_A("READ_FIRST"),
		.C_WRITE_MODE_B("READ_FIRST"),
		.C_WRITE_WIDTH_A(22),
		.C_WRITE_WIDTH_B(22),
		.C_XDEVICEFAMILY("virtex5"))
	inst (
		.CLKA(clka),
		.ENA(ena),
		.WEA(wea),
		.ADDRA(addra),
		.DINA(dina),
		.CLKB(clkb),
		.ADDRB(addrb),
		.DOUTB(doutb),
		.RSTA(),
		.REGCEA(),
		.DOUTA(),
		.RSTB(),
		.ENB(),
		.REGCEB(),
		.WEB(),
		.DINB(),
		.INJECTSBITERR(),
		.INJECTDBITERR(),
		.SBITERR(),
		.DBITERR(),
		.RDADDRECC());


// synthesis translate_on

`else

reg	[6:0]	addrb_reg;		// RAM address register

always @(posedge clka)
		addrb_reg <= #1 addrb;

//
// Generic RAM's registers and wires
//
reg	[21:0]	mem [(1<<7)-1:0];	// RAM content

//
// Data output drivers
//
assign doutb = mem[addrb_reg];

//
// RAM write
//
always @(posedge clka)
	if (ena && wea)
		mem[addra] <= #1 dina;

`endif


endmodule
module dtlb_mr_blk_cm2(
	clka,
	ena,
	wea,
	addra,
	dina,
	clkb,
	addrb,
	doutb);


input clka;
input ena;
input [0 : 0] wea;
input [6 : 0] addra;
input [13 : 0] dina;
input clkb;
input [6 : 0] addrb;
output [13 : 0] doutb;

`ifdef BLK_MEM_GEN

// synthesis translate_off

      BLK_MEM_GEN_V3_1 #(
		.C_ADDRA_WIDTH(7),
		.C_ADDRB_WIDTH(7),
		.C_ALGORITHM(1),
		.C_BYTE_SIZE(9),
		.C_COMMON_CLK(0),
		.C_DEFAULT_DATA("0"),
		.C_DISABLE_WARN_BHV_COLL(0),
		.C_DISABLE_WARN_BHV_RANGE(0),
		.C_FAMILY("virtex5"),
		.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_INITA_VAL("0"),
		.C_INITB_VAL("0"),
		.C_INIT_FILE_NAME("no_coe_file_loaded"),
		.C_LOAD_INIT_FILE(0),
		.C_MEM_TYPE(1),
		.C_MUX_PIPELINE_STAGES(0),
		.C_PRIM_TYPE(1),
		.C_READ_DEPTH_A(128),
		.C_READ_DEPTH_B(128),
		.C_READ_WIDTH_A(14),
		.C_READ_WIDTH_B(14),
		.C_RSTRAM_A(0),
		.C_RSTRAM_B(0),
		.C_RST_PRIORITY_A("CE"),
		.C_RST_PRIORITY_B("CE"),
		.C_RST_TYPE("SYNC"),
		.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_WEA_WIDTH(1),
		.C_WEB_WIDTH(1),
		.C_WRITE_DEPTH_A(128),
		.C_WRITE_DEPTH_B(128),
		.C_WRITE_MODE_A("READ_FIRST"),
		.C_WRITE_MODE_B("READ_FIRST"),
		.C_WRITE_WIDTH_A(14),
		.C_WRITE_WIDTH_B(14),
		.C_XDEVICEFAMILY("virtex5"))
	inst (
		.CLKA(clka),
		.ENA(ena),
		.WEA(wea),
		.ADDRA(addra),
		.DINA(dina),
		.CLKB(clkb),
		.ADDRB(addrb),
		.DOUTB(doutb),
		.RSTA(),
		.REGCEA(),
		.DOUTA(),
		.RSTB(),
		.ENB(),
		.REGCEB(),
		.WEB(),
		.DINB(),
		.INJECTSBITERR(),
		.INJECTDBITERR(),
		.SBITERR(),
		.DBITERR(),
		.RDADDRECC());


// synthesis translate_on

`else

reg	[6:0]	addrb_reg;		// RAM address register

always @(posedge clkb)
		addrb_reg <= #1 addrb;


//
// Generic RAM's registers and wires
//
reg	[13:0]	mem [(1<<7)-1:0];	// RAM content

//
// Data output drivers
//
assign doutb = mem[addrb_reg];

//
// RAM write
//
always @(posedge clka)
	if (ena && wea)
		mem[addra] <= #1 dina;

`endif


endmodule
module dc_ram_sub_cm2(
		clk_i_cml_1,
		cmls,
		
	clka,
	ena,
	wea,
	addra,
	dina,
	clkb,
	addrb,
	doutb);


input clk_i_cml_1;
input cmls;




input clka;
input ena;
input [3 : 0] wea;
input [10 : 0] addra;
input [31 : 0] dina;
input clkb;
input [10 : 0] addrb;
output [31 : 0] doutb;

wire ena_wire;
wire [3 : 0] wea_wire;
wire [10 : 0] addra_wire;
wire [31 : 0] dina_wire;
wire [10 : 0] addrb_wire;

assign ena_wire = ena;
assign wea_wire = wea;
assign addra_wire = addra;
assign dina_wire = dina;
assign addrb_wire = addrb;

dc_ram_blk_cm2 dc_ram_blki(
	.clka(clka),
	.ena(ena_wire),
	//.regcea(1'b1),
	.wea(wea_wire),
	.addra({cmls, addra_wire}),
	.dina(dina_wire),
	.clkb(clkb),
	.addrb({cmls, addrb_wire}),
	.doutb(doutb));

endmodule
module or1200_gmultp2_32x32_cm2 (
		clk_i_cml_1,
		 X, Y, CLK, RST, P );


input clk_i_cml_1;
reg [ 64 - 1 : 0 ] p0_cml_1;
reg [ 64 - 1 : 0 ] p1_cml_1;



input   [`OR1200_W-1:0]  X;
input   [`OR1200_W-1:0]  Y;
input           CLK;
input           RST;
output  [`OR1200_WW-1:0]  P;

reg     [`OR1200_WW-1:0]  p0;
reg     [`OR1200_WW-1:0]  p1;
integer 		  xi;
integer 		  yi;

//
// Conversion unsigned to signed
//
always @(X)
	xi <= X;

//
// Conversion unsigned to signed
//
always @(Y)
	yi <= Y;

//
// First multiply stage
//


// SynEDA CoreMultiplier
// assignment(s): p0
// replace(s): p0
always @(posedge CLK) begin  p0 <= p0_cml_1; 
                p0 <= #1 xi * yi; end


//
// Second multiply stage
//

// SynEDA CoreMultiplier
// assignment(s): p1
// replace(s): p0, p1
always @(posedge CLK or posedge RST)
        if (RST)
                p1 <= `OR1200_WW'b0;
        else begin  p1 <= p1_cml_1;
                p1 <= #1 p0_cml_1; end


// SynEDA CoreMultiplier
// assignment(s): P
// replace(s): p1
assign P = p1_cml_1;


always @ (posedge clk_i_cml_1) begin
p0_cml_1 <= p0;
p1_cml_1 <= p1;
end
endmodule
module or1200_gmultp2_32x32_cm2 (
		clk_i_cml_1,
		 X, Y, CLK, RST, P );


input clk_i_cml_1;
reg [ 64 - 1 : 0 ] p0_cml_1;
reg [ 64 - 1 : 0 ] p1_cml_1;



input   [`OR1200_W-1:0]  X;
input   [`OR1200_W-1:0]  Y;
input           CLK;
input           RST;
output  [`OR1200_WW-1:0]  P;

reg     [`OR1200_WW-1:0]  p0;
reg     [`OR1200_WW-1:0]  p1;
integer 		  xi;
integer 		  yi;

//
// Conversion unsigned to signed
//
always @(X)
	xi <= X;

//
// Conversion unsigned to signed
//
always @(Y)
	yi <= Y;

//
// First multiply stage
//


// SynEDA CoreMultiplier
// assignment(s): p0
// replace(s): p0
always @(posedge CLK) 
                p0 <= #1 xi * yi;


//
// Second multiply stage
//

// SynEDA CoreMultiplier
// assignment(s): p1
// replace(s): p0, p1
always @(posedge CLK) 
		p1 <= #1 p0_cml_1; 


// SynEDA CoreMultiplier
// assignment(s): P
// replace(s): p1
assign P = p1_cml_1;


always @ (posedge CLK) begin
p0_cml_1 <= p0;
p1_cml_1 <= p1;
end

endmodule
module or1200_reg2mem_cm2(
		clk_i_cml_1,
		addr, lsu_op, regdata, memdata);


input clk_i_cml_1;
reg [ 4 - 1 : 0 ] lsu_op_cml_1;
reg [ 32 - 1 : 0 ] regdata_cml_1;



parameter width = `OR1200_OPERAND_WIDTH;

//
// I/O
//
input	[1:0]			addr;
input	[`OR1200_LSUOP_WIDTH-1:0]	lsu_op;
input	[width-1:0]		regdata;
output	[width-1:0]		memdata;

//
// Internal regs and wires
//
reg	[7:0]			memdata_hh;
reg	[7:0]			memdata_hl;
reg	[7:0]			memdata_lh;
reg	[7:0]			memdata_ll;

assign memdata = {memdata_hh, memdata_hl, memdata_lh, memdata_ll};

//
// Mux to memdata[31:24]
//

// SynEDA CoreMultiplier
// assignment(s): memdata_hh
// replace(s): lsu_op, regdata
always @(lsu_op_cml_1 or addr or regdata_cml_1) begin
	casex({lsu_op_cml_1, addr[1:0]})	// synopsys parallel_case
		{`OR1200_LSUOP_SB, 2'b00} : memdata_hh = regdata_cml_1[7:0];
		{`OR1200_LSUOP_SH, 2'b00} : memdata_hh = regdata_cml_1[15:8];
		default : memdata_hh = regdata_cml_1[31:24];
	endcase
end

//
// Mux to memdata[23:16]
//

// SynEDA CoreMultiplier
// assignment(s): memdata_hl
// replace(s): lsu_op, regdata
always @(lsu_op_cml_1 or addr or regdata_cml_1) begin
	casex({lsu_op_cml_1, addr[1:0]})	// synopsys parallel_case
		{`OR1200_LSUOP_SW, 2'b00} : memdata_hl = regdata_cml_1[23:16];
		default : memdata_hl = regdata_cml_1[7:0];
	endcase
end

//
// Mux to memdata[15:8]
//

// SynEDA CoreMultiplier
// assignment(s): memdata_lh
// replace(s): lsu_op, regdata
always @(lsu_op_cml_1 or addr or regdata_cml_1) begin
	casex({lsu_op_cml_1, addr[1:0]})	// synopsys parallel_case
		{`OR1200_LSUOP_SB, 2'b10} : memdata_lh = regdata_cml_1[7:0];
		default : memdata_lh = regdata_cml_1[15:8];
	endcase
end

//
// Mux to memdata[7:0]
//

// SynEDA CoreMultiplier
// assignment(s): memdata_ll
// replace(s): regdata
always @(regdata_cml_1)
	memdata_ll = regdata_cml_1[7:0];


always @ (posedge clk_i_cml_1) begin
lsu_op_cml_1 <= lsu_op;
regdata_cml_1 <= regdata;
end
endmodule
module or1200_wbmux_cm2(
		clk_i_cml_1,
		
	// Clock and reset
	clk, rst,

	// Internal i/f
	wb_freeze, rfwb_op,
	muxin_a, muxin_b, muxin_c, muxin_d,
	muxout, muxreg, muxreg_valid
);


input clk_i_cml_1;
reg [ 3 - 1 : 0 ] rfwb_op_cml_1;
reg [ 32 - 1 : 0 ] muxin_a_cml_1;
reg [ 32 - 1 : 0 ] muxreg_cml_1;
reg  muxreg_valid_cml_1;



parameter width = `OR1200_OPERAND_WIDTH;

//
// I/O
//

//
// Clock and reset
//
input				clk;
input				rst;

//
// Internal i/f
//
input				wb_freeze;
input	[`OR1200_RFWBOP_WIDTH-1:0]	rfwb_op;
input	[width-1:0]		muxin_a;
input	[width-1:0]		muxin_b;
input	[width-1:0]		muxin_c;
input	[width-1:0]		muxin_d;
output	[width-1:0]		muxout;
output	[width-1:0]		muxreg;
output				muxreg_valid;

//
// Internal wires and regs
//
reg	[width-1:0]		muxout;
reg	[width-1:0]		muxreg;
reg				muxreg_valid;

//
// Registered output from the write-back multiplexer
//

// SynEDA CoreMultiplier
// assignment(s): muxreg, muxreg_valid
// replace(s): muxreg, rfwb_op, muxreg_valid
always @(posedge clk or posedge rst) begin
	if (rst) begin
		muxreg <= #1 32'd0;
		muxreg_valid <= #1 1'b0;
	end
	else begin  muxreg_valid <= muxreg_valid_cml_1; muxreg <= muxreg_cml_1; if (!wb_freeze) begin
		muxreg <= #1 muxout;
		muxreg_valid <= #1 rfwb_op_cml_1[0];
	end end
end

//
// Write-back multiplexer
//

// SynEDA CoreMultiplier
// assignment(s): muxout
// replace(s): rfwb_op, muxin_a
always @(muxin_a_cml_1 or muxin_b or muxin_c or muxin_d or rfwb_op_cml_1) begin
`ifdef OR1200_ADDITIONAL_SYNOPSYS_DIRECTIVES
	case(rfwb_op_cml_1[`OR1200_RFWBOP_WIDTH-1:1]) // synopsys parallel_case infer_mux
`else
	case(rfwb_op_cml_1[`OR1200_RFWBOP_WIDTH-1:1]) // synopsys parallel_case
`endif
		2'b00: muxout = muxin_a_cml_1;
		2'b01: begin
			muxout = muxin_b;
`ifdef OR1200_VERBOSE
// synopsys translate_off
			$display("  WBMUX: muxin_b %h", muxin_b);
// synopsys translate_on
`endif
		end
		2'b10: begin
			muxout = muxin_c;
`ifdef OR1200_VERBOSE
// synopsys translate_off
			$display("  WBMUX: muxin_c %h", muxin_c);
// synopsys translate_on
`endif
		end
		2'b11: begin
			muxout = muxin_d + 32'h8;
`ifdef OR1200_VERBOSE
// synopsys translate_off
			$display("  WBMUX: muxin_d %h", muxin_d + 4'h8);
// synopsys translate_on
`endif
		end
	endcase
end


always @ (posedge clk_i_cml_1) begin
rfwb_op_cml_1 <= rfwb_op;
muxin_a_cml_1 <= muxin_a;
muxreg_cml_1 <= muxreg;
muxreg_valid_cml_1 <= muxreg_valid;
end
endmodule
module or1200_gmultp2_32x32_cm4 (
		clk_i_cml_1,
		clk_i_cml_2,
		clk_i_cml_3,
		 X, Y, CLK, RST, P );


input clk_i_cml_1;
input clk_i_cml_2;
input clk_i_cml_3;
reg [ 64 - 1 : 0 ] p0_cml_3;
reg [ 64 - 1 : 0 ] p0_cml_2;
reg [ 64 - 1 : 0 ] p0_cml_1;
reg [ 64 - 1 : 0 ] p1_cml_3;
reg [ 64 - 1 : 0 ] p1_cml_2;
reg [ 64 - 1 : 0 ] p1_cml_1;



input   [`OR1200_W-1:0]  X;
input   [`OR1200_W-1:0]  Y;
input           CLK;
input           RST;
output  [`OR1200_WW-1:0]  P;

reg     [`OR1200_WW-1:0]  p0;
reg     [`OR1200_WW-1:0]  p1;
integer 		  xi;
integer 		  yi;

//
// Conversion unsigned to signed
//
always @(X)
	xi <= X;

//
// Conversion unsigned to signed
//
always @(Y)
	yi <= Y;

//
// First multiply stage
//


// SynEDA CoreMultiplier
// assignment(s): p0
// replace(s): p0
always @(posedge CLK) 
                p0 <= #1 xi * yi; 


//
// Second multiply stage
//

// SynEDA CoreMultiplier
// assignment(s): p1
// replace(s): p0, p1
always @(posedge CLK)
                p1 <= #1 p0_cml_3; 


// SynEDA CoreMultiplier
// assignment(s): P
// replace(s): p1
assign P = p1_cml_3;


always @ (posedge clk_i_cml_1) begin
p0_cml_1 <= p0;
p1_cml_1 <= p1;
end
always @ (posedge clk_i_cml_2) begin
p0_cml_2 <= p0_cml_1;
p1_cml_2 <= p1_cml_1;
end
always @ (posedge clk_i_cml_3) begin
p0_cml_3 <= p0_cml_2;
p1_cml_3 <= p1_cml_2;
end
endmodule
module or1200_reg2mem_cm4(
		clk_i_cml_1,
		clk_i_cml_2,
		clk_i_cml_3,
		addr, lsu_op, regdata, memdata);


input clk_i_cml_1;
input clk_i_cml_2;
input clk_i_cml_3;
reg [ 1 : 0 ] addr_cml_3;
reg [ 4 - 1 : 0 ] lsu_op_cml_3;
reg [ 4 - 1 : 0 ] lsu_op_cml_2;
reg [ 4 - 1 : 0 ] lsu_op_cml_1;
reg [ 32 - 1 : 0 ] regdata_cml_3;
reg [ 32 - 1 : 0 ] regdata_cml_2;
reg [ 32 - 1 : 0 ] regdata_cml_1;



parameter width = `OR1200_OPERAND_WIDTH;

//
// I/O
//
input	[1:0]			addr;
input	[`OR1200_LSUOP_WIDTH-1:0]	lsu_op;
input	[width-1:0]		regdata;
output	[width-1:0]		memdata;

//
// Internal regs and wires
//
reg	[7:0]			memdata_hh;
reg	[7:0]			memdata_hl;
reg	[7:0]			memdata_lh;
reg	[7:0]			memdata_ll;

assign memdata = {memdata_hh, memdata_hl, memdata_lh, memdata_ll};

//
// Mux to memdata[31:24]
//

// SynEDA CoreMultiplier
// assignment(s): memdata_hh
// replace(s): addr, lsu_op, regdata
always @(lsu_op_cml_3 or addr_cml_3 or regdata_cml_3) begin
	casex({lsu_op_cml_3, addr_cml_3[1:0]})	// synopsys parallel_case
		{`OR1200_LSUOP_SB, 2'b00} : memdata_hh = regdata_cml_3[7:0];
		{`OR1200_LSUOP_SH, 2'b00} : memdata_hh = regdata_cml_3[15:8];
		default : memdata_hh = regdata_cml_3[31:24];
	endcase
end

//
// Mux to memdata[23:16]
//

// SynEDA CoreMultiplier
// assignment(s): memdata_hl
// replace(s): addr, lsu_op, regdata
always @(lsu_op_cml_3 or addr_cml_3 or regdata_cml_3) begin
	casex({lsu_op_cml_3, addr_cml_3[1:0]})	// synopsys parallel_case
		{`OR1200_LSUOP_SW, 2'b00} : memdata_hl = regdata_cml_3[23:16];
		default : memdata_hl = regdata_cml_3[7:0];
	endcase
end

//
// Mux to memdata[15:8]
//

// SynEDA CoreMultiplier
// assignment(s): memdata_lh
// replace(s): addr, lsu_op, regdata
always @(lsu_op_cml_3 or addr_cml_3 or regdata_cml_3) begin
	casex({lsu_op_cml_3, addr_cml_3[1:0]})	// synopsys parallel_case
		{`OR1200_LSUOP_SB, 2'b10} : memdata_lh = regdata_cml_3[7:0];
		default : memdata_lh = regdata_cml_3[15:8];
	endcase
end

//
// Mux to memdata[7:0]
//

// SynEDA CoreMultiplier
// assignment(s): memdata_ll
// replace(s): regdata
always @(regdata_cml_3)
	memdata_ll = regdata_cml_3[7:0];


always @ (posedge clk_i_cml_1) begin
lsu_op_cml_1 <= lsu_op;
regdata_cml_1 <= regdata;
end
always @ (posedge clk_i_cml_2) begin
lsu_op_cml_2 <= lsu_op_cml_1;
regdata_cml_2 <= regdata_cml_1;
end
always @ (posedge clk_i_cml_3) begin
addr_cml_3 <= addr;
lsu_op_cml_3 <= lsu_op_cml_2;
regdata_cml_3 <= regdata_cml_2;
end
endmodule
module or1200_gmultp2_32x32_cm4 (
		clk_i_cml_1,
		clk_i_cml_2,
		clk_i_cml_3,
		 X, Y, CLK, RST, P );


input clk_i_cml_1;
input clk_i_cml_2;
input clk_i_cml_3;
reg [ 64 - 1 : 0 ] p0_cml_3;
reg [ 64 - 1 : 0 ] p0_cml_2;
reg [ 64 - 1 : 0 ] p0_cml_1;
reg [ 64 - 1 : 0 ] p1_cml_3;
reg [ 64 - 1 : 0 ] p1_cml_2;
reg [ 64 - 1 : 0 ] p1_cml_1;



input   [`OR1200_W-1:0]  X;
input   [`OR1200_W-1:0]  Y;
input           CLK;
input           RST;
output  [`OR1200_WW-1:0]  P;

reg     [`OR1200_WW-1:0]  p0;
reg     [`OR1200_WW-1:0]  p1;
integer 		  xi;
integer 		  yi;

//
// Conversion unsigned to signed
//
always @(X)
	xi <= X;

//
// Conversion unsigned to signed
//
always @(Y)
	yi <= Y;

//
// First multiply stage
//


// SynEDA CoreMultiplier
// assignment(s): p0
// replace(s): p0
always @(posedge CLK) 
                p0 <= #1 xi * yi; 


//
// Second multiply stage
//

// SynEDA CoreMultiplier
// assignment(s): p1
// replace(s): p0, p1
always @(posedge CLK)
                p1 <= #1 p0_cml_3; 


// SynEDA CoreMultiplier
// assignment(s): P
// replace(s): p1
assign P = p1_cml_3;


always @ (posedge CLK) begin
p0_cml_1 <= p0;
p1_cml_1 <= p1;
p0_cml_2 <= p0_cml_1;
p1_cml_2 <= p1_cml_1;
p0_cml_3 <= p0_cml_2;
p1_cml_3 <= p1_cml_2;
end
endmodule
module or1200_wbmux_cm4(
		clk_i_cml_1,
		clk_i_cml_2,
		clk_i_cml_3,
		
	// Clock and reset
	clk, rst,

	// Internal i/f
	wb_freeze, rfwb_op,
	muxin_a, muxin_b, muxin_c, muxin_d,
	muxout, muxreg, muxreg_valid
);


input clk_i_cml_1;
input clk_i_cml_2;
input clk_i_cml_3;
reg  wb_freeze_cml_3;
reg [ 3 - 1 : 0 ] rfwb_op_cml_3;
reg [ 3 - 1 : 0 ] rfwb_op_cml_2;
reg [ 3 - 1 : 0 ] rfwb_op_cml_1;
reg [ 32 - 1 : 0 ] muxin_a_cml_2;
reg [ 32 - 1 : 0 ] muxin_d_cml_2;
reg [ 32 - 1 : 0 ] muxout_cml_3;
reg [ 32 - 1 : 0 ] muxreg_cml_3;
reg [ 32 - 1 : 0 ] muxreg_cml_2;
reg [ 32 - 1 : 0 ] muxreg_cml_1;
reg  muxreg_valid_cml_3;
reg  muxreg_valid_cml_2;
reg  muxreg_valid_cml_1;



parameter width = `OR1200_OPERAND_WIDTH;

//
// I/O
//

//
// Clock and reset
//
input				clk;
input				rst;

//
// Internal i/f
//
input				wb_freeze;
input	[`OR1200_RFWBOP_WIDTH-1:0]	rfwb_op;
input	[width-1:0]		muxin_a;
input	[width-1:0]		muxin_b;
input	[width-1:0]		muxin_c;
input	[width-1:0]		muxin_d;
output	[width-1:0]		muxout;
output	[width-1:0]		muxreg;
output				muxreg_valid;

//
// Internal wires and regs
//
reg	[width-1:0]		muxout;
reg	[width-1:0]		muxreg;
reg				muxreg_valid;

//
// Registered output from the write-back multiplexer
//

// SynEDA CoreMultiplier
// assignment(s): muxreg, muxreg_valid
// replace(s): wb_freeze, muxout, muxreg, rfwb_op, muxreg_valid
always @(posedge clk or posedge rst) begin
	if (rst) begin
		muxreg <= #1 32'd0;
		muxreg_valid <= #1 1'b0;
	end
	else begin  muxreg_valid <= muxreg_valid_cml_3; muxreg <= muxreg_cml_3; if (!wb_freeze_cml_3) begin
		muxreg <= #1 muxout_cml_3;
		muxreg_valid <= #1 rfwb_op_cml_3[0];
	end end
end

//
// Write-back multiplexer
//

// SynEDA CoreMultiplier
// assignment(s): muxout
// replace(s): rfwb_op, muxin_a, muxin_d
always @(muxin_a_cml_2 or muxin_b or muxin_c or muxin_d_cml_2 or rfwb_op_cml_2) begin
`ifdef OR1200_ADDITIONAL_SYNOPSYS_DIRECTIVES
	case(rfwb_op_cml_2[`OR1200_RFWBOP_WIDTH-1:1]) // synopsys parallel_case infer_mux
`else
	case(rfwb_op_cml_2[`OR1200_RFWBOP_WIDTH-1:1]) // synopsys parallel_case
`endif
		2'b00: muxout = muxin_a_cml_2;
		2'b01: begin
			muxout = muxin_b;
`ifdef OR1200_VERBOSE
// synopsys translate_off
			$display("  WBMUX: muxin_b %h", muxin_b);
// synopsys translate_on
`endif
		end
		2'b10: begin
			muxout = muxin_c;
`ifdef OR1200_VERBOSE
// synopsys translate_off
			$display("  WBMUX: muxin_c %h", muxin_c);
// synopsys translate_on
`endif
		end
		2'b11: begin
			muxout = muxin_d_cml_2 + 32'h8;
`ifdef OR1200_VERBOSE
// synopsys translate_off
			$display("  WBMUX: muxin_d %h", muxin_d + 4'h8);
// synopsys translate_on
`endif
		end
	endcase
end


always @ (posedge clk_i_cml_1) begin
rfwb_op_cml_1 <= rfwb_op;
muxreg_cml_1 <= muxreg;
muxreg_valid_cml_1 <= muxreg_valid;
end
always @ (posedge clk_i_cml_2) begin
rfwb_op_cml_2 <= rfwb_op_cml_1;
muxin_a_cml_2 <= muxin_a;
muxin_d_cml_2 <= muxin_d;
muxreg_cml_2 <= muxreg_cml_1;
muxreg_valid_cml_2 <= muxreg_valid_cml_1;
end
always @ (posedge clk_i_cml_3) begin
wb_freeze_cml_3 <= wb_freeze;
rfwb_op_cml_3 <= rfwb_op_cml_2;
muxout_cml_3 <= muxout;
muxreg_cml_3 <= muxreg_cml_2;
muxreg_valid_cml_3 <= muxreg_valid_cml_2;
end
endmodule
module TRIPUTER( RCLK, RST_N, SSW, UA_TX, UA_RX, SRCO, SRAA, SRDB, HEXM, HEXL, LEDR, LEDG, AUD_XCK, HDMI_CLK );

	input			RCLK;
	input 			RST_N;

	input 	 [9:0]	SSW;

	input			UA_RX;
	output			UA_TX;

	output	 [4:0]	SRCO;
	output	[17:0]	SRAA;
	inout	[15:0]	SRDB;

	output	 [6:0]	HEXM,HEXL;
	output	 [9:0]	LEDR;
	output	 [7:0]	LEDG;
	
	output			AUD_XCK,HDMI_CLK;	// only driving 0

	reg		[31:0]	BOOT_ROM [0:511];	// 2 kByte
	reg		[31:0]	BOOT_Q;

	wire	[31:0]	AA;
	wire			NMI_N;
	wire			BCLK;
	wire			DC_ACC;	
	wire			DC_WR;
	wire			DC_MDONE;
	wire	[31:0]	DIN;
	wire	[28:0]	DRAM_ADR;
	wire	[35:0]	DRAM_DI;
	wire   [127:0]	DRAM_Q;
	wire	[31:0]	DRD;
	wire			DC_INHIBIT;
	wire			IC_ACC;
	wire			IC_MDONE;
	wire	[28:0]	IDRAM_ADR;
	wire			IC_INHIBIT;
	wire			READ;
	wire			READY;
	wire	 [3:0]	STATUS;
	wire			ENDRAM;
	wire			ENWR;
	wire			WRITE;
	wire	 [3:0]	BE;
	wire			CESRAM;
	wire	[31:0]	SRAM_Q;
	wire			SRAM_RDY;
	wire			BRESET;
	wire			INT_N;
	wire			UART_RD;
	wire	 [1:0]	UART_WR;
	wire	[31:0]	UART_Q;

	assign BCLK = RCLK;
	assign AUD_XCK = 1'b0;
	assign HDMI_CLK = 1'b0;

M32632	CPU(
	.BCLK(BCLK),
	.BRESET(BRESET),
	.DRAMSZ(3'b010),
	.NMI_N(NMI_N),
	.INT_N(~INT_N),
	.IC_MDONE(IC_MDONE),
	.IC_INHIBIT(IC_INHIBIT),
	.DRAM_Q(DRAM_Q),
	.ENWR(ENWR),
	.DC_MDONE(DC_MDONE),
	.DC_INHIBIT(DC_INHIBIT),
	.ENDRAM(ENDRAM),
	.COP_DONE(1'b0),
	.COP_IN(64'd0),
	.HOLD(1'b1),
	.DMA_CHK(1'b0),
	.DMA_AA(25'd0),
	.IO_READY(READY),
	.IO_Q(DRD),
// Outputs:
	.STATUS(STATUS),
	.ILO(),
	.STATSIGS(),
	.IC_ACC(IC_ACC),
	.IDRAM_ADR(IDRAM_ADR),
	.DC_WR(DC_WR),
	.DC_ACC(DC_ACC),
	.DRAM_ADR(DRAM_ADR),
	.DRAM_DI(DRAM_DI),
	.COP_GO(),
	.COP_OP(),
	.COP_OUT(),
	.HLDA(),
	.IO_RD(READ),
	.IO_WR(WRITE),
	.IO_A(AA),
	.IO_BE(BE),
	.IO_DI(DIN) );

DRAM_MOD	DRAM(
	.MCLK(BCLK),
	.RST_N(BRESET),
	.IC_ACC(IC_ACC),
	.IDRAM_ADR(IDRAM_ADR),
	.DC_WR(DC_WR),
	.DC_ACC(DC_ACC),
	.DRAM_ADR(DRAM_ADR),
	.DRAM_DI(DRAM_DI),
	.IC_MDONE(IC_MDONE),
	.IC_INHIBIT(IC_INHIBIT),
	.MEM_Q(DRAM_Q),
	.ENWR(ENWR),
	.DC_MDONE(DC_MDONE),
	.DC_INHIBIT(DC_INHIBIT) );


MAINDEC	 MDEC(
	.BCLK(BCLK),
	.WRITE(WRITE),
	.READ(READ),
	.ADDR(AA[31:2]),
	.STATUS(STATUS),
	.IO_DI(DIN),
	.SRAM_RDY(SRAM_RDY),
	.SRAM_Q(SRAM_Q),
	.BOOT_Q(BOOT_Q),
	.UART_Q(UART_Q),
	.BE(BE),
	.RST_N(RST_N),
	.SSW(SSW),
	.READY(READY),
	.DRD(DRD),
	.ENDRAM(ENDRAM),
	.BRESET(BRESET),
	.LEDR(LEDR),
	.LEDG(LEDG),
	.HEXM(HEXM),
	.HEXL(HEXL),
	.NMI_N(NMI_N),
	.UART_RD(UART_RD),
	.UART_WR(UART_WR),
	.CESRAM(CESRAM)	);

UART	SERIF(
	.BCLK(BCLK),
	.BRESET(BRESET),
	.UART_RD(UART_RD),
	.UART_WR(UART_WR),
	.DIN(DIN[15:0]),
	.UART_Q(UART_Q),
	.UA_INT(INT_N),
	.UA_RX(UA_RX),
	.UA_TX(UA_TX) );

SRAM	SRAMIF(
	.BCLK(BCLK),
	.BRESET(BRESET),
	.CESRAM(CESRAM),
	.WRITE(WRITE),
	.AA(AA[18:1]),
	.DIN(DIN),
	.BE(BE),
	.SRAM_Q(SRAM_Q),
	.READY(SRAM_RDY),
	.SRCO(SRCO),
	.SRAA(SRAA),
	.SRDB(SRDB) );
	
initial
	begin
		$readmemh("boot_rom.txt", BOOT_ROM);
	end
	
	always @(posedge BCLK) BOOT_Q <= BOOT_ROM[AA[10:2]];	

endmodule
module TRIPUTER_SIMU;

reg 			RCLK;
reg 			RST_N;
wire 	 [9:0]	SSW;
wire			UA_TX;
reg				UA_RX;
wire 	 [4:0]	SRCO;
wire 	[17:0]	SRAA;
wire 	[15:0]	SRDB;
wire 	 [6:0]	HEXM;
wire 	 [6:0]	HEXL;
wire 	 [9:0]	LEDR;
wire 	 [7:0]	LEDG;
wire 			AUD_XCK;
wire 			HDMI_CLK;

TRIPUTER CHIP(
	RCLK,
	RST_N,
	SSW,
	UA_TX,
	UA_RX,
	SRCO,
	SRAA,
	SRDB,
	HEXM,
	HEXL,
	LEDR,
	LEDG,
	AUD_XCK,
	HDMI_CLK);
	
	reg		 [7:0]	memh [8191:0];	// 16 KB in total
	reg		 [7:0]	meml [8191:0];
	reg		 [7:0]	ramh_q,raml_q;

initial // Clock generator
  begin
    RCLK = 0;
    #10 forever #10 RCLK = !RCLK;
  end
  
initial  
	begin
	 RST_N = 1'b0;
	 #105 RST_N = 1'b1;
	end
	
initial
	begin
	 UA_RX = 1'b1;
	 #100000 UA_RX = 1'b0;
	  #17360 UA_RX = 1'b1;
	  #34720 UA_RX = 1'b0;
	  #52080 UA_RX = 1'b1;
	  #17360 UA_RX = 1'b0;
	  #34720 UA_RX = 1'b1;
	end
			
	assign SSW = 10'd0;

	assign SRDB = SRCO[3] ? 16'hzzzz : {ramh_q,raml_q};

	always @(posedge SRCO[2])	// WE
		begin
			if (!SRCO[1]) memh[SRAA[12:0]] <= SRDB[15:8];
			if (!SRCO[0]) meml[SRAA[12:0]] <= SRDB[7:0];
		end
		
	always @(negedge RCLK)	// OE
		begin
			if (!SRCO[3]) ramh_q <= memh[SRAA[12:0]];
			if (!SRCO[3]) raml_q <= meml[SRAA[12:0]];
		end

endmodule
module SFPU_MUL ( BCLK, SRC1, SRC2, NZEXP, OUT);

	input			BCLK;
	input	[31:0]	SRC1,SRC2;	// only exponent of input data used
	input	 [2:1]	NZEXP;		// Flags of input data
	
	output	reg	[36:0]	OUT;		// The result

	wire	[47:0]	mresult;
	wire	 [9:0]	exponent,expoh,expol;
	wire	 [1:0]	restlow,resthigh;
	wire			zero,sign,orlow;
		
	assign mresult = {1'b1,SRC1[22:0]} * {1'b1,SRC2[22:0]};	// Unsigned Multiplier

	assign zero = 	~NZEXP[2] | ~NZEXP[1];	// one of both NULL -> NULL is the result
	assign sign = 	(SRC1[31] ^ SRC2[31]) & ~zero;
	assign orlow = 	(mresult[21:0] != 22'b0);
	
	assign restlow  = {mresult[22],orlow};
	assign resthigh = {mresult[23],(mresult[22] | orlow)};
	
	assign exponent = {2'b00,SRC1[30:23]} + {2'b00,SRC2[30:23]};
	assign expoh    = exponent - 10'h07E;
	assign expol	= exponent - 10'h07F;	// for MSB if mresult=0
	
	always @(posedge BCLK) OUT <= mresult[47] ? {zero,sign,expoh,mresult[46:24],resthigh}
											  : {zero,sign,expol,mresult[45:23],restlow};
	
endmodule
module PROG_COUNTER ( BCLK, BRESET, NEW, LOAD_PC, NEW_PC, NEXT_ADR, NEXT_PCA, DISP, PC_NEW, USED, USER, SAVE_PC, FPU_TRAP,
					  ADIVAR, PC_ARCHI, PC_ICACHE, PC_SAVE, ALSB, IC_USER);

	input			BCLK,BRESET;
	input			NEW;
	input			LOAD_PC;
	input			NEW_PC;
	input			NEXT_ADR;
	input			NEXT_PCA;
	input	[31:0]	DISP;
	input	[31:0]	PC_NEW;
	input	 [2:0]	USED;
	input			USER;
	input			SAVE_PC;
	input			FPU_TRAP;
	input			ADIVAR;
	
	output	[31:0]	PC_ARCHI;	// goes to Datapath
	output	[31:0]	PC_ICACHE;
	output	[31:0]	PC_SAVE;	// is the return address
	output	 [1:0]	ALSB;
	output			IC_USER;
	
	reg		[31:0]	PC_ARCHI;
	reg		[31:0]	pc_adduse;
	reg		[31:0]	pc_ic_reg;
	reg		[31:0]	fpu_trap_pc;
	reg				IC_USER;
	
	wire	[31:0]	branch,pc_jump,pc_icache_i;
	
	assign PC_SAVE = pc_adduse + {29'h0,USED};
	assign branch  = PC_ARCHI + DISP;
	
	assign pc_jump = LOAD_PC ? PC_NEW : branch;
	
	always @(posedge BCLK or negedge BRESET)
		if (!BRESET) pc_adduse <= 32'h0;
		  else
			pc_adduse <= NEW ? pc_jump : PC_SAVE;	// Only at NEW is the DISP correct !
			
	// The Architectur - PC : Address mode "Programm Memory"-relativ
	// no BRESET because NEXT_PCA is immediately valid
	always @(posedge BCLK)
		if (FPU_TRAP) PC_ARCHI <= fpu_trap_pc;	// go back !
		  else
			if (NEXT_PCA) PC_ARCHI <= pc_adduse;
	
	always @(posedge BCLK) if (SAVE_PC) fpu_trap_pc <= PC_ARCHI;	// Special storage for PC for FPU Trap
	
	always @(posedge BCLK or negedge BRESET)
		if (!BRESET) pc_ic_reg <= 32'h0;
		  else
			pc_ic_reg <= pc_icache_i;
		
	// NEW is only one cycle long - but in pc_adduse is the PC stored when ACC_OK is not there and therefore NEW_PC
	// is used to initiate a new access in ICACHE
	assign pc_icache_i = NEW_PC ? (NEW ? pc_jump : pc_adduse) : (NEXT_ADR ? ({pc_ic_reg[31:2],2'b00} + 32'h0000_0004) : pc_ic_reg);
	
	// This MUX is extra for LMR IVAR,... and CINV build in
	assign PC_ICACHE = {(ADIVAR ? PC_NEW[31:4] : pc_icache_i[31:4]),pc_icache_i[3:0]};
	
	assign ALSB = pc_ic_reg[1:0];	// for OPDEC_REG
	
	// The IC_USER flag is allowed to switch synchronously with one cycle delay to PC_ICACHE
	always @(posedge BCLK or negedge BRESET)
		if (!BRESET) IC_USER <= 1'b0;
		  else
			if (NEW_PC) IC_USER <= USER;
	
endmodule
module REG_LIST ( DIN, IPOS, INIT, OPOS, VALID);

	// Detects set bits in register list for SAVE/RESTORE & ENTER/EXIT

	input	 [7:0]	DIN;
	input	 [2:0]	IPOS;
	input			INIT;
	output	 [2:0]	OPOS;
	output			VALID;
	
	reg		 [7:1]	filter;
	wire	 [7:0]	mdat_0;
	wire	 [3:0]	mdat_1;

	always @(IPOS or DIN)
		case (IPOS)
		  3'd0 : filter =  DIN[7:1];
		  3'd1 : filter = {DIN[7:2],1'b0};
		  3'd2 : filter = {DIN[7:3],2'b0};
		  3'd3 : filter = {DIN[7:4],3'b0};
		  3'd4 : filter = {DIN[7:5],4'b0};
		  3'd5 : filter = {DIN[7:6],5'b0};
		  3'd6 : filter = {DIN[7]  ,6'b0};
		  3'd7 : filter =           7'b0;
		endcase
		
	assign mdat_0  = INIT ? DIN : {filter,1'b0};
	assign OPOS[2] = (mdat_0[3:0] == 4'h0);
	assign mdat_1  = OPOS[2] ? mdat_0[7:4] : mdat_0[3:0];
	assign OPOS[1] =   (mdat_1[1:0] == 2'b00);
	assign OPOS[0] = ~((mdat_1[2:1] == 2'b10) | mdat_1[0]);
	assign VALID   =   (mdat_1 != 4'b0000);
	
endmodule
module FP_STAT_REG ( BCLK, BRESET, LFSR, UP_SP, UP_DP, TT_SP, TT_DP, WREN, WRADR, DIN, FSR, TWREN, FPU_TRAP, SAVE_PC);
	
	input			BCLK;
	input			BRESET;
	input			LFSR;	// Load by LFSR opcode
	input			UP_SP,UP_DP;	// update if calculation operation
	input 	 [4:0]	TT_SP,TT_DP;
	input			WREN;	// for RMB and LFSR
	input	 [5:4]	WRADR;
	input 	[16:0] 	DIN;	// Data for LFSR opcode
	
	output	[31:0] 	FSR;
	output			TWREN;
	output	reg		FPU_TRAP;
	output			SAVE_PC;
	
	reg		 [4:3]	trap_d;
	reg				update_d;
	reg				set_rm_d;
	reg		[10:0]	set_bits;
	reg		 [4:0]	flags;
	reg				rm_bit;
	
	wire			load_fsr;
	wire			update,update_i;
	wire	 [4:0]	trap;
	wire			uflag,iflag,rmflag;

	assign load_fsr = LFSR & WREN;
	
	assign trap = UP_SP ? TT_SP : TT_DP;
	
	// This signal suppresses write into registers if FPU Trap, timing critical signal !
	assign TWREN = ~((UP_SP & (TT_SP[2:0] != 3'b0)) | (UP_DP & (TT_DP[2:0] != 3'b0)));
	
	always @(posedge BCLK or negedge BRESET)
		if (!BRESET) FPU_TRAP <= 1'b0;
		  else FPU_TRAP <= ~FPU_TRAP & ~TWREN;	// one pulse of one cycle informs the Opcode Decoder
				
	assign update_i = (UP_SP | UP_DP) & ~FPU_TRAP;	// unfortunately one FPU opcode may follow !
	always @(posedge BCLK) update_d	<= update_i;
	always @(posedge BCLK) trap_d	<= trap[4:3];
	always @(posedge BCLK) set_rm_d	<= WREN & (WRADR == 2'b10);
	assign update = update_d & ~FPU_TRAP;
	
	// The Flags are set and stay "1" 
	assign iflag  = (update & trap_d[4]) | flags[4];	// Inexact Result
	assign uflag  = (update & trap_d[3]) | flags[3];	// Underflow
	assign rmflag = (set_rm_d & ~FPU_TRAP) | rm_bit;	// Register Modify

	always @(posedge BCLK or negedge BRESET)
		if (!BRESET) flags[4:3] <= 2'b0;	// Inexact = Bit6, Underflow = Bit4
		  else
		  begin
			if (load_fsr) flags[4:3] <= {DIN[6],DIN[4]};
			  else
				if (update) flags[4:3] <= {iflag,uflag};
		  end
		  
	always @(posedge BCLK or negedge BRESET)
		if (!BRESET) flags[2:0] <= 3'b0;	// TT Field = Bit2-0
		  else
		  begin
			if (load_fsr) flags[2:0] <= DIN[2:0];
			  else
				if (update_i) flags[2:0] <= trap[2:0];
		  end
		  
	always @(posedge BCLK or negedge BRESET)
		if (!BRESET) rm_bit <= 1'b0;	// Register Modify Bit
		  else
		  begin
			if (load_fsr) rm_bit <= DIN[16];
			  else
				if (set_rm_d & ~FPU_TRAP) rm_bit <= 1'b1;	// in case of TRAP there is no writing to Register
		  end
		
	always @(posedge BCLK or negedge BRESET)
		if (!BRESET) set_bits <= 11'b0;	// all other Bits
		  else
			if (load_fsr) set_bits <= {DIN[15:7],DIN[5],DIN[3]};

	assign FSR = {15'h0,rmflag,set_bits[10:2],iflag,set_bits[1],uflag,set_bits[0],flags[2:0]};
	
	assign SAVE_PC = (UP_SP | UP_DP) & ~FPU_TRAP;	// Store the correct PC for FPU Trap
	
endmodule
module REGISTER( BCLK, ENWR, DOWR, BYDIN, DIN, RADR, WADR, WMASKE, DOUT, SELI );

input			BCLK;
input			DOWR,ENWR;
input	[31:0]	BYDIN,DIN;
input	 [7:0]	RADR;
input	 [5:0]	WADR;
input	 [1:0]	WMASKE;

output	[31:0]	DOUT;
output reg 		SELI;

reg	 	 [2:0] 	mx;

wire	 [2:0]	be;
wire			eq_rw;

// +++++++++++++++++++ Memories ++++++++++++++++++++

reg	 	[15:0]	REGFILE_C [0:63];	// Byte 3 and 2 , Verilog allows no "Byte Write" in wider memories !!!
reg	 	 [7:0]	REGFILE_B [0:63];	// Byte 1
reg	 	 [7:0]	REGFILE_A [0:63];	// Byte 0
reg		[31:0]	RF;

assign	be = {WMASKE[1],(WMASKE[1] | WMASKE[0]),1'b1};

assign	eq_rw = ENWR & (RADR[5:0] == WADR);

always @(posedge BCLK) if (RADR[7]) mx[2:0] <= be[2:0] & {{3{eq_rw}}};

always @(posedge BCLK) if (RADR[7]) SELI <= RADR[6];

assign DOUT[31:16] = mx[2] ? BYDIN[31:16] : RF[31:16];
assign DOUT[15:8]  = mx[1] ? BYDIN[15:8]  : RF[15:8];
assign DOUT[7:0]   = mx[0] ? BYDIN[7:0]   : RF[7:0];
	
// ++++++++++++++++ Register File 64 * 32 Bits ++++++++++++

always @(posedge BCLK)
	if (RADR[7])
		begin
			RF[31:16] <= REGFILE_C[RADR[5:0]];
			RF[15:8]  <= REGFILE_B[RADR[5:0]];
			RF[7:0]   <= REGFILE_A[RADR[5:0]];
		end

always @(posedge BCLK)
	if (DOWR)
		begin
			if (be[2]) REGFILE_C[WADR] <= DIN[31:16];
			if (be[1]) REGFILE_B[WADR] <= DIN[15:8];
			if (be[0]) REGFILE_A[WADR] <= DIN[7:0];
		end

endmodule
module WRPORT ( WRITE, DRAM_Q, WRDATA, ENBYTE, VADDR, DADDR, WDAT, CAP_Q, ENB );

	input			WRITE;
	input  [127:0]	DRAM_Q;
	input	[31:0]	WRDATA;
	input	 [3:0]	ENBYTE;
	input	 [3:2]	VADDR;
	input	 [3:2]	DADDR;
	
	output [127:0]	WDAT;
	
	output	reg	[31:0]	CAP_Q;
	output	reg	[15:0]	ENB;
	
	assign WDAT = WRITE ? {WRDATA,WRDATA,WRDATA,WRDATA} : DRAM_Q;
	
	always @(DADDR or DRAM_Q)
	  case (DADDR)
	    2'b00 : CAP_Q = DRAM_Q[31:0];
		2'b01 : CAP_Q = DRAM_Q[63:32];
		2'b10 : CAP_Q = DRAM_Q[95:64];
		2'b11 : CAP_Q = DRAM_Q[127:96];
	  endcase
	  
	always @(WRITE or VADDR or ENBYTE)
	  case ({WRITE,VADDR})
	     3'b100 : ENB = {4'd0  ,4'd0  ,4'd0  ,ENBYTE};
	     3'b101 : ENB = {4'd0  ,4'd0  ,ENBYTE,4'd0  };
	     3'b110 : ENB = {4'd0  ,ENBYTE,4'd0  ,4'd0  };
	     3'b111 : ENB = {ENBYTE,4'd0  ,4'd0  ,4'd0  };
		default : ENB = 16'hFFFF;
	  endcase
	  
endmodule
module NEU_VALID ( BCLK, VALIN, WADR, WREN, RADR, VALOUT );

	input			BCLK;
	input	[23:0]	VALIN;
	input	 [4:0]	WADR;
	input			WREN;
	input	 [4:0]	RADR;
	
	output	[23:0]	VALOUT;
	
	reg		[23:0]	cvalid [0:31];	// Valid bits for Data Set 0 and 1 : 32 entries of 24 bits
	reg		[23:0]	ramout;
	reg		[23:0]	valhold;
	reg				gleich;

	always @(posedge BCLK) ramout <= cvalid[RADR];
	always @(posedge BCLK) if (WREN) cvalid[WADR] <= VALIN;
	
	always @(posedge BCLK) valhold <= VALIN;
	always @(posedge BCLK) gleich  <= WREN & (RADR == WADR);
	
	assign VALOUT = gleich ? valhold : ramout;
	
endmodule
module DEBUG_AE ( DBG_IN, READ, WRITE, USER, VIRTUELL, ACC_OK, VADR_R, MMU_Q, ENBYTE, DBG_HIT );

	input	[40:2]	DBG_IN;
	
	input			READ,WRITE;
	input			USER;
	input			VIRTUELL;
	input			ACC_OK;
	input	[31:2]	VADR_R;
	input	[19:0]	MMU_Q;
	input	 [3:0]	ENBYTE;
	
	output	 		DBG_HIT;
	
	wire			sd,ud,crd,cwr,vnp;
	wire			make;
	wire			virt_adr,real_adr,page_adr;
	wire			byte_en;
	
	assign sd  = DBG_IN[40];
	assign ud  = DBG_IN[39];
	assign crd = DBG_IN[38];
	assign cwr = DBG_IN[37];
	assign vnp = DBG_IN[36];
	
	assign make =  ((ud & USER) | (sd & ~USER))		// compare USER or SUPERVISOR
				 & (VIRTUELL == vnp)				// compare real or virtual address
				 & ((cwr & WRITE) | (crd & READ));	// compare READ or WRITE
	
	assign virt_adr = (MMU_Q 		 == DBG_IN[31:12]);
	assign real_adr = (VADR_R[31:12] == DBG_IN[31:12]);
	assign page_adr = (VADR_R[11:2]	 == DBG_IN[11:2]);
	
	assign byte_en  = |(ENBYTE & DBG_IN[35:32]);
	
	assign DBG_HIT  =  ACC_OK		// all valid
					 & make			// selection is valid
					 & (VIRTUELL ? virt_adr : real_adr)	& page_adr	// address
					 & byte_en;		// Byte Enable
					 
endmodule
module MMU_UP ( BCLK, BRESET, NEW_PTB, PTB1, IVAR, WR_MRAM, VADR, VADR_R, MVALID, UPDATE,
				WE_MV, WADR_MV, RADR_MV, DAT_MV, NEW_PTB_RUN );

	input			BCLK;
	input			BRESET;	
	input			NEW_PTB;	// the MMU memory is cleared. Pulse of one BCLK cycle, Op-Dec is waiting
	input			PTB1;		// which one
	input			IVAR;
	input			WR_MRAM;	// BCLK : update MRAM and MMU_VAL
	input  [19:16]	VADR,VADR_R;	// For update
	input	[31:0]	MVALID,UPDATE;
	
	output			WE_MV;		// Write Enable MMU Valid
	output	 [3:0]	WADR_MV,RADR_MV;
	output	[31:0]	DAT_MV;
	output			NEW_PTB_RUN;
	
	reg				neue_ptb,wr_flag,old_rst,run_over;
	reg		 [3:0]	count;
	
	wire	[15:0]	new_val;
	
	assign WE_MV   = wr_flag | WR_MRAM | IVAR;	// write on falling edge BCLK
	assign RADR_MV = run_over ? count : VADR;
	assign WADR_MV = wr_flag ? (count - 4'b0001) : VADR_R;
	assign DAT_MV  = wr_flag ? {MVALID[31:16],new_val} : UPDATE;	// Only the matching entries are cleared : PTB0/PTB1

	// [31:16] Address-Space memory, [15:0] Valid memory
	assign new_val = neue_ptb ? (PTB1 ? (MVALID[15:0] & ~MVALID[31:16]) : (MVALID[15:0] & MVALID[31:16])) : 16'h0;
	
	always @(posedge BCLK or negedge BRESET)
		if (!BRESET) neue_ptb <= 1'b0;
			else neue_ptb <= NEW_PTB | (neue_ptb & run_over);
			
	always @(posedge BCLK) old_rst <= BRESET;	// after Reset all will be set to 0 
	
	always @(posedge BCLK) run_over <= ((~old_rst | NEW_PTB) | (run_over & (count != 4'hF))) & BRESET;
	
	always @(posedge BCLK) count <= run_over ? count + 4'h1 : 4'h0;
	
	always @(posedge BCLK) wr_flag <= run_over;

	assign NEW_PTB_RUN = wr_flag;	// Info to Op-Dec
	
endmodule
module DCA_CONTROL ( BCLK, BRESET, CUPDATE, DRAM_ACC, CA_SET, HIT_ALL, VADR_R, UPDATE, INVAL_A, WRITE, MDONE, USE_CA,
					 INHIBIT, KILL, WRCRAM0, WRCRAM1, WE_CV, WADR_CV, DAT_CV, INIT_CA_RUN, WRSET0, WRSET1 );

	input			BCLK;
	input			BRESET;
	input			CUPDATE;	// State CUPDATE : Cache is filled from DRAM
	input			DRAM_ACC;
	input			CA_SET;
	input			HIT_ALL;	// a complete cache hit !
	input	[11:7]	VADR_R;
	input	[23:0]	UPDATE;
	input			INVAL_A;
	input			WRITE;
	input			MDONE;		// Signal from DRAM : Access Done
	input			USE_CA;		// Signal use cache
	input	 		INHIBIT;	// Signal cache inhibit  - no write in cache
	input			KILL;		// valid Ram must be updated because of collision ... or CINV
	
	output			WRCRAM0,WRCRAM1;
	output			WE_CV;
	output	 [4:0]	WADR_CV;
	output	[23:0]	DAT_CV;
	output			INIT_CA_RUN;
	output			WRSET0,WRSET1;
	
	reg		 [1:0]	state;
	reg		 [4:0]	acount;
	reg				ca_set_d;

	wire			countf;
	
	always @(posedge BCLK) if (DRAM_ACC) ca_set_d <= CA_SET;	// Store for whole access

	// physical address is stored in TAG-RAM

	assign WRCRAM0 = (CUPDATE & ~INHIBIT) & ~ca_set_d;
	assign WRCRAM1 = (CUPDATE & ~INHIBIT) &  ca_set_d;
	
	// Load Valid RAM :
	
	assign WE_CV   = state[1] | HIT_ALL | (CUPDATE & ~INHIBIT) | KILL; // Hit All for "Last" Update
	assign WADR_CV = state[1] ? acount : VADR_R;
	assign DAT_CV  = state[1] ? 24'h0 : UPDATE;	

	// Clear of Cache-Valid RAMs : 32 clocks of BCLK
	
	assign countf = (acount == 5'h1F);
	
	always @(posedge BCLK)
		casex ({BRESET,INVAL_A,countf,state[1:0]})
		  5'b0xx_xx : state <= 2'b01;
		  5'b1xx_01 : state <= 2'b10;		// start counter
		  5'b10x_00 : state <= 2'b00;		// wait ...
		  5'b11x_00 : state <= 2'b10;
		  5'b1x0_10 : state <= 2'b10;
		  5'b1x1_10 : state <= 2'b00;
		  default   : state <= 2'b0;
		endcase
	
	always @(posedge BCLK) if (!state[1]) acount <= 5'h0; else acount <= acount + 5'h01;

	assign INIT_CA_RUN = state[1];
	
	// WRITE Control in data RAMs
	assign WRSET0 = ( ~CA_SET & WRITE & HIT_ALL) | (MDONE & USE_CA & ~ca_set_d);
	assign WRSET1 = (  CA_SET & WRITE & HIT_ALL) | (MDONE & USE_CA &  ca_set_d);
	
endmodule
module MMU_MATCH ( USER, READ, WRITE, RMW, MCR_FLAGS, MVALID, VADR_R, MMU_VA, IVAR,
				   VIRTUELL, MMU_HIT , UPDATE, PROT_ERROR, CI, SEL_PTB1 );

	input			USER;
	input			READ;
	input			WRITE;
	input			RMW;
	input	 [2:0]	MCR_FLAGS;
	input	[31:0]	MVALID;
	input  [31:12]	VADR_R;
	input  [31:16]	MMU_VA;
	input	 [1:0]	IVAR;	// Invalidate Entry
	
	output			VIRTUELL;	// only for Adress-Mux
	output			MMU_HIT;
	output	[31:0]	UPDATE;
	output	reg		PROT_ERROR;	// if valid must suppress write in Write Buffer and cache
	output			CI,SEL_PTB1;
	
	reg		[15:0]	maske;

	wire			adr_space,as_sorte,match,alles_ok;
	wire	[15:0]	val_bits,as_bits;
	wire			ena_prot;
	wire			zugriff;
	
	assign zugriff = READ | WRITE;
	
	always @(VADR_R)
		case (VADR_R[15:12])
		  4'h0 : maske = 16'h0001;
		  4'h1 : maske = 16'h0002;
		  4'h2 : maske = 16'h0004;
		  4'h3 : maske = 16'h0008;
		  4'h4 : maske = 16'h0010;
		  4'h5 : maske = 16'h0020;
		  4'h6 : maske = 16'h0040;
		  4'h7 : maske = 16'h0080;
		  4'h8 : maske = 16'h0100;
		  4'h9 : maske = 16'h0200;
		  4'hA : maske = 16'h0400;
		  4'hB : maske = 16'h0800;
		  4'hC : maske = 16'h1000;
		  4'hD : maske = 16'h2000;
		  4'hE : maske = 16'h4000;
		  4'hF : maske = 16'h8000;
		endcase
		
	assign VIRTUELL = USER ? MCR_FLAGS[0] : MCR_FLAGS[1];
	
	assign adr_space = IVAR[1] ? IVAR[0] : (MCR_FLAGS[2] & USER);	// adr_space = IVARx ? 1 or 0 : DualSpace & TU
	
	assign as_sorte = ((MVALID[31:16] & maske) != 16'h0);
		  
	assign match = (VADR_R[31:20] == MMU_VA[31:20]) & (adr_space == as_sorte) & ((MVALID[15:0] & maske) != 16'h0000);
	
	assign alles_ok = match & ( ~WRITE | MMU_VA[17] ) & ~PROT_ERROR;	// Modified - Flag : reload the PTE
	
	// if MMU_HIT = 0 then there is no Write-Buffer access and no update of cache !
	assign MMU_HIT = zugriff ? ( VIRTUELL ? alles_ok : 1'b1 ) : 1'b0 ;	// MMU off : then always HIT

	assign val_bits = IVAR[1] ? (MVALID[15:0] & (match ? ~maske : 16'hFFFF)) : (MVALID[15:0] | maske);
	assign as_bits  = IVAR[1] ? MVALID[31:16] : (adr_space ? (MVALID[31:16] | maske) : (MVALID[31:16] & ~maske));
	
	assign UPDATE = {as_bits,val_bits};

	assign ena_prot = zugriff & VIRTUELL & match;
	
	// A Protection error must suppress write in WB and cache
	always @(ena_prot or MMU_VA or USER or WRITE or RMW)
		case ({ena_prot,MMU_VA[19:18]})
		   3'b100 : PROT_ERROR = USER | WRITE | RMW;	// Only Supervisor READ
		   3'b101 : PROT_ERROR = USER;					// no USER access
		   3'b110 : PROT_ERROR = USER & (WRITE | RMW);	// USER only READ
		  default : PROT_ERROR = 1'b0;
		endcase
		
	assign CI = VIRTUELL & MMU_VA[16];
	assign SEL_PTB1 = adr_space;		// For PTE update
		
endmodule
module CA_MATCH ( CVALID, DRAMSZ, ADDR, TAG0, TAG1, CFG, WRITE, MMU_HIT, CI, INVAL_L, KDET, ENDRAM, DC_ILO,
				  CA_HIT, CA_SET, UPDATE, IO_SPACE, USE_CA, WB_ACC, KILL );

	input	[23:0]	CVALID;
	input	 [2:0]	DRAMSZ;
	input	[31:4]	ADDR;
	input  [28:12]	TAG0,TAG1;
	input	 [1:0]	CFG;	// LDC , DC
	input			WRITE;
	input			MMU_HIT;
	input			CI;
	input			INVAL_L;	// invalid cache line
	input			KDET;
	input			ENDRAM;
	input			DC_ILO;		// CBITI/SBITI special case
	
	output			CA_HIT;
	output			CA_SET;	// if no Hit then says SET where to store
	output	[23:0]	UPDATE;	// Update Information for CVALID memory 
	output			IO_SPACE;
	output			USE_CA;
	output			WB_ACC;
	output			KILL;
	
	reg		 [7:0]	maske;
	reg				acc_dram;
	
	wire			match_0,match_1;
	wire			valid_0,valid_1;
	wire			select;
	wire			clear;
	wire	 [7:0]	update_0,update_1,lastinfo;
	wire			sel_dram;
	
	always @(ADDR)
		case (ADDR[6:4])
		  3'h0 : maske = 8'h01;
		  3'h1 : maske = 8'h02;
		  3'h2 : maske = 8'h04;
		  3'h3 : maske = 8'h08;
		  3'h4 : maske = 8'h10;
		  3'h5 : maske = 8'h20;
		  3'h6 : maske = 8'h40;
		  3'h7 : maske = 8'h80;
		endcase
		
	assign valid_0 = (( CVALID[7:0] & maske) != 8'h00);
	assign valid_1 = ((CVALID[15:8] & maske) != 8'h00);
	
	assign match_0 = ( TAG0 == ADDR[28:12] );	// 4KB
	assign match_1 = ( TAG1 == ADDR[28:12] );	// 4KB

	assign CA_HIT = ((valid_0 & match_0) | (valid_1 & match_1)) & ~DC_ILO & CFG[0] & (sel_dram | KDET);
	
	// which SET is written in cache miss ? If both are valid the last used is not taken
	assign select = (valid_1 & valid_0) ? ~((CVALID[23:16] & maske) != 8'h00) : valid_0;	// Last-used field = CVALID[23:16]
	
	assign CA_SET = CA_HIT ? (valid_1 & match_1) : select;
	
	assign clear = INVAL_L | KDET;	// INVAL_L is from CINV
 
	assign update_0 = CA_SET ? CVALID[7:0] : (clear ? (CVALID[7:0] & ~maske) : (CVALID[7:0] | maske));
	assign update_1 = CA_SET ? (clear ? (CVALID[15:8] & ~maske) : (CVALID[15:8] | maske)) : CVALID[15:8];
	
	assign lastinfo = CA_HIT ? (CA_SET ? (CVALID[23:16] | maske) : (CVALID[23:16] & ~maske)) : CVALID[23:16];
	
	assign UPDATE = {lastinfo,update_1,update_0};
	
	assign KILL = clear & CA_HIT & ~CFG[1];		// only if cache is not locked
	
	always @(DRAMSZ or ADDR)	// Size of DRAM
		case (DRAMSZ)
		  3'b000 : acc_dram = (ADDR[28:23] == 6'd0);	//   8 MB 32016 Second Processor
		  3'b001 : acc_dram = (ADDR[28:24] == 5'd0);	//  16 MB
		  3'b010 : acc_dram = (ADDR[28:25] == 4'd0);	//  32 MB
		  3'b011 : acc_dram = (ADDR[28:26] == 3'd0);	//  64 MB
		  3'b100 : acc_dram = (ADDR[28:27] == 2'd0);	// 128 MB
		  3'b101 : acc_dram = ~ADDR[28];				// 256 MB
		  3'b110 : acc_dram =   1'b1;					// 512 MB
		  3'b111 : acc_dram = ~(ADDR[28:27] == 2'b10);	// 256 MB NetBSD + 128 MB
		endcase
	
	assign sel_dram =  (ADDR[31:29] == 3'd0) & acc_dram & ENDRAM;
	assign IO_SPACE = ~sel_dram;					// not DRAM or DRAM ist off
	
	assign USE_CA   = ~CI & ~DC_ILO & CFG[0] & ~CFG[1];	// CI ? ILO ? Cache on ? Locked Cache ? 
	assign WB_ACC   = WRITE & MMU_HIT & sel_dram;
	
endmodule