data/full_repos/permissive/518460376/verilog/rtl/ips/apb/apb_spi_master/spi_master_controller.v
1: b'%Error: data/full_repos/permissive/518460376/verilog/rtl/ips/apb/apb_spi_master/spi_master_controller.v:112: Cannot find file containing module: \'spi_master_clkgen\'\n spi_master_clkgen u_clkgen(\n ^~~~~~~~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/518460376/verilog/rtl/ips/apb/apb_spi_master,data/full_repos/permissive/518460376/spi_master_clkgen\n             data/full_repos/permissive/518460376/verilog/rtl/ips/apb/apb_spi_master,data/full_repos/permissive/518460376/spi_master_clkgen.v\n             data/full_repos/permissive/518460376/verilog/rtl/ips/apb/apb_spi_master,data/full_repos/permissive/518460376/spi_master_clkgen.sv\n             spi_master_clkgen\n             spi_master_clkgen.v\n             spi_master_clkgen.sv\n             obj_dir/spi_master_clkgen\n             obj_dir/spi_master_clkgen.v\n             obj_dir/spi_master_clkgen.sv\n%Error: data/full_repos/permissive/518460376/verilog/rtl/ips/apb/apb_spi_master/spi_master_controller.v:122: Cannot find file containing module: \'spi_master_tx\'\n spi_master_tx u_txreg(\n ^~~~~~~~~~~~~\n%Error: data/full_repos/permissive/518460376/verilog/rtl/ips/apb/apb_spi_master/spi_master_controller.v:140: Cannot find file containing module: \'spi_master_rx\'\n spi_master_rx u_rxreg(\n ^~~~~~~~~~~~~\n%Warning-WIDTH: data/full_repos/permissive/518460376/verilog/rtl/ips/apb/apb_spi_master/spi_master_controller.v:164: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS\'s CONST \'1\'sh0\' generates 1 bits.\n                                                                                                                   : ... In instance spi_master_controller\n    data_to_tx = 1\'sb0;\n               ^\n                ... Use "/* verilator lint_off WIDTH */" and lint_on around source to disable this message.\n%Warning-WIDTH: data/full_repos/permissive/518460376/verilog/rtl/ips/apb/apb_spi_master/spi_master_controller.v:169: Operator ASSIGN expects 32 bits on the Assign RHS, but Assign RHS\'s CONST \'1\'sh0\' generates 1 bits.\n                                                                                                                   : ... In instance spi_master_controller\n    data_to_tx = 1\'sb0;\n               ^\n%Warning-WIDTH: data/full_repos/permissive/518460376/verilog/rtl/ips/apb/apb_spi_master/spi_master_controller.v:192: Operator ASSIGN expects 16 bits on the Assign RHS, but Assign RHS\'s CONST \'1\'sh0\' generates 1 bits.\n                                                                                                                   : ... In instance spi_master_controller\n  counter_tx = 1\'sb0;\n             ^\n%Warning-WIDTH: data/full_repos/permissive/518460376/verilog/rtl/ips/apb/apb_spi_master/spi_master_controller.v:194: Operator ASSIGN expects 16 bits on the Assign RHS, but Assign RHS\'s CONST \'1\'sh0\' generates 1 bits.\n                                                                                                                   : ... In instance spi_master_controller\n  counter_rx = 1\'sb0;\n             ^\n%Warning-WIDTH: data/full_repos/permissive/518460376/verilog/rtl/ips/apb/apb_spi_master/spi_master_controller.v:201: Operator ASSIGN expects 7 bits on the Assign RHS, but Assign RHS\'s CONST \'1\'sh0\' generates 1 bits.\n                                                                                                                   : ... In instance spi_master_controller\n  spi_status = 1\'sb0;\n             ^\n%Warning-WIDTH: data/full_repos/permissive/518460376/verilog/rtl/ips/apb/apb_spi_master/spi_master_controller.v:213: Operator ASSIGN expects 16 bits on the Assign RHS, but Assign RHS\'s REPLICATE generates 14 bits.\n                                                                                                                   : ... In instance spi_master_controller\n      counter_tx = {8\'h00, spi_cmd_len};\n                 ^\n%Warning-WIDTH: data/full_repos/permissive/518460376/verilog/rtl/ips/apb/apb_spi_master/spi_master_controller.v:222: Operator ASSIGN expects 16 bits on the Assign RHS, but Assign RHS\'s REPLICATE generates 14 bits.\n                                                                                                                   : ... In instance spi_master_controller\n      counter_tx = {8\'h00, spi_addr_len};\n                 ^\n%Warning-WIDTH: data/full_repos/permissive/518460376/verilog/rtl/ips/apb/apb_spi_master/spi_master_controller.v:278: Operator ASSIGN expects 16 bits on the Assign RHS, but Assign RHS\'s REPLICATE generates 14 bits.\n                                                                                                                   : ... In instance spi_master_controller\n      counter_tx = {8\'h00, spi_addr_len};\n                 ^\n%Error: Exiting due to 3 error(s), 8 warning(s)\n'
module spi_master_controller (
	clk,
	rstn,
	eot,
	spi_clk_div,
	spi_clk_div_valid,
	spi_status,
	spi_addr,
	spi_addr_len,
	spi_cmd,
	spi_cmd_len,
	spi_data_len,
	spi_dummy_rd,
	spi_dummy_wr,
	spi_csreg,
	spi_swrst,
	spi_rd,
	spi_wr,
	spi_qrd,
	spi_qwr,
	spi_ctrl_data_tx,
	spi_ctrl_data_tx_valid,
	spi_ctrl_data_tx_ready,
	spi_ctrl_data_rx,
	spi_ctrl_data_rx_valid,
	spi_ctrl_data_rx_ready,
	spi_clk,
	spi_csn0,
	spi_csn1,
	spi_csn2,
	spi_csn3,
	spi_mode,
	spi_sdo0,
	spi_sdo1,
	spi_sdo2,
	spi_sdo3,
	spi_sdi0,
	spi_sdi1,
	spi_sdi2,
	spi_sdi3
);
	input wire clk;
	input wire rstn;
	output reg eot;
	input wire [7:0] spi_clk_div;
	input wire spi_clk_div_valid;
	output reg [6:0] spi_status;
	input wire [31:0] spi_addr;
	input wire [5:0] spi_addr_len;
	input wire [31:0] spi_cmd;
	input wire [5:0] spi_cmd_len;
	input wire [15:0] spi_data_len;
	input wire [15:0] spi_dummy_rd;
	input wire [15:0] spi_dummy_wr;
	input wire [3:0] spi_csreg;
	input wire spi_swrst;
	input wire spi_rd;
	input wire spi_wr;
	input wire spi_qrd;
	input wire spi_qwr;
	input wire [31:0] spi_ctrl_data_tx;
	input wire spi_ctrl_data_tx_valid;
	output reg spi_ctrl_data_tx_ready;
	output wire [31:0] spi_ctrl_data_rx;
	output wire spi_ctrl_data_rx_valid;
	input wire spi_ctrl_data_rx_ready;
	output wire spi_clk;
	output wire spi_csn0;
	output wire spi_csn1;
	output wire spi_csn2;
	output wire spi_csn3;
	output reg [1:0] spi_mode;
	output wire spi_sdo0;
	output wire spi_sdo1;
	output wire spi_sdo2;
	output wire spi_sdo3;
	input wire spi_sdi0;
	input wire spi_sdi1;
	input wire spi_sdi2;
	input wire spi_sdi3;
	wire spi_rise;
	wire spi_fall;
	reg spi_clock_en;
	reg spi_en_tx;
	reg spi_en_rx;
	reg [15:0] counter_tx;
	reg counter_tx_valid;
	reg [15:0] counter_rx;
	reg counter_rx_valid;
	reg [31:0] data_to_tx;
	reg data_to_tx_valid;
	wire data_to_tx_ready;
	wire en_quad;
	reg en_quad_int;
	reg do_tx;
	reg do_rx;
	wire tx_done;
	wire rx_done;
	reg [1:0] s_spi_mode;
	reg ctrl_data_valid;
	reg spi_cs;
	wire tx_clk_en;
	wire rx_clk_en;
	reg [2:0] ctrl_data_mux;
	reg [4:0] state;
	reg [4:0] state_next;
	assign en_quad = (spi_qrd | spi_qwr) | en_quad_int;
	spi_master_clkgen u_clkgen(
		.clk(clk),
		.rstn(rstn),
		.en(spi_clock_en),
		.clk_div(spi_clk_div),
		.clk_div_valid(spi_clk_div_valid),
		.spi_clk(spi_clk),
		.spi_fall(spi_fall),
		.spi_rise(spi_rise)
	);
	spi_master_tx u_txreg(
		.clk(clk),
		.rstn(rstn),
		.en(spi_en_tx),
		.tx_edge(spi_fall),
		.tx_done(tx_done),
		.sdo0(spi_sdo0),
		.sdo1(spi_sdo1),
		.sdo2(spi_sdo2),
		.sdo3(spi_sdo3),
		.en_quad_in(en_quad),
		.counter_in(counter_tx),
		.counter_in_upd(counter_tx_valid),
		.data(data_to_tx),
		.data_valid(data_to_tx_valid),
		.data_ready(data_to_tx_ready),
		.clk_en_o(tx_clk_en)
	);
	spi_master_rx u_rxreg(
		.clk(clk),
		.rstn(rstn),
		.en(spi_en_rx),
		.rx_edge(spi_rise),
		.rx_done(rx_done),
		.sdi0(spi_sdi0),
		.sdi1(spi_sdi1),
		.sdi2(spi_sdi2),
		.sdi3(spi_sdi3),
		.en_quad_in(en_quad),
		.counter_in(counter_rx),
		.counter_in_upd(counter_rx_valid),
		.data(spi_ctrl_data_rx),
		.data_valid(spi_ctrl_data_rx_valid),
		.data_ready(spi_ctrl_data_rx_ready),
		.clk_en_o(rx_clk_en)
	);
	always @(*) begin
		data_to_tx = 'h0;
		data_to_tx_valid = 1'b0;
		spi_ctrl_data_tx_ready = 1'b0;
		case (ctrl_data_mux)
			3'd0: begin
				data_to_tx = 1'sb0;
				data_to_tx_valid = 1'b0;
				spi_ctrl_data_tx_ready = 1'b0;
			end
			3'd1: begin
				data_to_tx = 1'sb0;
				data_to_tx_valid = 1'b1;
			end
			3'd2: begin
				data_to_tx = spi_cmd;
				data_to_tx_valid = ctrl_data_valid;
				spi_ctrl_data_tx_ready = 1'b0;
			end
			3'd3: begin
				data_to_tx = spi_addr;
				data_to_tx_valid = ctrl_data_valid;
				spi_ctrl_data_tx_ready = 1'b0;
			end
			3'd4: begin
				data_to_tx = spi_ctrl_data_tx;
				data_to_tx_valid = spi_ctrl_data_tx_valid;
				spi_ctrl_data_tx_ready = data_to_tx_ready;
			end
		endcase
	end
	always @(*) begin
		spi_cs = 1'b1;
		spi_clock_en = 1'b0;
		counter_tx = 1'sb0;
		counter_tx_valid = 1'b0;
		counter_rx = 1'sb0;
		counter_rx_valid = 1'b0;
		state_next = state;
		ctrl_data_mux = 3'd0;
		ctrl_data_valid = 1'b0;
		spi_en_rx = 1'b0;
		spi_en_tx = 1'b0;
		spi_status = 1'sb0;
		s_spi_mode = 2'b10;
		eot = 1'b0;
		case (state)
			5'd0: begin
				spi_status[0] = 1'b1;
				s_spi_mode = 2'b10;
				if (((spi_rd || spi_wr) || spi_qrd) || spi_qwr) begin
					spi_cs = 1'b0;
					spi_clock_en = 1'b1;
					if (spi_cmd_len != 0) begin
						s_spi_mode = (spi_qrd | spi_qwr ? 2'b01 : 2'b00);
						counter_tx = {8'h00, spi_cmd_len};
						counter_tx_valid = 1'b1;
						ctrl_data_mux = 3'd2;
						ctrl_data_valid = 1'b1;
						spi_en_tx = 1'b1;
						state_next = 5'd1;
					end
					else if (spi_addr_len != 0) begin
						s_spi_mode = (spi_qrd | spi_qwr ? 2'b01 : 2'b00);
						counter_tx = {8'h00, spi_addr_len};
						counter_tx_valid = 1'b1;
						ctrl_data_mux = 3'd3;
						ctrl_data_valid = 1'b1;
						spi_en_tx = 1'b1;
						state_next = 5'd2;
					end
					else if (spi_data_len != 0)
						if (spi_rd || spi_qrd) begin
							s_spi_mode = (spi_qrd ? 2'b10 : 2'b00);
							if (spi_dummy_rd != 0) begin
								counter_tx = (en_quad ? {spi_dummy_rd[13:0], 2'b00} : spi_dummy_rd);
								counter_tx_valid = 1'b1;
								spi_en_tx = 1'b1;
								ctrl_data_mux = 3'd1;
								state_next = 5'd4;
							end
							else begin
								counter_rx = spi_data_len;
								counter_rx_valid = 1'b1;
								spi_en_rx = 1'b1;
								state_next = 5'd6;
							end
						end
						else begin
							s_spi_mode = (spi_qwr ? 2'b01 : 2'b00);
							if (spi_dummy_wr != 0) begin
								counter_tx = (en_quad ? {spi_dummy_wr[13:0], 2'b00} : spi_dummy_wr);
								counter_tx_valid = 1'b1;
								ctrl_data_mux = 3'd1;
								spi_en_tx = 1'b1;
								state_next = 5'd4;
							end
							else begin
								counter_tx = spi_data_len;
								counter_tx_valid = 1'b1;
								ctrl_data_mux = 3'd4;
								ctrl_data_valid = 1'b0;
								spi_en_tx = 1'b1;
								state_next = 5'd5;
							end
						end
				end
				else begin
					spi_cs = 1'b1;
					state_next = 5'd0;
				end
			end
			5'd1: begin
				spi_status[1] = 1'b1;
				spi_cs = 1'b0;
				spi_clock_en = 1'b1;
				s_spi_mode = (en_quad ? 2'b01 : 2'b00);
				if (tx_done) begin
					if (spi_addr_len != 0) begin
						s_spi_mode = (en_quad ? 2'b01 : 2'b00);
						counter_tx = {8'h00, spi_addr_len};
						counter_tx_valid = 1'b1;
						ctrl_data_mux = 3'd3;
						ctrl_data_valid = 1'b1;
						spi_en_tx = 1'b1;
						state_next = 5'd2;
					end
					else if (spi_data_len != 0) begin
						if (do_rx) begin
							s_spi_mode = (en_quad ? 2'b10 : 2'b00);
							if (spi_dummy_rd != 0) begin
								counter_tx = (en_quad ? {spi_dummy_rd[13:0], 2'b00} : spi_dummy_rd);
								counter_tx_valid = 1'b1;
								spi_en_tx = 1'b1;
								ctrl_data_mux = 3'd1;
								state_next = 5'd4;
							end
							else begin
								counter_rx = spi_data_len;
								counter_rx_valid = 1'b1;
								spi_en_rx = 1'b1;
								state_next = 5'd6;
							end
						end
						else begin
							s_spi_mode = (en_quad ? 2'b01 : 2'b00);
							if (spi_dummy_wr != 0) begin
								counter_tx = (en_quad ? {spi_dummy_wr[13:0], 2'b00} : spi_dummy_wr);
								counter_tx_valid = 1'b1;
								ctrl_data_mux = 3'd1;
								spi_en_tx = 1'b1;
								state_next = 5'd4;
							end
							else begin
								counter_tx = spi_data_len;
								counter_tx_valid = 1'b1;
								ctrl_data_mux = 3'd4;
								ctrl_data_valid = 1'b1;
								spi_en_tx = 1'b1;
								state_next = 5'd5;
							end
						end
					end
					else
						state_next = 5'd0;
				end
				else begin
					spi_en_tx = 1'b1;
					state_next = 5'd1;
				end
			end
			5'd2: begin
				spi_en_tx = 1'b1;
				spi_status[2] = 1'b1;
				spi_cs = 1'b0;
				spi_clock_en = 1'b1;
				s_spi_mode = (en_quad ? 2'b01 : 2'b00);
				if (tx_done)
					if (spi_data_len != 0) begin
						if (do_rx) begin
							s_spi_mode = (en_quad ? 2'b10 : 2'b00);
							if (spi_dummy_rd != 0) begin
								counter_tx = (en_quad ? {spi_dummy_rd[13:0], 2'b00} : spi_dummy_rd);
								counter_tx_valid = 1'b1;
								spi_en_tx = 1'b1;
								ctrl_data_mux = 3'd1;
								state_next = 5'd4;
							end
							else begin
								counter_rx = spi_data_len;
								counter_rx_valid = 1'b1;
								spi_en_rx = 1'b1;
								state_next = 5'd6;
							end
						end
						else begin
							s_spi_mode = (en_quad ? 2'b01 : 2'b00);
							spi_en_tx = 1'b1;
							if (spi_dummy_wr != 0) begin
								counter_tx = (en_quad ? {spi_dummy_wr[13:0], 2'b00} : spi_dummy_wr);
								counter_tx_valid = 1'b1;
								ctrl_data_mux = 3'd1;
								state_next = 5'd4;
							end
							else begin
								counter_tx = spi_data_len;
								counter_tx_valid = 1'b1;
								ctrl_data_mux = 3'd4;
								ctrl_data_valid = 1'b1;
								state_next = 5'd5;
							end
						end
					end
					else
						state_next = 5'd0;
			end
			5'd3: begin
				spi_status[3] = 1'b1;
				spi_cs = 1'b0;
				spi_clock_en = 1'b1;
				spi_en_tx = 1'b1;
			end
			5'd4: begin
				spi_en_tx = 1'b1;
				spi_status[4] = 1'b1;
				spi_cs = 1'b0;
				spi_clock_en = 1'b1;
				s_spi_mode = (en_quad ? 2'b10 : 2'b00);
				if (tx_done) begin
					if (spi_data_len != 0) begin
						if (do_rx) begin
							counter_rx = spi_data_len;
							counter_rx_valid = 1'b1;
							spi_en_rx = 1'b1;
							state_next = 5'd6;
						end
						else begin
							counter_tx = spi_data_len;
							counter_tx_valid = 1'b1;
							s_spi_mode = (en_quad ? 2'b01 : 2'b00);
							spi_clock_en = tx_clk_en;
							spi_en_tx = 1'b1;
							state_next = 5'd5;
						end
					end
					else begin
						eot = 1'b1;
						state_next = 5'd0;
					end
				end
				else begin
					ctrl_data_mux = 3'd1;
					spi_en_tx = 1'b1;
					state_next = 5'd4;
				end
			end
			5'd5: begin
				spi_status[5] = 1'b1;
				spi_cs = 1'b0;
				spi_clock_en = tx_clk_en;
				ctrl_data_mux = 3'd4;
				ctrl_data_valid = 1'b1;
				spi_en_tx = 1'b1;
				s_spi_mode = (en_quad ? 2'b01 : 2'b00);
				if (tx_done) begin
					eot = 1'b1;
					state_next = 5'd0;
					spi_clock_en = 1'b0;
				end
				else
					state_next = 5'd5;
			end
			5'd6: begin
				spi_status[6] = 1'b1;
				spi_cs = 1'b0;
				spi_clock_en = rx_clk_en;
				s_spi_mode = (en_quad ? 2'b10 : 2'b00);
				if (rx_done)
					state_next = 5'd7;
				else begin
					spi_en_rx = 1'b1;
					state_next = 5'd6;
				end
			end
			5'd7: begin
				spi_status[6] = 1'b1;
				spi_cs = 1'b0;
				spi_clock_en = 1'b0;
				s_spi_mode = (en_quad ? 2'b10 : 2'b00);
				if (spi_fall) begin
					eot = 1'b1;
					state_next = 5'd0;
				end
				else
					state_next = 5'd7;
			end
		endcase
	end
	always @(posedge clk or negedge rstn)
		if (rstn == 1'b0) begin
			state <= 5'd0;
			en_quad_int <= 1'b0;
			do_rx <= 1'b0;
			do_tx <= 1'b0;
			spi_mode <= 2'b10;
		end
		else begin
			state <= state_next;
			spi_mode <= s_spi_mode;
			if (spi_qrd || spi_qwr)
				en_quad_int <= 1'b1;
			else if (state_next == 5'd0)
				en_quad_int <= 1'b0;
			if (spi_rd || spi_qrd) begin
				do_rx <= 1'b1;
				do_tx <= 1'b0;
			end
			else if (spi_wr || spi_qwr) begin
				do_rx <= 1'b0;
				do_tx <= 1'b1;
			end
			else if (state_next == 5'd0) begin
				do_rx <= 1'b0;
				do_tx <= 1'b0;
			end
		end
	assign spi_csn0 = ~spi_csreg[0] | spi_cs;
	assign spi_csn1 = ~spi_csreg[1] | spi_cs;
	assign spi_csn2 = ~spi_csreg[2] | spi_cs;
	assign spi_csn3 = ~spi_csreg[3] | spi_cs;
endmodule
module spi_master_controller (
	clk,
	rstn,
	eot,
	spi_clk_div,
	spi_clk_div_valid,
	spi_status,
	spi_addr,
	spi_addr_len,
	spi_cmd,
	spi_cmd_len,
	spi_data_len,
	spi_dummy_rd,
	spi_dummy_wr,
	spi_csreg,
	spi_swrst,
	spi_rd,
	spi_wr,
	spi_qrd,
	spi_qwr,
	spi_ctrl_data_tx,
	spi_ctrl_data_tx_valid,
	spi_ctrl_data_tx_ready,
	spi_ctrl_data_rx,
	spi_ctrl_data_rx_valid,
	spi_ctrl_data_rx_ready,
	spi_clk,
	spi_csn0,
	spi_csn1,
	spi_csn2,
	spi_csn3,
	spi_mode,
	spi_sdo0,
	spi_sdo1,
	spi_sdo2,
	spi_sdo3,
	spi_sdi0,
	spi_sdi1,
	spi_sdi2,
	spi_sdi3
);

	input wire clk;
	input wire rstn;
	output reg eot;
	input wire [7:0] spi_clk_div;
	input wire spi_clk_div_valid;
	output reg [6:0] spi_status;
	input wire [31:0] spi_addr;
	input wire [5:0] spi_addr_len;
	input wire [31:0] spi_cmd;
	input wire [5:0] spi_cmd_len;
	input wire [15:0] spi_data_len;
	input wire [15:0] spi_dummy_rd;
	input wire [15:0] spi_dummy_wr;
	input wire [3:0] spi_csreg;
	input wire spi_swrst;
	input wire spi_rd;
	input wire spi_wr;
	input wire spi_qrd;
	input wire spi_qwr;
	input wire [31:0] spi_ctrl_data_tx;
	input wire spi_ctrl_data_tx_valid;
	output reg spi_ctrl_data_tx_ready;
	output wire [31:0] spi_ctrl_data_rx;
	output wire spi_ctrl_data_rx_valid;
	input wire spi_ctrl_data_rx_ready;
	output wire spi_clk;
	output wire spi_csn0;
	output wire spi_csn1;
	output wire spi_csn2;
	output wire spi_csn3;
	output reg [1:0] spi_mode;
	output wire spi_sdo0;
	output wire spi_sdo1;
	output wire spi_sdo2;
	output wire spi_sdo3;
	input wire spi_sdi0;
	input wire spi_sdi1;
	input wire spi_sdi2;
	input wire spi_sdi3;
	wire spi_rise;
	wire spi_fall;
	reg spi_clock_en;
	reg spi_en_tx;
	reg spi_en_rx;
	reg [15:0] counter_tx;
	reg counter_tx_valid;
	reg [15:0] counter_rx;
	reg counter_rx_valid;
	reg [31:0] data_to_tx;
	reg data_to_tx_valid;
	wire data_to_tx_ready;
	wire en_quad;
	reg en_quad_int;
	reg do_tx;
	reg do_rx;
	wire tx_done;
	wire rx_done;
	reg [1:0] s_spi_mode;
	reg ctrl_data_valid;
	reg spi_cs;
	wire tx_clk_en;
	wire rx_clk_en;
	reg [2:0] ctrl_data_mux;
	reg [4:0] state;
	reg [4:0] state_next;
	assign en_quad = (spi_qrd | spi_qwr) | en_quad_int;
	spi_master_clkgen u_clkgen(
		.clk(clk),
		.rstn(rstn),
		.en(spi_clock_en),
		.clk_div(spi_clk_div),
		.clk_div_valid(spi_clk_div_valid),
		.spi_clk(spi_clk),
		.spi_fall(spi_fall),
		.spi_rise(spi_rise)
	);
	spi_master_tx u_txreg(
		.clk(clk),
		.rstn(rstn),
		.en(spi_en_tx),
		.tx_edge(spi_fall),
		.tx_done(tx_done),
		.sdo0(spi_sdo0),
		.sdo1(spi_sdo1),
		.sdo2(spi_sdo2),
		.sdo3(spi_sdo3),
		.en_quad_in(en_quad),
		.counter_in(counter_tx),
		.counter_in_upd(counter_tx_valid),
		.data(data_to_tx),
		.data_valid(data_to_tx_valid),
		.data_ready(data_to_tx_ready),
		.clk_en_o(tx_clk_en)
	);
	spi_master_rx u_rxreg(
		.clk(clk),
		.rstn(rstn),
		.en(spi_en_rx),
		.rx_edge(spi_rise),
		.rx_done(rx_done),
		.sdi0(spi_sdi0),
		.sdi1(spi_sdi1),
		.sdi2(spi_sdi2),
		.sdi3(spi_sdi3),
		.en_quad_in(en_quad),
		.counter_in(counter_rx),
		.counter_in_upd(counter_rx_valid),
		.data(spi_ctrl_data_rx),
		.data_valid(spi_ctrl_data_rx_valid),
		.data_ready(spi_ctrl_data_rx_ready),
		.clk_en_o(rx_clk_en)
	);
	always @(*) begin
		data_to_tx = 'h0;
		data_to_tx_valid = 1'b0;
		spi_ctrl_data_tx_ready = 1'b0;
		case (ctrl_data_mux)
			3'd0: begin
				data_to_tx = 1'sb0;
				data_to_tx_valid = 1'b0;
				spi_ctrl_data_tx_ready = 1'b0;
			end
			3'd1: begin
				data_to_tx = 1'sb0;
				data_to_tx_valid = 1'b1;
			end
			3'd2: begin
				data_to_tx = spi_cmd;
				data_to_tx_valid = ctrl_data_valid;
				spi_ctrl_data_tx_ready = 1'b0;
			end
			3'd3: begin
				data_to_tx = spi_addr;
				data_to_tx_valid = ctrl_data_valid;
				spi_ctrl_data_tx_ready = 1'b0;
			end
			3'd4: begin
				data_to_tx = spi_ctrl_data_tx;
				data_to_tx_valid = spi_ctrl_data_tx_valid;
				spi_ctrl_data_tx_ready = data_to_tx_ready;
			end
		endcase
	end
	always @(*) begin
		spi_cs = 1'b1;
		spi_clock_en = 1'b0;
		counter_tx = 1'sb0;
		counter_tx_valid = 1'b0;
		counter_rx = 1'sb0;
		counter_rx_valid = 1'b0;
		state_next = state;
		ctrl_data_mux = 3'd0;
		ctrl_data_valid = 1'b0;
		spi_en_rx = 1'b0;
		spi_en_tx = 1'b0;
		spi_status = 1'sb0;
		s_spi_mode = 2'b10;
		eot = 1'b0;
		case (state)
			5'd0: begin
				spi_status[0] = 1'b1;
				s_spi_mode = 2'b10;
				if (((spi_rd || spi_wr) || spi_qrd) || spi_qwr) begin
					spi_cs = 1'b0;
					spi_clock_en = 1'b1;
					if (spi_cmd_len != 0) begin
						s_spi_mode = (spi_qrd | spi_qwr ? 2'b01 : 2'b00);
						counter_tx = {8'h00, spi_cmd_len};
						counter_tx_valid = 1'b1;
						ctrl_data_mux = 3'd2;
						ctrl_data_valid = 1'b1;
						spi_en_tx = 1'b1;
						state_next = 5'd1;
					end
					else if (spi_addr_len != 0) begin
						s_spi_mode = (spi_qrd | spi_qwr ? 2'b01 : 2'b00);
						counter_tx = {8'h00, spi_addr_len};
						counter_tx_valid = 1'b1;
						ctrl_data_mux = 3'd3;
						ctrl_data_valid = 1'b1;
						spi_en_tx = 1'b1;
						state_next = 5'd2;
					end
					else if (spi_data_len != 0)
						if (spi_rd || spi_qrd) begin
							s_spi_mode = (spi_qrd ? 2'b10 : 2'b00);
							if (spi_dummy_rd != 0) begin
								counter_tx = (en_quad ? {spi_dummy_rd[13:0], 2'b00} : spi_dummy_rd);
								counter_tx_valid = 1'b1;
								spi_en_tx = 1'b1;
								ctrl_data_mux = 3'd1;
								state_next = 5'd4;
							end
							else begin
								counter_rx = spi_data_len;
								counter_rx_valid = 1'b1;
								spi_en_rx = 1'b1;
								state_next = 5'd6;
							end
						end
						else begin
							s_spi_mode = (spi_qwr ? 2'b01 : 2'b00);
							if (spi_dummy_wr != 0) begin
								counter_tx = (en_quad ? {spi_dummy_wr[13:0], 2'b00} : spi_dummy_wr);
								counter_tx_valid = 1'b1;
								ctrl_data_mux = 3'd1;
								spi_en_tx = 1'b1;
								state_next = 5'd4;
							end
							else begin
								counter_tx = spi_data_len;
								counter_tx_valid = 1'b1;
								ctrl_data_mux = 3'd4;
								ctrl_data_valid = 1'b0;
								spi_en_tx = 1'b1;
								state_next = 5'd5;
							end
						end
				end
				else begin
					spi_cs = 1'b1;
					state_next = 5'd0;
				end
			end
			5'd1: begin
				spi_status[1] = 1'b1;
				spi_cs = 1'b0;
				spi_clock_en = 1'b1;
				s_spi_mode = (en_quad ? 2'b01 : 2'b00);
				if (tx_done) begin
					if (spi_addr_len != 0) begin
						s_spi_mode = (en_quad ? 2'b01 : 2'b00);
						counter_tx = {8'h00, spi_addr_len};
						counter_tx_valid = 1'b1;
						ctrl_data_mux = 3'd3;
						ctrl_data_valid = 1'b1;
						spi_en_tx = 1'b1;
						state_next = 5'd2;
					end
					else if (spi_data_len != 0) begin
						if (do_rx) begin
							s_spi_mode = (en_quad ? 2'b10 : 2'b00);
							if (spi_dummy_rd != 0) begin
								counter_tx = (en_quad ? {spi_dummy_rd[13:0], 2'b00} : spi_dummy_rd);
								counter_tx_valid = 1'b1;
								spi_en_tx = 1'b1;
								ctrl_data_mux = 3'd1;
								state_next = 5'd4;
							end
							else begin
								counter_rx = spi_data_len;
								counter_rx_valid = 1'b1;
								spi_en_rx = 1'b1;
								state_next = 5'd6;
							end
						end
						else begin
							s_spi_mode = (en_quad ? 2'b01 : 2'b00);
							if (spi_dummy_wr != 0) begin
								counter_tx = (en_quad ? {spi_dummy_wr[13:0], 2'b00} : spi_dummy_wr);
								counter_tx_valid = 1'b1;
								ctrl_data_mux = 3'd1;
								spi_en_tx = 1'b1;
								state_next = 5'd4;
							end
							else begin
								counter_tx = spi_data_len;
								counter_tx_valid = 1'b1;
								ctrl_data_mux = 3'd4;
								ctrl_data_valid = 1'b1;
								spi_en_tx = 1'b1;
								state_next = 5'd5;
							end
						end
					end
					else
						state_next = 5'd0;
				end
				else begin
					spi_en_tx = 1'b1;
					state_next = 5'd1;
				end
			end
			5'd2: begin
				spi_en_tx = 1'b1;
				spi_status[2] = 1'b1;
				spi_cs = 1'b0;
				spi_clock_en = 1'b1;
				s_spi_mode = (en_quad ? 2'b01 : 2'b00);
				if (tx_done)
					if (spi_data_len != 0) begin
						if (do_rx) begin
							s_spi_mode = (en_quad ? 2'b10 : 2'b00);
							if (spi_dummy_rd != 0) begin
								counter_tx = (en_quad ? {spi_dummy_rd[13:0], 2'b00} : spi_dummy_rd);
								counter_tx_valid = 1'b1;
								spi_en_tx = 1'b1;
								ctrl_data_mux = 3'd1;
								state_next = 5'd4;
							end
							else begin
								counter_rx = spi_data_len;
								counter_rx_valid = 1'b1;
								spi_en_rx = 1'b1;
								state_next = 5'd6;
							end
						end
						else begin
							s_spi_mode = (en_quad ? 2'b01 : 2'b00);
							spi_en_tx = 1'b1;
							if (spi_dummy_wr != 0) begin
								counter_tx = (en_quad ? {spi_dummy_wr[13:0], 2'b00} : spi_dummy_wr);
								counter_tx_valid = 1'b1;
								ctrl_data_mux = 3'd1;
								state_next = 5'd4;
							end
							else begin
								counter_tx = spi_data_len;
								counter_tx_valid = 1'b1;
								ctrl_data_mux = 3'd4;
								ctrl_data_valid = 1'b1;
								state_next = 5'd5;
							end
						end
					end
					else
						state_next = 5'd0;
			end
			5'd3: begin
				spi_status[3] = 1'b1;
				spi_cs = 1'b0;
				spi_clock_en = 1'b1;
				spi_en_tx = 1'b1;
			end
			5'd4: begin
				spi_en_tx = 1'b1;
				spi_status[4] = 1'b1;
				spi_cs = 1'b0;
				spi_clock_en = 1'b1;
				s_spi_mode = (en_quad ? 2'b10 : 2'b00);
				if (tx_done) begin
					if (spi_data_len != 0) begin
						if (do_rx) begin
							counter_rx = spi_data_len;
							counter_rx_valid = 1'b1;
							spi_en_rx = 1'b1;
							state_next = 5'd6;
						end
						else begin
							counter_tx = spi_data_len;
							counter_tx_valid = 1'b1;
							s_spi_mode = (en_quad ? 2'b01 : 2'b00);
							spi_clock_en = tx_clk_en;
							spi_en_tx = 1'b1;
							state_next = 5'd5;
						end
					end
					else begin
						eot = 1'b1;
						state_next = 5'd0;
					end
				end
				else begin
					ctrl_data_mux = 3'd1;
					spi_en_tx = 1'b1;
					state_next = 5'd4;
				end
			end
			5'd5: begin
				spi_status[5] = 1'b1;
				spi_cs = 1'b0;
				spi_clock_en = tx_clk_en;
				ctrl_data_mux = 3'd4;
				ctrl_data_valid = 1'b1;
				spi_en_tx = 1'b1;
				s_spi_mode = (en_quad ? 2'b01 : 2'b00);
				if (tx_done) begin
					eot = 1'b1;
					state_next = 5'd0;
					spi_clock_en = 1'b0;
				end
				else
					state_next = 5'd5;
			end
			5'd6: begin
				spi_status[6] = 1'b1;
				spi_cs = 1'b0;
				spi_clock_en = rx_clk_en;
				s_spi_mode = (en_quad ? 2'b10 : 2'b00);
				if (rx_done)
					state_next = 5'd7;
				else begin
					spi_en_rx = 1'b1;
					state_next = 5'd6;
				end
			end
			5'd7: begin
				spi_status[6] = 1'b1;
				spi_cs = 1'b0;
				spi_clock_en = 1'b0;
				s_spi_mode = (en_quad ? 2'b10 : 2'b00);
				if (spi_fall) begin
					eot = 1'b1;
					state_next = 5'd0;
				end
				else
					state_next = 5'd7;
			end
		endcase
	end
	always @(posedge clk or negedge rstn)
		if (rstn == 1'b0) begin
			state <= 5'd0;
			en_quad_int <= 1'b0;
			do_rx <= 1'b0;
			do_tx <= 1'b0;
			spi_mode <= 2'b10;
		end
		else begin
			state <= state_next;
			spi_mode <= s_spi_mode;
			if (spi_qrd || spi_qwr)
				en_quad_int <= 1'b1;
			else if (state_next == 5'd0)
				en_quad_int <= 1'b0;
			if (spi_rd || spi_qrd) begin
				do_rx <= 1'b1;
				do_tx <= 1'b0;
			end
			else if (spi_wr || spi_qwr) begin
				do_rx <= 1'b0;
				do_tx <= 1'b1;
			end
			else if (state_next == 5'd0) begin
				do_rx <= 1'b0;
				do_tx <= 1'b0;
			end
		end
	assign spi_csn0 = ~spi_csreg[0] | spi_cs;
	assign spi_csn1 = ~spi_csreg[1] | spi_cs;
	assign spi_csn2 = ~spi_csreg[2] | spi_cs;
	assign spi_csn3 = ~spi_csreg[3] | spi_cs;
endmodule