data/full_repos/permissive/51997848/mist_io.v
1: b'%Warning-LITENDIAN: data/full_repos/permissive/51997848/mist_io.v:37: Little bit endian vector: MSB < LSB of bit range: -1:0\n input [(8*STRLEN)-1:0] conf_str,\n       ^\n                    ... Use "/* verilator lint_off LITENDIAN */" and lint_on around source to disable this message.\n%Warning-WIDTHCONCAT: data/full_repos/permissive/51997848/mist_io.v:139: Unsized numbers/parameters not allowed in concatenations.\n                                                                       : ... In instance mist_io\n      if(byte_cnt < STRLEN + 1) spi_do <= conf_str[{STRLEN - byte_cnt,~bit_cnt}];\n                                                           ^\n%Warning-WIDTHCONCAT: data/full_repos/permissive/51997848/mist_io.v:139: Unsized numbers/parameters not allowed in replications.\n                                                                       : ... In instance mist_io\n      if(byte_cnt < STRLEN + 1) spi_do <= conf_str[{STRLEN - byte_cnt,~bit_cnt}];\n                                                                     ^\n%Warning-WIDTH: data/full_repos/permissive/51997848/mist_io.v:139: Bit extraction of var[1:-1] requires 1 bit index, not 35 or 13 bits.\n                                                                 : ... In instance mist_io\n      if(byte_cnt < STRLEN + 1) spi_do <= conf_str[{STRLEN - byte_cnt,~bit_cnt}];\n                                                  ^\n%Warning-WIDTHCONCAT: data/full_repos/permissive/51997848/mist_io.v:146: Unsized numbers/parameters not allowed in concatenations.\n                                                                       : ... In instance mist_io\n      else if((byte_cnt >= 2) && (byte_cnt < 6)) spi_do <= sd_lba[{5-byte_cnt, ~bit_cnt}];\n                                                                    ^\n%Warning-WIDTHCONCAT: data/full_repos/permissive/51997848/mist_io.v:146: Unsized numbers/parameters not allowed in replications.\n                                                                       : ... In instance mist_io\n      else if((byte_cnt >= 2) && (byte_cnt < 6)) spi_do <= sd_lba[{5-byte_cnt, ~bit_cnt}];\n                                                                             ^\n%Warning-WIDTH: data/full_repos/permissive/51997848/mist_io.v:146: Bit extraction of var[31:0] requires 5 bit index, not 35 or 13 bits.\n                                                                 : ... In instance mist_io\n      else if((byte_cnt >= 2) && (byte_cnt < 6)) spi_do <= sd_lba[{5-byte_cnt, ~bit_cnt}];\n                                                                 ^\n%Warning-WIDTH: data/full_repos/permissive/51997848/mist_io.v:193: Operator ADD expects 10 bits on the RHS, but RHS\'s CONST \'8\'h1\' generates 8 bits.\n                                                                 : ... In instance mist_io\n   if(~&byte_cnt) byte_cnt <= byte_cnt + 8\'d1;\n                                       ^\n%Warning-WIDTH: data/full_repos/permissive/51997848/mist_io.v:447: Operator ASSIGNDLY expects 25 bits on the Assign RHS, but Assign RHS\'s VARREF \'start_addr\' generates 16 bits.\n                                                                 : ... In instance mist_io\n   if(addr == 25\'h100003) addr <= start_addr;\n                               ^~\n%Warning-WIDTH: data/full_repos/permissive/51997848/mist_io.v:530: Operator ASSIGNDLY expects 25 bits on the Assign RHS, but Assign RHS\'s VARREF \'start_addr\' generates 16 bits.\n                                                                 : ... In instance mist_io\n   end_addr      <= start_addr;\n                 ^~\n%Warning-WIDTH: data/full_repos/permissive/51997848/mist_io.v:542: Logical Operator LOGNOT expects 1 bit on the LHS, but LHS\'s VARREF \'erase_clk_div\' generates 6 bits.\n                                                                 : ... In instance mist_io\n   if(!erase_clk_div) begin\n      ^\n%Error: Exiting due to 11 warning(s)\n'
module mist_io #(parameter STRLEN=0, parameter PS2DIV=20)
(


	input [(8*STRLEN)-1:0] conf_str,


	input             clk_sys,


	input             SPI_SCK,

	input             CONF_DATA0,
	input             SPI_SS2,
	output            SPI_DO,
	input             SPI_DI,

	output reg  [7:0] joystick_0,
	output reg  [7:0] joystick_1,
	output reg [15:0] joystick_analog_0,
	output reg [15:0] joystick_analog_1,
	output      [1:0] buttons,
	output      [1:0] switches,
	output            scandoubler_disable,
	output            ypbpr,

	output reg [31:0] status,


	input             sd_conf,
	input             sd_sdhc,
	output            img_mounted,
	output reg [31:0] img_size,


	input      [31:0] sd_lba,
	input             sd_rd,
	input             sd_wr,
	output reg        sd_ack,
	output reg        sd_ack_conf,


	output reg  [8:0] sd_buff_addr,
	output reg  [7:0] sd_buff_dout,
	input       [7:0] sd_buff_din,
	output reg        sd_buff_wr,


	output            ps2_kbd_clk,
	output reg        ps2_kbd_data,
	output            ps2_mouse_clk,
	output reg        ps2_mouse_data,
	input             ps2_caps_led,


	input             ioctl_force_erase,
	output reg        ioctl_download = 0,
	output reg        ioctl_erasing = 0,
	output reg  [7:0] ioctl_index,
	output reg        ioctl_wr = 0,
	output reg [24:0] ioctl_addr,
	output reg  [7:0] ioctl_dout
);

reg [7:0] b_data;
reg [6:0] sbuf;
reg [7:0] cmd;
reg [2:0] bit_cnt;
reg [9:0] byte_cnt;
reg [7:0] but_sw;
reg [2:0] stick_idx;

reg    mount_strobe = 0;
assign img_mounted  = mount_strobe;

assign buttons = but_sw[1:0];
assign switches = but_sw[3:2];
assign scandoubler_disable = but_sw[4];
assign ypbpr = but_sw[5];

wire [7:0] spi_dout = { sbuf, SPI_DI};


wire [7:0] core_type = 8'ha4;


wire [7:0] sd_cmd = { 4'h5, sd_conf, sd_sdhc, sd_wr, sd_rd };

reg spi_do;
assign SPI_DO = CONF_DATA0 ? 1'bZ : spi_do;

wire [7:0] kbd_led = { 2'b01, 4'b0000, ps2_caps_led, 1'b1};


always@(negedge SPI_SCK) begin
	if(!CONF_DATA0) begin


      if(byte_cnt == 0) begin
		  spi_do <= core_type[~bit_cnt];

		end else begin
			case(cmd)

				8'h14: begin

						if(byte_cnt < STRLEN + 1) spi_do <= conf_str[{STRLEN - byte_cnt,~bit_cnt}];
							else spi_do <= 0;
					end


				8'h16: begin
						if(byte_cnt == 1) spi_do <= sd_cmd[~bit_cnt];
						else if((byte_cnt >= 2) && (byte_cnt < 6)) spi_do <= sd_lba[{5-byte_cnt, ~bit_cnt}];
						else spi_do <= 0;
					end


				8'h18:
						spi_do <= b_data[~bit_cnt];


				8'h1f:
						spi_do <= kbd_led[~bit_cnt];

				default:
						spi_do <= 0;
			endcase
		end
   end
end

reg b_wr2,b_wr3;
always @(negedge clk_sys) begin
	b_wr3      <= b_wr2;
	sd_buff_wr <= b_wr3;
end


always@(posedge SPI_SCK or posedge CONF_DATA0) begin

	if(CONF_DATA0) begin
		b_wr2 <= 0;
	   bit_cnt <= 0;
	   byte_cnt <= 0;
		sd_ack <= 0;
		sd_ack_conf <= 0;
	end else begin
		b_wr2 <= 0;

		sbuf <= spi_dout[6:0];
		bit_cnt <= bit_cnt + 1'd1;
		if(bit_cnt == 5) begin
			if (byte_cnt == 0) sd_buff_addr <= 0;
			if((byte_cnt != 0) & (sd_buff_addr != 511)) sd_buff_addr <= sd_buff_addr + 1'b1;
			if((byte_cnt == 1) & ((cmd == 8'h17) | (cmd == 8'h19))) sd_buff_addr <= 0;
		end


      if(bit_cnt == 7) begin
			if(~&byte_cnt) byte_cnt <= byte_cnt + 8'd1;
			if(byte_cnt == 0) begin
				cmd <= spi_dout;

				if(spi_dout == 8'h19) begin
					sd_ack_conf  <= 1;
					sd_buff_addr <= 0;
				end
				if((spi_dout == 8'h17) || (spi_dout == 8'h18)) begin
					sd_ack       <= 1;
					sd_buff_addr <= 0;
				end
				if(spi_dout == 8'h18) b_data <= sd_buff_din;

				mount_strobe <= 0;

			end else begin
			
				case(cmd)

					8'h01: but_sw <= spi_dout; 
					8'h02: joystick_0 <= spi_dout;
					8'h03: joystick_1 <= spi_dout;


					8'h04: begin
							ps2_mouse_fifo[ps2_mouse_wptr] <= spi_dout; 
							ps2_mouse_wptr <= ps2_mouse_wptr + 1'd1;
						end


					8'h05: begin
							ps2_kbd_fifo[ps2_kbd_wptr] <= spi_dout; 
							ps2_kbd_wptr <= ps2_kbd_wptr + 1'd1;
						end
				
					8'h15: status[7:0] <= spi_dout;
				




					8'h19,


					8'h17: begin
							sd_buff_dout <= spi_dout;
							b_wr2 <= 1;
						end

					8'h18: b_data <= sd_buff_din;


					8'h1a: begin

							if(byte_cnt == 1) stick_idx <= spi_dout[2:0];
							else if(byte_cnt == 2) begin

								if(stick_idx == 0) joystick_analog_0[15:8] <= spi_dout;
									else if(stick_idx == 1) joystick_analog_1[15:8] <= spi_dout;
							end else if(byte_cnt == 3) begin

								if(stick_idx == 0) joystick_analog_0[7:0] <= spi_dout;
									else if(stick_idx == 1) joystick_analog_1[7:0] <= spi_dout;
							end
						end


					8'h1c: mount_strobe <= 1;


					8'h1d: if(byte_cnt<5) img_size[(byte_cnt-1)<<3 +:8] <= spi_dout;


					8'h1e: if(byte_cnt<5) status[(byte_cnt-1)<<3 +:8] <= spi_dout;

					default: ;
				endcase
			end
		end
	end
end




localparam PS2_FIFO_BITS = 3;

reg clk_ps2;
always @(negedge clk_sys) begin
	integer cnt;
	cnt <= cnt + 1'd1;
	if(cnt == PS2DIV) begin
		clk_ps2 <= ~clk_ps2;
		cnt <= 0;
	end
end


reg [7:0] ps2_kbd_fifo[1<<PS2_FIFO_BITS];
reg [PS2_FIFO_BITS-1:0] ps2_kbd_wptr;
reg [PS2_FIFO_BITS-1:0] ps2_kbd_rptr;


reg [3:0] ps2_kbd_tx_state;
reg [7:0] ps2_kbd_tx_byte;
reg ps2_kbd_parity;

assign ps2_kbd_clk = clk_ps2 || (ps2_kbd_tx_state == 0);



reg ps2_kbd_r_inc;
always@(posedge clk_sys) begin
	reg old_clk;
	old_clk <= clk_ps2;
	if(~old_clk & clk_ps2) begin
		ps2_kbd_r_inc <= 0;

		if(ps2_kbd_r_inc) ps2_kbd_rptr <= ps2_kbd_rptr + 1'd1;


		if(ps2_kbd_tx_state == 0) begin

			if(ps2_kbd_wptr != ps2_kbd_rptr) begin

				ps2_kbd_tx_byte <= ps2_kbd_fifo[ps2_kbd_rptr];
				ps2_kbd_r_inc <= 1;


				ps2_kbd_parity <= 1;


				ps2_kbd_tx_state <= 1;


				ps2_kbd_data <= 0;
			end
		end else begin


			if((ps2_kbd_tx_state >= 1)&&(ps2_kbd_tx_state < 9)) begin
				ps2_kbd_data <= ps2_kbd_tx_byte[0];
				ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1];
				if(ps2_kbd_tx_byte[0]) 
					ps2_kbd_parity <= !ps2_kbd_parity;
			end


			if(ps2_kbd_tx_state == 9) ps2_kbd_data <= ps2_kbd_parity;


			if(ps2_kbd_tx_state == 10) ps2_kbd_data <= 1;


			if(ps2_kbd_tx_state < 11) ps2_kbd_tx_state <= ps2_kbd_tx_state + 1'd1;
				else ps2_kbd_tx_state <= 0;
		end
	end
end


reg [7:0] ps2_mouse_fifo[1<<PS2_FIFO_BITS];
reg [PS2_FIFO_BITS-1:0] ps2_mouse_wptr;
reg [PS2_FIFO_BITS-1:0] ps2_mouse_rptr;


reg [3:0] ps2_mouse_tx_state;
reg [7:0] ps2_mouse_tx_byte;
reg ps2_mouse_parity;

assign ps2_mouse_clk = clk_ps2 || (ps2_mouse_tx_state == 0);



reg ps2_mouse_r_inc;
always@(posedge clk_sys) begin
	reg old_clk;
	old_clk <= clk_ps2;
	if(~old_clk & clk_ps2) begin
		ps2_mouse_r_inc <= 0;

		if(ps2_mouse_r_inc) ps2_mouse_rptr <= ps2_mouse_rptr + 1'd1;


		if(ps2_mouse_tx_state == 0) begin

			if(ps2_mouse_wptr != ps2_mouse_rptr) begin

				ps2_mouse_tx_byte <= ps2_mouse_fifo[ps2_mouse_rptr];
				ps2_mouse_r_inc <= 1;


				ps2_mouse_parity <= 1;


				ps2_mouse_tx_state <= 1;


				ps2_mouse_data <= 0;
			end
		end else begin


			if((ps2_mouse_tx_state >= 1)&&(ps2_mouse_tx_state < 9)) begin
				ps2_mouse_data <= ps2_mouse_tx_byte[0];
				ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1];
				if(ps2_mouse_tx_byte[0]) 
					ps2_mouse_parity <= !ps2_mouse_parity;
			end


			if(ps2_mouse_tx_state == 9) ps2_mouse_data <= ps2_mouse_parity;


			if(ps2_mouse_tx_state == 10) ps2_mouse_data <= 1;


			if(ps2_mouse_tx_state < 11) ps2_mouse_tx_state <= ps2_mouse_tx_state + 1'd1;
				else ps2_mouse_tx_state <= 0;
		end
	end
end




reg  [7:0] data_w;
reg [24:0] addr_w;
reg        rclk   = 0;
reg [15:0] start_addr;

localparam UIO_FILE_TX      = 8'h53;
localparam UIO_FILE_TX_DAT  = 8'h54;
localparam UIO_FILE_INDEX   = 8'h55;


always@(posedge SPI_SCK, posedge SPI_SS2) begin
	reg  [6:0] sbuf;
	reg  [7:0] cmd;
	reg  [4:0] cnt;
	reg [24:0] addr;

	if(SPI_SS2) cnt <= 0;
	else begin
		rclk <= 0;



		if(cnt != 15) sbuf <= { sbuf[5:0], SPI_DI};


		if(rclk) begin
			addr <= addr + 1'd1;
			if(addr == 25'h100003) addr <= start_addr;
		end


		if(cnt < 15) cnt <= cnt + 1'd1;
			else cnt <= 8;


      if(cnt == 7) cmd <= {sbuf, SPI_DI};


		if((cmd == UIO_FILE_TX) && (cnt == 15)) begin

			if(SPI_DI) begin
				case(ioctl_index) 
				         0: addr <= 'h200000;
				 'h01,'h41: addr <= 'h100000;
					default: addr <= 'h0FFFFF;
				endcase
				ioctl_download <= 1; 
			end else begin
				addr_w <= addr;
				ioctl_download <= 0;
			end
		end


		if((cmd == UIO_FILE_TX_DAT) && (cnt == 15)) begin
			if(addr == 25'h100000) begin
				start_addr[15:8] <= {sbuf, SPI_DI};
				data_w <= 8'hC3;
				addr_w <= 0;
			end else if(addr == 25'h100001) begin
				start_addr[7:0] <= {sbuf, SPI_DI};
				data_w <= {sbuf, SPI_DI};
				addr_w <= 1;
			end else if(addr == 25'h100002) begin
				data_w <= start_addr[15:8];
				addr_w <= 2;
			end else begin
				addr_w <= addr;
				data_w <= {sbuf, SPI_DI};
			end
			rclk <= 1;
		end


      if((cmd == UIO_FILE_INDEX) && (cnt == 15)) ioctl_index <= {sbuf, SPI_DI};
	end
end

reg  [24:0] erase_mask;
wire [24:0] next_erase = (ioctl_addr + 1'd1) & erase_mask;

always@(posedge clk_sys) begin
	reg        rclkD, rclkD2;
	reg        old_force = 0;
	reg  [5:0] erase_clk_div;
	reg [24:0] end_addr;
	reg        erase_trigger = 0;

	rclkD    <= rclk;
	rclkD2   <= rclkD;
	ioctl_wr <= 0;

	if(rclkD & ~rclkD2) begin
		ioctl_dout <= data_w;
		ioctl_addr <= addr_w;
		ioctl_wr   <= 1;
	end

	if(ioctl_download) begin
		old_force     <= 0;
		ioctl_erasing <= 0;
		erase_trigger <= (ioctl_index != 0);
	end else begin

		old_force <= ioctl_force_erase;


		if(erase_trigger) begin
			erase_trigger <= 0;
			erase_mask    <= 'hFFFF;
			end_addr      <= start_addr;
			erase_clk_div <= 1;
			ioctl_erasing <= 1;
		end else if((ioctl_force_erase & ~old_force)) begin
			erase_trigger <= 0;
			ioctl_addr    <= 'hFFFF;
			erase_mask    <= 'hFFFF;
			end_addr      <= 'hFFFE;
			erase_clk_div <= 1;
			ioctl_erasing <= 1;
		end else if(ioctl_erasing) begin
			erase_clk_div <= erase_clk_div + 1'd1;
			if(!erase_clk_div) begin
				if(next_erase == end_addr) ioctl_erasing <= 0;
				else begin
					ioctl_addr <= next_erase;
					ioctl_dout <= 0;
					if(next_erase > 2) ioctl_wr <= 1;
				end
			end
		end
	end
end

endmodule
module mist_io #(parameter STRLEN=0, parameter PS2DIV=20)
(


	input [(8*STRLEN)-1:0] conf_str,


	input             clk_sys,


	input             SPI_SCK,

	input             CONF_DATA0,
	input             SPI_SS2,
	output            SPI_DO,
	input             SPI_DI,

	output reg  [7:0] joystick_0,
	output reg  [7:0] joystick_1,
	output reg [15:0] joystick_analog_0,
	output reg [15:0] joystick_analog_1,
	output      [1:0] buttons,
	output      [1:0] switches,
	output            scandoubler_disable,
	output            ypbpr,

	output reg [31:0] status,


	input             sd_conf,
	input             sd_sdhc,
	output            img_mounted,
	output reg [31:0] img_size,


	input      [31:0] sd_lba,
	input             sd_rd,
	input             sd_wr,
	output reg        sd_ack,
	output reg        sd_ack_conf,


	output reg  [8:0] sd_buff_addr,
	output reg  [7:0] sd_buff_dout,
	input       [7:0] sd_buff_din,
	output reg        sd_buff_wr,


	output            ps2_kbd_clk,
	output reg        ps2_kbd_data,
	output            ps2_mouse_clk,
	output reg        ps2_mouse_data,
	input             ps2_caps_led,


	input             ioctl_force_erase,
	output reg        ioctl_download = 0,
	output reg        ioctl_erasing = 0,
	output reg  [7:0] ioctl_index,
	output reg        ioctl_wr = 0,
	output reg [24:0] ioctl_addr,
	output reg  [7:0] ioctl_dout
);


reg [7:0] b_data;
reg [6:0] sbuf;
reg [7:0] cmd;
reg [2:0] bit_cnt;
reg [9:0] byte_cnt;
reg [7:0] but_sw;
reg [2:0] stick_idx;

reg    mount_strobe = 0;
assign img_mounted  = mount_strobe;

assign buttons = but_sw[1:0];
assign switches = but_sw[3:2];
assign scandoubler_disable = but_sw[4];
assign ypbpr = but_sw[5];

wire [7:0] spi_dout = { sbuf, SPI_DI};


wire [7:0] core_type = 8'ha4;


wire [7:0] sd_cmd = { 4'h5, sd_conf, sd_sdhc, sd_wr, sd_rd };

reg spi_do;
assign SPI_DO = CONF_DATA0 ? 1'bZ : spi_do;

wire [7:0] kbd_led = { 2'b01, 4'b0000, ps2_caps_led, 1'b1};


always@(negedge SPI_SCK) begin
	if(!CONF_DATA0) begin


      if(byte_cnt == 0) begin
		  spi_do <= core_type[~bit_cnt];

		end else begin
			case(cmd)

				8'h14: begin

						if(byte_cnt < STRLEN + 1) spi_do <= conf_str[{STRLEN - byte_cnt,~bit_cnt}];
							else spi_do <= 0;
					end


				8'h16: begin
						if(byte_cnt == 1) spi_do <= sd_cmd[~bit_cnt];
						else if((byte_cnt >= 2) && (byte_cnt < 6)) spi_do <= sd_lba[{5-byte_cnt, ~bit_cnt}];
						else spi_do <= 0;
					end


				8'h18:
						spi_do <= b_data[~bit_cnt];


				8'h1f:
						spi_do <= kbd_led[~bit_cnt];

				default:
						spi_do <= 0;
			endcase
		end
   end
end

reg b_wr2,b_wr3;
always @(negedge clk_sys) begin
	b_wr3      <= b_wr2;
	sd_buff_wr <= b_wr3;
end


always@(posedge SPI_SCK or posedge CONF_DATA0) begin

	if(CONF_DATA0) begin
		b_wr2 <= 0;
	   bit_cnt <= 0;
	   byte_cnt <= 0;
		sd_ack <= 0;
		sd_ack_conf <= 0;
	end else begin
		b_wr2 <= 0;

		sbuf <= spi_dout[6:0];
		bit_cnt <= bit_cnt + 1'd1;
		if(bit_cnt == 5) begin
			if (byte_cnt == 0) sd_buff_addr <= 0;
			if((byte_cnt != 0) & (sd_buff_addr != 511)) sd_buff_addr <= sd_buff_addr + 1'b1;
			if((byte_cnt == 1) & ((cmd == 8'h17) | (cmd == 8'h19))) sd_buff_addr <= 0;
		end


      if(bit_cnt == 7) begin
			if(~&byte_cnt) byte_cnt <= byte_cnt + 8'd1;
			if(byte_cnt == 0) begin
				cmd <= spi_dout;

				if(spi_dout == 8'h19) begin
					sd_ack_conf  <= 1;
					sd_buff_addr <= 0;
				end
				if((spi_dout == 8'h17) || (spi_dout == 8'h18)) begin
					sd_ack       <= 1;
					sd_buff_addr <= 0;
				end
				if(spi_dout == 8'h18) b_data <= sd_buff_din;

				mount_strobe <= 0;

			end else begin
			
				case(cmd)

					8'h01: but_sw <= spi_dout; 
					8'h02: joystick_0 <= spi_dout;
					8'h03: joystick_1 <= spi_dout;


					8'h04: begin
							ps2_mouse_fifo[ps2_mouse_wptr] <= spi_dout; 
							ps2_mouse_wptr <= ps2_mouse_wptr + 1'd1;
						end


					8'h05: begin
							ps2_kbd_fifo[ps2_kbd_wptr] <= spi_dout; 
							ps2_kbd_wptr <= ps2_kbd_wptr + 1'd1;
						end
				
					8'h15: status[7:0] <= spi_dout;
				




					8'h19,


					8'h17: begin
							sd_buff_dout <= spi_dout;
							b_wr2 <= 1;
						end

					8'h18: b_data <= sd_buff_din;


					8'h1a: begin

							if(byte_cnt == 1) stick_idx <= spi_dout[2:0];
							else if(byte_cnt == 2) begin

								if(stick_idx == 0) joystick_analog_0[15:8] <= spi_dout;
									else if(stick_idx == 1) joystick_analog_1[15:8] <= spi_dout;
							end else if(byte_cnt == 3) begin

								if(stick_idx == 0) joystick_analog_0[7:0] <= spi_dout;
									else if(stick_idx == 1) joystick_analog_1[7:0] <= spi_dout;
							end
						end


					8'h1c: mount_strobe <= 1;


					8'h1d: if(byte_cnt<5) img_size[(byte_cnt-1)<<3 +:8] <= spi_dout;


					8'h1e: if(byte_cnt<5) status[(byte_cnt-1)<<3 +:8] <= spi_dout;

					default: ;
				endcase
			end
		end
	end
end




localparam PS2_FIFO_BITS = 3;

reg clk_ps2;
always @(negedge clk_sys) begin
	integer cnt;
	cnt <= cnt + 1'd1;
	if(cnt == PS2DIV) begin
		clk_ps2 <= ~clk_ps2;
		cnt <= 0;
	end
end


reg [7:0] ps2_kbd_fifo[1<<PS2_FIFO_BITS];
reg [PS2_FIFO_BITS-1:0] ps2_kbd_wptr;
reg [PS2_FIFO_BITS-1:0] ps2_kbd_rptr;


reg [3:0] ps2_kbd_tx_state;
reg [7:0] ps2_kbd_tx_byte;
reg ps2_kbd_parity;

assign ps2_kbd_clk = clk_ps2 || (ps2_kbd_tx_state == 0);



reg ps2_kbd_r_inc;
always@(posedge clk_sys) begin
	reg old_clk;
	old_clk <= clk_ps2;
	if(~old_clk & clk_ps2) begin
		ps2_kbd_r_inc <= 0;

		if(ps2_kbd_r_inc) ps2_kbd_rptr <= ps2_kbd_rptr + 1'd1;


		if(ps2_kbd_tx_state == 0) begin

			if(ps2_kbd_wptr != ps2_kbd_rptr) begin

				ps2_kbd_tx_byte <= ps2_kbd_fifo[ps2_kbd_rptr];
				ps2_kbd_r_inc <= 1;


				ps2_kbd_parity <= 1;


				ps2_kbd_tx_state <= 1;


				ps2_kbd_data <= 0;
			end
		end else begin


			if((ps2_kbd_tx_state >= 1)&&(ps2_kbd_tx_state < 9)) begin
				ps2_kbd_data <= ps2_kbd_tx_byte[0];
				ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1];
				if(ps2_kbd_tx_byte[0]) 
					ps2_kbd_parity <= !ps2_kbd_parity;
			end


			if(ps2_kbd_tx_state == 9) ps2_kbd_data <= ps2_kbd_parity;


			if(ps2_kbd_tx_state == 10) ps2_kbd_data <= 1;


			if(ps2_kbd_tx_state < 11) ps2_kbd_tx_state <= ps2_kbd_tx_state + 1'd1;
				else ps2_kbd_tx_state <= 0;
		end
	end
end


reg [7:0] ps2_mouse_fifo[1<<PS2_FIFO_BITS];
reg [PS2_FIFO_BITS-1:0] ps2_mouse_wptr;
reg [PS2_FIFO_BITS-1:0] ps2_mouse_rptr;


reg [3:0] ps2_mouse_tx_state;
reg [7:0] ps2_mouse_tx_byte;
reg ps2_mouse_parity;

assign ps2_mouse_clk = clk_ps2 || (ps2_mouse_tx_state == 0);



reg ps2_mouse_r_inc;
always@(posedge clk_sys) begin
	reg old_clk;
	old_clk <= clk_ps2;
	if(~old_clk & clk_ps2) begin
		ps2_mouse_r_inc <= 0;

		if(ps2_mouse_r_inc) ps2_mouse_rptr <= ps2_mouse_rptr + 1'd1;


		if(ps2_mouse_tx_state == 0) begin

			if(ps2_mouse_wptr != ps2_mouse_rptr) begin

				ps2_mouse_tx_byte <= ps2_mouse_fifo[ps2_mouse_rptr];
				ps2_mouse_r_inc <= 1;


				ps2_mouse_parity <= 1;


				ps2_mouse_tx_state <= 1;


				ps2_mouse_data <= 0;
			end
		end else begin


			if((ps2_mouse_tx_state >= 1)&&(ps2_mouse_tx_state < 9)) begin
				ps2_mouse_data <= ps2_mouse_tx_byte[0];
				ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1];
				if(ps2_mouse_tx_byte[0]) 
					ps2_mouse_parity <= !ps2_mouse_parity;
			end


			if(ps2_mouse_tx_state == 9) ps2_mouse_data <= ps2_mouse_parity;


			if(ps2_mouse_tx_state == 10) ps2_mouse_data <= 1;


			if(ps2_mouse_tx_state < 11) ps2_mouse_tx_state <= ps2_mouse_tx_state + 1'd1;
				else ps2_mouse_tx_state <= 0;
		end
	end
end




reg  [7:0] data_w;
reg [24:0] addr_w;
reg        rclk   = 0;
reg [15:0] start_addr;

localparam UIO_FILE_TX      = 8'h53;
localparam UIO_FILE_TX_DAT  = 8'h54;
localparam UIO_FILE_INDEX   = 8'h55;


always@(posedge SPI_SCK, posedge SPI_SS2) begin
	reg  [6:0] sbuf;
	reg  [7:0] cmd;
	reg  [4:0] cnt;
	reg [24:0] addr;

	if(SPI_SS2) cnt <= 0;
	else begin
		rclk <= 0;



		if(cnt != 15) sbuf <= { sbuf[5:0], SPI_DI};


		if(rclk) begin
			addr <= addr + 1'd1;
			if(addr == 25'h100003) addr <= start_addr;
		end


		if(cnt < 15) cnt <= cnt + 1'd1;
			else cnt <= 8;


      if(cnt == 7) cmd <= {sbuf, SPI_DI};


		if((cmd == UIO_FILE_TX) && (cnt == 15)) begin

			if(SPI_DI) begin
				case(ioctl_index) 
				         0: addr <= 'h200000;
				 'h01,'h41: addr <= 'h100000;
					default: addr <= 'h0FFFFF;
				endcase
				ioctl_download <= 1; 
			end else begin
				addr_w <= addr;
				ioctl_download <= 0;
			end
		end


		if((cmd == UIO_FILE_TX_DAT) && (cnt == 15)) begin
			if(addr == 25'h100000) begin
				start_addr[15:8] <= {sbuf, SPI_DI};
				data_w <= 8'hC3;
				addr_w <= 0;
			end else if(addr == 25'h100001) begin
				start_addr[7:0] <= {sbuf, SPI_DI};
				data_w <= {sbuf, SPI_DI};
				addr_w <= 1;
			end else if(addr == 25'h100002) begin
				data_w <= start_addr[15:8];
				addr_w <= 2;
			end else begin
				addr_w <= addr;
				data_w <= {sbuf, SPI_DI};
			end
			rclk <= 1;
		end


      if((cmd == UIO_FILE_INDEX) && (cnt == 15)) ioctl_index <= {sbuf, SPI_DI};
	end
end

reg  [24:0] erase_mask;
wire [24:0] next_erase = (ioctl_addr + 1'd1) & erase_mask;

always@(posedge clk_sys) begin
	reg        rclkD, rclkD2;
	reg        old_force = 0;
	reg  [5:0] erase_clk_div;
	reg [24:0] end_addr;
	reg        erase_trigger = 0;

	rclkD    <= rclk;
	rclkD2   <= rclkD;
	ioctl_wr <= 0;

	if(rclkD & ~rclkD2) begin
		ioctl_dout <= data_w;
		ioctl_addr <= addr_w;
		ioctl_wr   <= 1;
	end

	if(ioctl_download) begin
		old_force     <= 0;
		ioctl_erasing <= 0;
		erase_trigger <= (ioctl_index != 0);
	end else begin

		old_force <= ioctl_force_erase;


		if(erase_trigger) begin
			erase_trigger <= 0;
			erase_mask    <= 'hFFFF;
			end_addr      <= start_addr;
			erase_clk_div <= 1;
			ioctl_erasing <= 1;
		end else if((ioctl_force_erase & ~old_force)) begin
			erase_trigger <= 0;
			ioctl_addr    <= 'hFFFF;
			erase_mask    <= 'hFFFF;
			end_addr      <= 'hFFFE;
			erase_clk_div <= 1;
			ioctl_erasing <= 1;
		end else if(ioctl_erasing) begin
			erase_clk_div <= erase_clk_div + 1'd1;
			if(!erase_clk_div) begin
				if(next_erase == end_addr) ioctl_erasing <= 0;
				else begin
					ioctl_addr <= next_erase;
					ioctl_dout <= 0;
					if(next_erase > 2) ioctl_wr <= 1;
				end
			end
		end
	end
end

endmodule