data/full_repos/permissive/427281804/FPU/verilog/IFIR.v
1: b'%Error: data/full_repos/permissive/427281804/FPU/verilog/IFIR.v:270: Cannot find file containing module: \'icgc\'\n icgc u_cgc_cmem(.CK(clk_fast),.E(first_cycle_r|dmem_clk_en),.ECK(cmem_clk));\n ^~~~\n        ... Looked in:\n             data/full_repos/permissive/427281804/FPU/verilog,data/full_repos/permissive/427281804/icgc\n             data/full_repos/permissive/427281804/FPU/verilog,data/full_repos/permissive/427281804/icgc.v\n             data/full_repos/permissive/427281804/FPU/verilog,data/full_repos/permissive/427281804/icgc.sv\n             icgc\n             icgc.v\n             icgc.sv\n             obj_dir/icgc\n             obj_dir/icgc.v\n             obj_dir/icgc.sv\n%Warning-WIDTH: data/full_repos/permissive/427281804/FPU/verilog/IFIR.v:391: Operator ASSIGN expects 29 bits on the Assign RHS, but Assign RHS\'s CONST \'30\'h0\' generates 30 bits.\n                                                                           : ... In instance W4823_IFIR\n  alu_b_29i = 30\'b0;\n            ^\n                ... Use "/* verilator lint_off WIDTH */" and lint_on around source to disable this message.\n%Warning-WIDTH: data/full_repos/permissive/427281804/FPU/verilog/IFIR.v:440: Operator ASSIGN expects 29 bits on the Assign RHS, but Assign RHS\'s REPLICATE generates 30 bits.\n                                                                           : ... In instance W4823_IFIR\n  alu_a_29i = {30{1\'bx}};\n            ^\n%Warning-WIDTH: data/full_repos/permissive/427281804/FPU/verilog/IFIR.v:441: Operator ASSIGN expects 29 bits on the Assign RHS, but Assign RHS\'s REPLICATE generates 30 bits.\n                                                                           : ... In instance W4823_IFIR\n  alu_b_29i = {30{1\'bx}};\n            ^\n%Warning-WIDTH: data/full_repos/permissive/427281804/FPU/verilog/IFIR.v:460: Operator ASSIGN expects 29 bits on the Assign RHS, but Assign RHS\'s REPLICATE generates 30 bits.\n                                                                           : ... In instance W4823_IFIR\n  alu_a_29i = {30{1\'bx}};\n            ^\n%Warning-WIDTH: data/full_repos/permissive/427281804/FPU/verilog/IFIR.v:461: Operator ASSIGN expects 29 bits on the Assign RHS, but Assign RHS\'s REPLICATE generates 30 bits.\n                                                                           : ... In instance W4823_IFIR\n  alu_b_29i = {30{1\'bx}};\n            ^\n%Error: data/full_repos/permissive/427281804/FPU/verilog/IFIR.v:481: Cannot find file containing module: \'FPALU_dummy\'\n FPALU_dummy u_fpalu(\n ^~~~~~~~~~~\n%Warning-WIDTH: data/full_repos/permissive/427281804/FPU/verilog/IFIR.v:509: Operator ASSIGNW expects 16 bits on the Assign RHS, but Assign RHS\'s VARREF \'alu_y_29i\' generates 29 bits.\n                                                                           : ... In instance W4823_IFIR\nassign dout     = alu_y_29i;\n                ^\n%Error: data/full_repos/permissive/427281804/FPU/verilog/IFIR.v:519: Cannot find file containing module: \'SP_DMEM\'\n SP_DMEM u_dmem (\n ^~~~~~~\n%Error: data/full_repos/permissive/427281804/FPU/verilog/IFIR.v:532: Cannot find file containing module: \'SP_CMEM\'\n SP_CMEM u_cmem (\n ^~~~~~~\n%Error: data/full_repos/permissive/427281804/FPU/verilog/IFIR.v:550: Cannot find file containing module: \'SP_REGF\'\n SP_REGF u_regf (\n ^~~~~~~\n%Error: Exiting due to 5 error(s), 6 warning(s)\n'
module W4823_IFIR(
	input           rst_n,
	input           clk_slow,
	input           clk,
	input [15:0]    din,
	input           valid_in,
	input [16:0]    cin,
	input [5:0]     caddr,
	input           cload,
	output [15:0]   dout,
	output          valid,
	output [28:0]   dout_29i
);




`define USE_VENDOR_MEMORY
`define USE_DUMMY_ALU




wire       clk_fast   = clk;
wire       clk_fast_n = ~clk_fast;
reg [7:0]  ss_r;
reg [7:0]  cycle_cnt_r;
reg        first_cycle_r;


localparam SLEEP_LEN = 106;



`define S0_LOAD      8'b00000001
`define S1_MUL_NDAV  8'b00000011
`define S2_MUL       8'b00000010
`define S3_ACC_THRU  8'b00000110
`define S4_ACC       8'b00000100
`define S5_ACC_P1    8'b00001100
`define S6_ACC_CWR   8'b00001000
`define S7_ACC_DWR   8'b00011000
`define S8_ACC_EWR   8'b00010000
`define S9_ACC_P21   8'b00110000
`define SA_ACC_P22   8'b00100000
`define SB_ACC_P31   8'b01100000
`define SC_ACC_P32   8'b01000000
`define SD_ACC_NORM  8'b11000000
`define SE_SLEEP     8'b10000000
`define SF_DINLATCH  8'b10000001

wire cycle_load      = ss_r[0]&~ss_r[7];
wire cycle_mul_ndav  = ss_r[0]& ss_r[1];
wire cycle_mul       = ss_r[1]&~ss_r[0];
wire cycle_acc_thru  = ss_r[1]& ss_r[2];
wire cycle_acc       = ss_r[2]&~ss_r[1];
wire cycle_acc_p1    = ss_r[2]& ss_r[1];
wire cycle_acc_cwr   = ss_r[3]&~ss_r[2];
wire cycle_acc_dwr   = ss_r[3]& ss_r[2];
wire cycle_acc_ewr	 = ss_r[4]&~ss_r[3];
wire cycle_acc_p21   = ss_r[4]& ss_r[3];
wire cycle_acc_p22   = ss_r[5]&~ss_r[4];
wire cycle_acc_p31   = ss_r[5]& ss_r[4];
wire cycle_acc_p32   = ss_r[6]&~ss_r[5];
wire cycle_accnorm   = ss_r[6]& ss_r[5];
wire cycle_sleep     = ss_r[7]&~ss_r[6];
wire cycle_dinlatch  = ss_r[7]& ss_r[0];


always @(posedge clk_fast or negedge rst_n) begin
	if(~rst_n) begin

		ss_r          <= `SE_SLEEP;
		cycle_cnt_r   <= SLEEP_LEN;
		first_cycle_r <= 1'b1;
	end else begin
		case(ss_r)
		`S0_LOAD:
			ss_r <= `S1_MUL_NDAV;
		`S1_MUL_NDAV: begin
			if(cycle_cnt_r==8'd3) begin	
				ss_r        <= `S2_MUL;
				cycle_cnt_r <= 0;	
			end else
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
		end
		`S2_MUL: begin
			if(cycle_cnt_r==8'd57) begin
				ss_r        <= `S3_ACC_THRU;
				cycle_cnt_r <= 0;	
			end else 
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
		end
		`S3_ACC_THRU: begin
			if(cycle_cnt_r==8'd4) begin
				ss_r        <= `S4_ACC;
				cycle_cnt_r <= 0;
			end else 
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
		end
		`S4_ACC: begin
			if(cycle_cnt_r==8'd58) begin
				ss_r        <= `S5_ACC_P1;
				cycle_cnt_r <= 0;	
			end else 
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
		end
		`S5_ACC_P1: begin
			if(cycle_cnt_r==8'd1) begin
				ss_r        <= `S6_ACC_CWR;
				cycle_cnt_r <= 0;	
			end else 
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
		end
		`S6_ACC_CWR: begin
			if(cycle_cnt_r==8'd1) begin
				ss_r        <= `S7_ACC_DWR;
				cycle_cnt_r <= 0;
			end else
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
	end
		`S7_ACC_DWR: ss_r   <= `S8_ACC_EWR;
		`S8_ACC_EWR: ss_r   <= `S9_ACC_P21;
		`S9_ACC_P21: begin
			if(cycle_cnt_r==8'd1) begin
				ss_r        <= `SA_ACC_P22;
				cycle_cnt_r <= 0;	
			end else 
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
		end
		`SA_ACC_P22: begin
			if(cycle_cnt_r==8'd3) begin
				ss_r        <= `SB_ACC_P31;
				cycle_cnt_r <= 0;	
			end else 
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
		end
		`SB_ACC_P31: ss_r   <= `SC_ACC_P32;
		`SC_ACC_P32: begin
			if(cycle_cnt_r==8'd3) begin
				ss_r        <= `SD_ACC_NORM;
				cycle_cnt_r <= 0;	
			end else 
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
		end
		`SD_ACC_NORM: begin
			if(cycle_cnt_r==8'd4) begin
				ss_r        <= `SE_SLEEP;
				cycle_cnt_r <= 0;	
			end else 
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
		end
		`SE_SLEEP: begin
			if(cycle_cnt_r==SLEEP_LEN-1) begin
				ss_r          <= `SF_DINLATCH;
				cycle_cnt_r   <= 0;	
				first_cycle_r <= 0;
			end else 
				cycle_cnt_r   <= cycle_cnt_r + 1'b1;
		end
		`SF_DINLATCH: ss_r    <= `S0_LOAD;
		endcase
	end
end







reg cycle_load_dly_r;	
always @(negedge clk_fast) begin
	if(cycle_load) cycle_load_dly_r <= 1;
	else           cycle_load_dly_r <= 0;
end



wire        cmem_wr = first_cycle_r&clk_slow;
wire        cmem_clk;
wire [5:0]  cmem_addr;
reg  [5:0]  cmem_addr_r;
wire [16:0] cmem_din_FP16i = cin;

reg         dmem_wr_r;
wire         dmem_clk;
wire         dmem_clk_en;

reg [5:0]	 dmem_addr_r;


wire din_latch;
reg [15:0] din_r;

assign cmem_addr = (first_cycle_r) ? caddr : cmem_addr_r;

wire dmem_cmem_rst = dmem_wr_r&~dmem_clk;
reg cycle_dinlatch_pulse_r;

always @(posedge cycle_dinlatch or negedge clk_fast) begin
	if(~clk_fast) cycle_dinlatch_pulse_r <= 0;
	else          cycle_dinlatch_pulse_r <= 1;
end

always @(posedge cycle_dinlatch) begin
	din_r <= din;
end
always @(posedge cycle_dinlatch_pulse_r or negedge dmem_clk) begin
	if(cycle_dinlatch_pulse_r) begin

		cmem_addr_r <= 0;
	end else begin

		cmem_addr_r <= cmem_addr_r + 1;
	end
end

always @(negedge clk_fast) begin
	if(cycle_dinlatch&&dmem_wr_r==0) dmem_wr_r <= 1;
	else                             dmem_wr_r <= 0;
end

wire alu_clk_en = ~cycle_sleep;
wire alu_clk;



reg cycle_mul_dly1_r;
always @(posedge alu_clk) begin
	if(cycle_mul)        cycle_mul_dly1_r <= 1;
	else                 cycle_mul_dly1_r <= 0;
end

reg cycle_acc_thru_dly1_r;
always @(negedge alu_clk) begin
	if(cycle_acc_thru) cycle_acc_thru_dly1_r <= 1;
	else               cycle_acc_thru_dly1_r <= 0;
end

reg cycle_acc_thru_dly2_r;
always @(posedge alu_clk) begin
	if(cycle_acc_thru) cycle_acc_thru_dly2_r <= 1;
	else               cycle_acc_thru_dly2_r <= 0;
end

assign din_latch = cycle_dinlatch_pulse_r;
assign dmem_clk_en = (cycle_dinlatch|cycle_load|cycle_mul_ndav|cycle_mul) & ~cycle_acc_thru_dly1_r;


always @(negedge clk_fast or negedge rst_n) begin
	if(~rst_n)	dmem_addr_r <= 0;
	else if(dmem_clk_en) dmem_addr_r <= dmem_addr_r + 1;
end



`ifdef USE_VENDOR_CGC
		
`else
	icgc u_cgc_cmem(.CK(clk_fast),.E(first_cycle_r|dmem_clk_en),.ECK(cmem_clk));

	assign alu_clk = clk_fast & alu_clk_en;
	assign dmem_clk  = dmem_clk_en & clk_fast;

`endif





reg  regf_wr_r;
wire regf_clken = (regf_wr_r|cycle_acc_thru);
wire regf_clk   = regf_clken & alu_clk;
reg [5:0]    regf_addr_r;

always @(negedge alu_clk) begin
	if(cycle_mul&~cycle_acc_thru_dly2_r) regf_wr_r = 1;
	else                          regf_wr_r = 0;

	if((~regf_clken)|(cycle_mul&cycle_acc_thru_dly2_r)) regf_addr_r <= 0;
	else            regf_addr_r <= regf_addr_r + 1;
end





wire [15:0] dmem_q_fp16;
wire [16:0] cmem_q_fp16i;
wire [28:0] regf_q_fp29i;


wire [28:0] alumux_din_fp16;
wire [28:0] alumux_dmem_fp16;
wire [28:0] alumux_cmem_fp16i;
wire [28:0] alumux_self_fp29i; 
wire [28:0] alumux_regf_fp29i;
wire [28:0] alumux_acc_fp29i;

reg [1:0]   alu_opcode;


reg [28:0]  alu_a_29i_r;
reg [28:0]  alu_b_29i_r;
reg [28:0]  alu_a_29i;
reg [28:0]  alu_b_29i;
wire        alu_a_s = alu_a_29i_r[28];
wire [5:0]  alu_a_e = alu_a_29i_r[27:22];
wire [21:0] alu_a_m = alu_a_29i_r[21:0];
wire        alu_b_s = alu_b_29i_r[28];
wire [5:0]  alu_b_e = alu_b_29i_r[27:22];
wire [21:0] alu_b_m = alu_b_29i_r[21:0];
wire        alu_y_s;
wire [5:0]	alu_y_e;
wire [21:0]	alu_y_m;
wire [28:0] alu_y_29i = {alu_y_s, alu_y_e, alu_y_m};


reg [28:0] alumux_dly;
reg [28:0] alumux_dly1;
reg [28:0] alumux_dly2;
reg [28:0] alumux_dly3;
always @(negedge alu_clk) begin
	if(cycle_acc_p1|cycle_acc_dwr) begin
		alumux_dly <= alumux_self_fp29i;
		alumux_dly1 <= alumux_dly;
		alumux_dly2 <= alumux_dly1;
	end
	if(cycle_acc_p1) begin
		alumux_dly3 <= alumux_dly2;
	end
end


reg [1:0] alu_opcode_r;
always @(posedge alu_clk) begin
	alu_a_29i_r  <= alu_a_29i;
	alu_b_29i_r  <= alu_b_29i;
	alu_opcode_r <= alu_opcode;
end





assign alumux_din_fp16  = {din_r[15], 1'bx, din_r[14:10], {12{1'bx}}, din_r[9:0]};
assign alumux_dmem_fp16  = {dmem_q_fp16[15], 1'bx, dmem_q_fp16[14:10], {12{1'bx}}, dmem_q_fp16[9:0]};


assign alumux_cmem_fp16i = {cmem_q_fp16i[16], 1'bx, cmem_q_fp16i[15:11], {11{1'bx}}, cmem_q_fp16i[10:0]};
assign alumux_regf_fp29i = regf_q_fp29i;
assign alumux_self_fp29i = alu_y_29i;
`ifdef DEBUGINFO
integer dbg_alumux_state;
`endif
always @* begin
	alu_opcode = 2'bxx;


	if(cycle_dinlatch) begin
		alu_a_29i = alumux_din_fp16;
		alu_b_29i = alumux_cmem_fp16i;
		alu_opcode = 2'b10;
		`ifdef DEBUGINFO
			dbg_alumux_state = 0;
		`endif
	end

	if((cycle_mul_ndav|cycle_mul)&~cycle_acc_thru) begin
		alu_a_29i = alumux_dmem_fp16;
		alu_b_29i = alumux_cmem_fp16i;
		alu_opcode = 2'b10;
		`ifdef DEBUGINFO
			dbg_alumux_state = 1;
		`endif
	end         
	

	if(cycle_acc_thru&~cycle_acc) begin		
		alu_a_29i = alumux_self_fp29i;	
		alu_b_29i = 30'b0;
		alu_opcode = 2'b11;
		`ifdef DEBUGINFO
			dbg_alumux_state = 2;
		`endif
	end 


	if(cycle_acc&~cycle_acc_p1) begin
		alu_a_29i = alumux_self_fp29i;
		alu_b_29i = alumux_regf_fp29i;
		alu_opcode = 2'b11;
		`ifdef DEBUGINFO
			dbg_alumux_state = 3;
		`endif
	end 


	if(cycle_acc_p1 & ~cycle_acc_cwr) begin
		alu_a_29i = alumux_self_fp29i;
		alu_b_29i = {29{1'b0}};
		alu_opcode = 2'b11;
		`ifdef DEBUGINFO
			dbg_alumux_state = 4;
		`endif
	end


	if((cycle_acc_cwr|cycle_acc_dwr|cycle_acc_ewr)&~cycle_acc_p21) begin
		alu_a_29i = alumux_dly;
		alu_b_29i = alu_a_29i_r;
		alu_opcode = 2'bxx;
		`ifdef DEBUGINFO
			dbg_alumux_state = 5;
		`endif
	end


	if(cycle_acc_p21&~cycle_acc_p22) begin
		alu_a_29i = alumux_self_fp29i;
		alu_b_29i = alumux_dly1;
		alu_opcode = 2'b11;
		`ifdef DEBUGINFO
			dbg_alumux_state = 6;
		`endif
	end


	if(cycle_acc_p22&~cycle_acc_p31) begin
		alu_a_29i = {30{1'bx}};
		alu_b_29i = {30{1'bx}};
		alu_opcode = 2'bxx;
		`ifdef DEBUGINFO
			dbg_alumux_state = 7;
		`endif
	end
	

	if(cycle_acc_p31&~cycle_acc_p32) begin
		alu_a_29i = alumux_self_fp29i;
		alu_b_29i = alumux_dly2;
		alu_opcode = 2'b11;
		`ifdef DEBUGINFO
			dbg_alumux_state = 8;
		`endif
	end


	if(cycle_acc_p32&~cycle_accnorm) begin
		alu_a_29i = {30{1'bx}};
		alu_b_29i = {30{1'bx}};
		alu_opcode = 2'bxx;
		`ifdef DEBUGINFO
			dbg_alumux_state = 9;
		`endif
	end


	if(cycle_accnorm&~cycle_sleep) begin
		alu_a_29i = alumux_self_fp29i;
		alu_b_29i = alumux_dly3;
		alu_opcode = 2'b00;
		`ifdef DEBUGINFO
			dbg_alumux_state = 10;
		`endif
	end
end


`ifdef USE_DUMMY_ALU
	FPALU_dummy u_fpalu(
		.clk               (alu_clk   ),
		.opcode            (alu_opcode_r),
		.din_uni_a_sgn     (alu_a_s   ),
		.din_uni_a_exp     (alu_a_e   ),
		.din_uni_a_man_dn  (alu_a_m   ),
		.din_uni_b_sgn     (alu_b_s   ),
		.din_uni_b_exp     (alu_b_e   ),
		.din_uni_b_man_dn  (alu_b_m   ),
		.dout_uni_y_sgn    (alu_y_s   ),
		.dout_uni_y_exp    (alu_y_e   ),
		.dout_uni_y_man_dn (alu_y_m   )
	);
`else
	FPALU u_fpalu(
		.clk               (alu_clk   ),
		.opcode            (alu_opcode_r),
		.din_uni_a_sgn     (alu_a_s   ),
		.din_uni_a_exp     (alu_a_e   ),
		.din_uni_a_man_dn  (alu_a_m   ),
		.din_uni_b_sgn     (alu_b_s   ),
		.din_uni_b_exp     (alu_b_e   ),
		.din_uni_b_man_dn  (alu_b_m   ),
		.dout_uni_y_sgn    (alu_y_s   ),
		.dout_uni_y_exp    (alu_y_e   ),
		.dout_uni_y_man_dn (alu_y_m   )
	);
`endif
assign dout     = alu_y_29i;
assign dout_29i = alu_y_29i;





`ifdef USE_VENDOR_MEMORY
	

	SP_DMEM u_dmem (
		.Q   (dmem_q_fp16),
		.CLK (clk_fast  ),
		.CEN (~dmem_clk_en),
		.WEN (~dmem_wr_r ),
		.A   (dmem_addr_r),
		.D   (din_r        )
	);



	wire [15:0] cmem_q_fp16;
	wire [15:0] cmem_din_fp16;
	SP_CMEM u_cmem (
		.Q   (cmem_q_fp16),
		.CLK (clk_fast^first_cycle_r),
		.CEN (~(first_cycle_r|dmem_clk_en)),
		.WEN (~cmem_wr   ),
		.A   (cmem_addr  ),
		.D   (cmem_din_fp16)
	);
	assign cmem_q_fp16i[16]    = cmem_q_fp16[15];
	assign cmem_q_fp16i[15:12] = cmem_q_fp16[14:11];
	assign cmem_q_fp16i[11]    = 1'b1;
	assign cmem_q_fp16i[10:0]  = cmem_q_fp16[10:0];

	assign cmem_din_fp16[15]    = cmem_din_FP16i[16];
	assign cmem_din_fp16[14:11] = cmem_din_FP16i[15:12];
	assign cmem_din_fp16[10:0]  = cmem_din_FP16i[10:0];


	SP_REGF u_regf (
		.Q   (regf_q_fp29i ),
		.CLK (regf_clk     ),
		.CEN (~rst_n       ),
		.WEN (~regf_wr_r   ),
		.A   (regf_addr_r  ),
		.D   (alumux_self_fp29i)
	);

`else


sp_sram #(
	.ADDR_WIDTH(6),
	.DATA_WIDTH(16)
) u_dmem (
	.clk  (dmem_clk   ),
	.addr (dmem_addr_r),
	.din  (din_r        ),
	.wr   (dmem_wr_r  ),
	.qout (dmem_q_fp16)
);


sp_sram #(
	.ADDR_WIDTH(6),
	.DATA_WIDTH(17)
) u_cmem (
	.clk  (cmem_clk      ),
	.addr (cmem_addr     ),
	.din  (cmem_din_FP16i),
	.wr   (cmem_wr       ),
	.qout (cmem_q_fp16i  )
);


sp_sram #(
	.ADDR_WIDTH(6),
	.DATA_WIDTH(29)
) u_regf (
	.clk  (regf_clk         ),
	.addr (regf_addr_r      ),
	.din  (alumux_self_fp29i),
	.wr   (regf_wr_r        ),
	.qout (regf_q_fp29i     )
);

`endif



`ifdef DEBUGINFO
integer dbg_alu_clk_cnt;
reg     dbg_alu_outrdy;
always @(posedge alu_clk or posedge cycle_dinlatch) begin
	if(cycle_dinlatch) begin
		dbg_alu_clk_cnt <= 0;
		dbg_alu_outrdy <= 0;
	end else begin          
		dbg_alu_clk_cnt <= dbg_alu_clk_cnt + 1;
		if(dbg_alu_clk_cnt==3)  
			dbg_alu_outrdy <= 1;
	end
end 

`endif

endmodule
module W4823_IFIR(
	input           rst_n,
	input           clk_slow,
	input           clk,
	input [15:0]    din,
	input           valid_in,
	input [16:0]    cin,
	input [5:0]     caddr,
	input           cload,
	output [15:0]   dout,
	output          valid,
	output [28:0]   dout_29i
);





`define USE_VENDOR_MEMORY
`define USE_DUMMY_ALU




wire       clk_fast   = clk;
wire       clk_fast_n = ~clk_fast;
reg [7:0]  ss_r;
reg [7:0]  cycle_cnt_r;
reg        first_cycle_r;


localparam SLEEP_LEN = 106;



`define S0_LOAD      8'b00000001
`define S1_MUL_NDAV  8'b00000011
`define S2_MUL       8'b00000010
`define S3_ACC_THRU  8'b00000110
`define S4_ACC       8'b00000100
`define S5_ACC_P1    8'b00001100
`define S6_ACC_CWR   8'b00001000
`define S7_ACC_DWR   8'b00011000
`define S8_ACC_EWR   8'b00010000
`define S9_ACC_P21   8'b00110000
`define SA_ACC_P22   8'b00100000
`define SB_ACC_P31   8'b01100000
`define SC_ACC_P32   8'b01000000
`define SD_ACC_NORM  8'b11000000
`define SE_SLEEP     8'b10000000
`define SF_DINLATCH  8'b10000001

wire cycle_load      = ss_r[0]&~ss_r[7];
wire cycle_mul_ndav  = ss_r[0]& ss_r[1];
wire cycle_mul       = ss_r[1]&~ss_r[0];
wire cycle_acc_thru  = ss_r[1]& ss_r[2];
wire cycle_acc       = ss_r[2]&~ss_r[1];
wire cycle_acc_p1    = ss_r[2]& ss_r[1];
wire cycle_acc_cwr   = ss_r[3]&~ss_r[2];
wire cycle_acc_dwr   = ss_r[3]& ss_r[2];
wire cycle_acc_ewr	 = ss_r[4]&~ss_r[3];
wire cycle_acc_p21   = ss_r[4]& ss_r[3];
wire cycle_acc_p22   = ss_r[5]&~ss_r[4];
wire cycle_acc_p31   = ss_r[5]& ss_r[4];
wire cycle_acc_p32   = ss_r[6]&~ss_r[5];
wire cycle_accnorm   = ss_r[6]& ss_r[5];
wire cycle_sleep     = ss_r[7]&~ss_r[6];
wire cycle_dinlatch  = ss_r[7]& ss_r[0];


always @(posedge clk_fast or negedge rst_n) begin
	if(~rst_n) begin

		ss_r          <= `SE_SLEEP;
		cycle_cnt_r   <= SLEEP_LEN;
		first_cycle_r <= 1'b1;
	end else begin
		case(ss_r)
		`S0_LOAD:
			ss_r <= `S1_MUL_NDAV;
		`S1_MUL_NDAV: begin
			if(cycle_cnt_r==8'd3) begin	
				ss_r        <= `S2_MUL;
				cycle_cnt_r <= 0;	
			end else
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
		end
		`S2_MUL: begin
			if(cycle_cnt_r==8'd57) begin
				ss_r        <= `S3_ACC_THRU;
				cycle_cnt_r <= 0;	
			end else 
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
		end
		`S3_ACC_THRU: begin
			if(cycle_cnt_r==8'd4) begin
				ss_r        <= `S4_ACC;
				cycle_cnt_r <= 0;
			end else 
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
		end
		`S4_ACC: begin
			if(cycle_cnt_r==8'd58) begin
				ss_r        <= `S5_ACC_P1;
				cycle_cnt_r <= 0;	
			end else 
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
		end
		`S5_ACC_P1: begin
			if(cycle_cnt_r==8'd1) begin
				ss_r        <= `S6_ACC_CWR;
				cycle_cnt_r <= 0;	
			end else 
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
		end
		`S6_ACC_CWR: begin
			if(cycle_cnt_r==8'd1) begin
				ss_r        <= `S7_ACC_DWR;
				cycle_cnt_r <= 0;
			end else
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
	end
		`S7_ACC_DWR: ss_r   <= `S8_ACC_EWR;
		`S8_ACC_EWR: ss_r   <= `S9_ACC_P21;
		`S9_ACC_P21: begin
			if(cycle_cnt_r==8'd1) begin
				ss_r        <= `SA_ACC_P22;
				cycle_cnt_r <= 0;	
			end else 
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
		end
		`SA_ACC_P22: begin
			if(cycle_cnt_r==8'd3) begin
				ss_r        <= `SB_ACC_P31;
				cycle_cnt_r <= 0;	
			end else 
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
		end
		`SB_ACC_P31: ss_r   <= `SC_ACC_P32;
		`SC_ACC_P32: begin
			if(cycle_cnt_r==8'd3) begin
				ss_r        <= `SD_ACC_NORM;
				cycle_cnt_r <= 0;	
			end else 
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
		end
		`SD_ACC_NORM: begin
			if(cycle_cnt_r==8'd4) begin
				ss_r        <= `SE_SLEEP;
				cycle_cnt_r <= 0;	
			end else 
				cycle_cnt_r <= cycle_cnt_r + 1'b1;
		end
		`SE_SLEEP: begin
			if(cycle_cnt_r==SLEEP_LEN-1) begin
				ss_r          <= `SF_DINLATCH;
				cycle_cnt_r   <= 0;	
				first_cycle_r <= 0;
			end else 
				cycle_cnt_r   <= cycle_cnt_r + 1'b1;
		end
		`SF_DINLATCH: ss_r    <= `S0_LOAD;
		endcase
	end
end







reg cycle_load_dly_r;	
always @(negedge clk_fast) begin
	if(cycle_load) cycle_load_dly_r <= 1;
	else           cycle_load_dly_r <= 0;
end



wire        cmem_wr = first_cycle_r&clk_slow;
wire        cmem_clk;
wire [5:0]  cmem_addr;
reg  [5:0]  cmem_addr_r;
wire [16:0] cmem_din_FP16i = cin;

reg         dmem_wr_r;
wire         dmem_clk;
wire         dmem_clk_en;

reg [5:0]	 dmem_addr_r;


wire din_latch;
reg [15:0] din_r;

assign cmem_addr = (first_cycle_r) ? caddr : cmem_addr_r;

wire dmem_cmem_rst = dmem_wr_r&~dmem_clk;
reg cycle_dinlatch_pulse_r;

always @(posedge cycle_dinlatch or negedge clk_fast) begin
	if(~clk_fast) cycle_dinlatch_pulse_r <= 0;
	else          cycle_dinlatch_pulse_r <= 1;
end

always @(posedge cycle_dinlatch) begin
	din_r <= din;
end
always @(posedge cycle_dinlatch_pulse_r or negedge dmem_clk) begin
	if(cycle_dinlatch_pulse_r) begin

		cmem_addr_r <= 0;
	end else begin

		cmem_addr_r <= cmem_addr_r + 1;
	end
end

always @(negedge clk_fast) begin
	if(cycle_dinlatch&&dmem_wr_r==0) dmem_wr_r <= 1;
	else                             dmem_wr_r <= 0;
end

wire alu_clk_en = ~cycle_sleep;
wire alu_clk;



reg cycle_mul_dly1_r;
always @(posedge alu_clk) begin
	if(cycle_mul)        cycle_mul_dly1_r <= 1;
	else                 cycle_mul_dly1_r <= 0;
end

reg cycle_acc_thru_dly1_r;
always @(negedge alu_clk) begin
	if(cycle_acc_thru) cycle_acc_thru_dly1_r <= 1;
	else               cycle_acc_thru_dly1_r <= 0;
end

reg cycle_acc_thru_dly2_r;
always @(posedge alu_clk) begin
	if(cycle_acc_thru) cycle_acc_thru_dly2_r <= 1;
	else               cycle_acc_thru_dly2_r <= 0;
end

assign din_latch = cycle_dinlatch_pulse_r;
assign dmem_clk_en = (cycle_dinlatch|cycle_load|cycle_mul_ndav|cycle_mul) & ~cycle_acc_thru_dly1_r;


always @(negedge clk_fast or negedge rst_n) begin
	if(~rst_n)	dmem_addr_r <= 0;
	else if(dmem_clk_en) dmem_addr_r <= dmem_addr_r + 1;
end



`ifdef USE_VENDOR_CGC
		
`else
	icgc u_cgc_cmem(.CK(clk_fast),.E(first_cycle_r|dmem_clk_en),.ECK(cmem_clk));

	assign alu_clk = clk_fast & alu_clk_en;
	assign dmem_clk  = dmem_clk_en & clk_fast;

`endif





reg  regf_wr_r;
wire regf_clken = (regf_wr_r|cycle_acc_thru);
wire regf_clk   = regf_clken & alu_clk;
reg [5:0]    regf_addr_r;

always @(negedge alu_clk) begin
	if(cycle_mul&~cycle_acc_thru_dly2_r) regf_wr_r = 1;
	else                          regf_wr_r = 0;

	if((~regf_clken)|(cycle_mul&cycle_acc_thru_dly2_r)) regf_addr_r <= 0;
	else            regf_addr_r <= regf_addr_r + 1;
end





wire [15:0] dmem_q_fp16;
wire [16:0] cmem_q_fp16i;
wire [28:0] regf_q_fp29i;


wire [28:0] alumux_din_fp16;
wire [28:0] alumux_dmem_fp16;
wire [28:0] alumux_cmem_fp16i;
wire [28:0] alumux_self_fp29i; 
wire [28:0] alumux_regf_fp29i;
wire [28:0] alumux_acc_fp29i;

reg [1:0]   alu_opcode;


reg [28:0]  alu_a_29i_r;
reg [28:0]  alu_b_29i_r;
reg [28:0]  alu_a_29i;
reg [28:0]  alu_b_29i;
wire        alu_a_s = alu_a_29i_r[28];
wire [5:0]  alu_a_e = alu_a_29i_r[27:22];
wire [21:0] alu_a_m = alu_a_29i_r[21:0];
wire        alu_b_s = alu_b_29i_r[28];
wire [5:0]  alu_b_e = alu_b_29i_r[27:22];
wire [21:0] alu_b_m = alu_b_29i_r[21:0];
wire        alu_y_s;
wire [5:0]	alu_y_e;
wire [21:0]	alu_y_m;
wire [28:0] alu_y_29i = {alu_y_s, alu_y_e, alu_y_m};


reg [28:0] alumux_dly;
reg [28:0] alumux_dly1;
reg [28:0] alumux_dly2;
reg [28:0] alumux_dly3;
always @(negedge alu_clk) begin
	if(cycle_acc_p1|cycle_acc_dwr) begin
		alumux_dly <= alumux_self_fp29i;
		alumux_dly1 <= alumux_dly;
		alumux_dly2 <= alumux_dly1;
	end
	if(cycle_acc_p1) begin
		alumux_dly3 <= alumux_dly2;
	end
end


reg [1:0] alu_opcode_r;
always @(posedge alu_clk) begin
	alu_a_29i_r  <= alu_a_29i;
	alu_b_29i_r  <= alu_b_29i;
	alu_opcode_r <= alu_opcode;
end





assign alumux_din_fp16  = {din_r[15], 1'bx, din_r[14:10], {12{1'bx}}, din_r[9:0]};
assign alumux_dmem_fp16  = {dmem_q_fp16[15], 1'bx, dmem_q_fp16[14:10], {12{1'bx}}, dmem_q_fp16[9:0]};


assign alumux_cmem_fp16i = {cmem_q_fp16i[16], 1'bx, cmem_q_fp16i[15:11], {11{1'bx}}, cmem_q_fp16i[10:0]};
assign alumux_regf_fp29i = regf_q_fp29i;
assign alumux_self_fp29i = alu_y_29i;
`ifdef DEBUGINFO
integer dbg_alumux_state;
`endif
always @* begin
	alu_opcode = 2'bxx;


	if(cycle_dinlatch) begin
		alu_a_29i = alumux_din_fp16;
		alu_b_29i = alumux_cmem_fp16i;
		alu_opcode = 2'b10;
		`ifdef DEBUGINFO
			dbg_alumux_state = 0;
		`endif
	end

	if((cycle_mul_ndav|cycle_mul)&~cycle_acc_thru) begin
		alu_a_29i = alumux_dmem_fp16;
		alu_b_29i = alumux_cmem_fp16i;
		alu_opcode = 2'b10;
		`ifdef DEBUGINFO
			dbg_alumux_state = 1;
		`endif
	end         
	

	if(cycle_acc_thru&~cycle_acc) begin		
		alu_a_29i = alumux_self_fp29i;	
		alu_b_29i = 30'b0;
		alu_opcode = 2'b11;
		`ifdef DEBUGINFO
			dbg_alumux_state = 2;
		`endif
	end 


	if(cycle_acc&~cycle_acc_p1) begin
		alu_a_29i = alumux_self_fp29i;
		alu_b_29i = alumux_regf_fp29i;
		alu_opcode = 2'b11;
		`ifdef DEBUGINFO
			dbg_alumux_state = 3;
		`endif
	end 


	if(cycle_acc_p1 & ~cycle_acc_cwr) begin
		alu_a_29i = alumux_self_fp29i;
		alu_b_29i = {29{1'b0}};
		alu_opcode = 2'b11;
		`ifdef DEBUGINFO
			dbg_alumux_state = 4;
		`endif
	end


	if((cycle_acc_cwr|cycle_acc_dwr|cycle_acc_ewr)&~cycle_acc_p21) begin
		alu_a_29i = alumux_dly;
		alu_b_29i = alu_a_29i_r;
		alu_opcode = 2'bxx;
		`ifdef DEBUGINFO
			dbg_alumux_state = 5;
		`endif
	end


	if(cycle_acc_p21&~cycle_acc_p22) begin
		alu_a_29i = alumux_self_fp29i;
		alu_b_29i = alumux_dly1;
		alu_opcode = 2'b11;
		`ifdef DEBUGINFO
			dbg_alumux_state = 6;
		`endif
	end


	if(cycle_acc_p22&~cycle_acc_p31) begin
		alu_a_29i = {30{1'bx}};
		alu_b_29i = {30{1'bx}};
		alu_opcode = 2'bxx;
		`ifdef DEBUGINFO
			dbg_alumux_state = 7;
		`endif
	end
	

	if(cycle_acc_p31&~cycle_acc_p32) begin
		alu_a_29i = alumux_self_fp29i;
		alu_b_29i = alumux_dly2;
		alu_opcode = 2'b11;
		`ifdef DEBUGINFO
			dbg_alumux_state = 8;
		`endif
	end


	if(cycle_acc_p32&~cycle_accnorm) begin
		alu_a_29i = {30{1'bx}};
		alu_b_29i = {30{1'bx}};
		alu_opcode = 2'bxx;
		`ifdef DEBUGINFO
			dbg_alumux_state = 9;
		`endif
	end


	if(cycle_accnorm&~cycle_sleep) begin
		alu_a_29i = alumux_self_fp29i;
		alu_b_29i = alumux_dly3;
		alu_opcode = 2'b00;
		`ifdef DEBUGINFO
			dbg_alumux_state = 10;
		`endif
	end
end


`ifdef USE_DUMMY_ALU
	FPALU_dummy u_fpalu(
		.clk               (alu_clk   ),
		.opcode            (alu_opcode_r),
		.din_uni_a_sgn     (alu_a_s   ),
		.din_uni_a_exp     (alu_a_e   ),
		.din_uni_a_man_dn  (alu_a_m   ),
		.din_uni_b_sgn     (alu_b_s   ),
		.din_uni_b_exp     (alu_b_e   ),
		.din_uni_b_man_dn  (alu_b_m   ),
		.dout_uni_y_sgn    (alu_y_s   ),
		.dout_uni_y_exp    (alu_y_e   ),
		.dout_uni_y_man_dn (alu_y_m   )
	);
`else
	FPALU u_fpalu(
		.clk               (alu_clk   ),
		.opcode            (alu_opcode_r),
		.din_uni_a_sgn     (alu_a_s   ),
		.din_uni_a_exp     (alu_a_e   ),
		.din_uni_a_man_dn  (alu_a_m   ),
		.din_uni_b_sgn     (alu_b_s   ),
		.din_uni_b_exp     (alu_b_e   ),
		.din_uni_b_man_dn  (alu_b_m   ),
		.dout_uni_y_sgn    (alu_y_s   ),
		.dout_uni_y_exp    (alu_y_e   ),
		.dout_uni_y_man_dn (alu_y_m   )
	);
`endif
assign dout     = alu_y_29i;
assign dout_29i = alu_y_29i;





`ifdef USE_VENDOR_MEMORY
	

	SP_DMEM u_dmem (
		.Q   (dmem_q_fp16),
		.CLK (clk_fast  ),
		.CEN (~dmem_clk_en),
		.WEN (~dmem_wr_r ),
		.A   (dmem_addr_r),
		.D   (din_r        )
	);



	wire [15:0] cmem_q_fp16;
	wire [15:0] cmem_din_fp16;
	SP_CMEM u_cmem (
		.Q   (cmem_q_fp16),
		.CLK (clk_fast^first_cycle_r),
		.CEN (~(first_cycle_r|dmem_clk_en)),
		.WEN (~cmem_wr   ),
		.A   (cmem_addr  ),
		.D   (cmem_din_fp16)
	);
	assign cmem_q_fp16i[16]    = cmem_q_fp16[15];
	assign cmem_q_fp16i[15:12] = cmem_q_fp16[14:11];
	assign cmem_q_fp16i[11]    = 1'b1;
	assign cmem_q_fp16i[10:0]  = cmem_q_fp16[10:0];

	assign cmem_din_fp16[15]    = cmem_din_FP16i[16];
	assign cmem_din_fp16[14:11] = cmem_din_FP16i[15:12];
	assign cmem_din_fp16[10:0]  = cmem_din_FP16i[10:0];


	SP_REGF u_regf (
		.Q   (regf_q_fp29i ),
		.CLK (regf_clk     ),
		.CEN (~rst_n       ),
		.WEN (~regf_wr_r   ),
		.A   (regf_addr_r  ),
		.D   (alumux_self_fp29i)
	);

`else


sp_sram #(
	.ADDR_WIDTH(6),
	.DATA_WIDTH(16)
) u_dmem (
	.clk  (dmem_clk   ),
	.addr (dmem_addr_r),
	.din  (din_r        ),
	.wr   (dmem_wr_r  ),
	.qout (dmem_q_fp16)
);


sp_sram #(
	.ADDR_WIDTH(6),
	.DATA_WIDTH(17)
) u_cmem (
	.clk  (cmem_clk      ),
	.addr (cmem_addr     ),
	.din  (cmem_din_FP16i),
	.wr   (cmem_wr       ),
	.qout (cmem_q_fp16i  )
);


sp_sram #(
	.ADDR_WIDTH(6),
	.DATA_WIDTH(29)
) u_regf (
	.clk  (regf_clk         ),
	.addr (regf_addr_r      ),
	.din  (alumux_self_fp29i),
	.wr   (regf_wr_r        ),
	.qout (regf_q_fp29i     )
);

`endif



`ifdef DEBUGINFO
integer dbg_alu_clk_cnt;
reg     dbg_alu_outrdy;
always @(posedge alu_clk or posedge cycle_dinlatch) begin
	if(cycle_dinlatch) begin
		dbg_alu_clk_cnt <= 0;
		dbg_alu_outrdy <= 0;
	end else begin          
		dbg_alu_clk_cnt <= dbg_alu_clk_cnt + 1;
		if(dbg_alu_clk_cnt==3)  
			dbg_alu_outrdy <= 1;
	end
end 

`endif

endmodule