`timescale 1ns / 1ps // Interpret commands from USB interface chip and drive internal bus // /* The read and write commands use 20 bits for the address field, although only 11 are necessary Improve the efficiency by 1 shortening the address, 2 adding burst modes, 3 figure out why the clock has to be so slow to work. packet format: Write: Byte: | Bit7 6 5 4 3 2 1 0 0 1 1 a19............a15 1 1 0 a14............a9 2 1 0 a8.............a2 3 1 0 a1 a0 d15......d9 4 1 0 d8.............d6 5 1 0 d5.............d0 Read: Byte: | Bit7 6 5 4 3 2 1 0 0 1 1 a19............a15 1 0 1 a14............a9 2 1 0 a8.............a2 3 1 0 a1 a0 x x x x 3 d15..................d8 4 d7...................d0 */ module usb_interface(usb_data, usb_txe, usb_rxf, usb_rd, usb_wr, ib_data, ib_addr, ib_read, ib_write, ib_req, ib_gnt, clock, reset); inout [7:0] usb_data; input usb_txe; input usb_rxf; output usb_rd; output usb_wr; inout [15:0] ib_data; output [10:0] ib_addr; output ib_read; output ib_write; output ib_req; input ib_gnt; input clock; input reset; reg [7:0] state; reg [19:0] addr; reg [15:0] data; reg usb_rd; reg usb_wr; reg operation_rd; reg ib_req; reg ib_read; reg ib_write; reg out_msb; reg [4:0] wait_timer; assign debug = {ib_addr[3:0],ib_data,out_msb,ib_req,ib_read,ib_write,state}; assign ib_addr = (ib_gnt) ? addr[11:0] : 11'bz; assign ib_data = (ib_gnt & !operation_rd) ? data : 16'bz; assign usb_data = usb_wr ? (out_msb ? data[15:8] : data[7:0]) : 8'bz ; always @ (posedge clock or posedge reset) if (reset) begin state <= 0; data <= 0; addr <= 0; usb_rd <= 0; usb_wr <= 0; ib_write <= 0; ib_read <= 0; ib_req <= 0; out_msb <= 0; usb_wr <= 0; operation_rd <= 0; wait_timer <= 0; end else begin case(state) //read for byte 0 'd0: begin usb_rd <= 0; usb_wr <= 0; ib_write <= 0; ib_read <= 0; ib_req <= 0; state <= state + usb_rxf; end 'd1: begin usb_rd <= 1; state <= state + 1; end 'd2: state <= state + 1; 'd3: begin usb_rd <= 0; addr[19:14] <= usb_data[5:0]; if(usb_data[7:6]==3) state <= state + 1; else state <= 0; end //read byte 1 'd4: state <= state + usb_rxf; 'd5: begin usb_rd <= 1; state <= state + 1; end 'd6: state <= state + 1; 'd7: case(usb_data[7:6]) 0: state <= 0; 1: begin usb_rd <= 0; state <= state + 1; addr[13:8] <= usb_data[5:0]; operation_rd <= 1; end 2: begin usb_rd <= 0; state <= state + 1; addr[13:8] <= usb_data[5:0]; operation_rd <= 0; end 3: state <= 'd3; endcase //read byte 2 'd8: state <= state + usb_rxf; 'd9: begin usb_rd <= 1; state <= state + 1; end 'd10: state <= state + 1; 'd11: if(usb_data[7:6] == 2) begin usb_rd <= 0; state <= state + 1; addr[7:2] <= usb_data[5:0]; end else if(usb_data[7:6] == 3)state <= 'd3; else state <= 0; //read byte 3 'd12: state <= state + usb_rxf; 'd13: begin usb_rd <= 1; state <= state + 1; end 'd14: state <= state + 1; 'd15: if(usb_data[7:6] == 2) begin usb_rd <= 0; state <= state + 1; addr[1:0] <= usb_data[5:4]; data[15:12] <= usb_data[3:0]; end else if(usb_data[7:6] == 3) state <= 'd3; else state <= 0; 'd16: if (operation_rd) state <= 'd32; else state <= state + 1; //read byte 4 'd17: state <= state + usb_rxf; 'd18: begin usb_rd <= 1; state <= state + 1; end 'd19: state <= state + 1; 'd20: if(usb_data[7:6]==2) begin usb_rd <= 0; state <= state + 1; data[11:6] <= usb_data[5:0]; end else if(usb_data[7:6] == 3) state <= 'd3; else state <= 0; //read byte 5 'd21: state <= state + usb_rxf; 'd22: begin usb_rd <= 1; state <= state + 1; end 'd23: state <= state + 1; 'd24: if(usb_data[7:6] == 2) begin usb_rd <= 0; state <= state + 1; data[5:0] <= usb_data[5:0]; end else if(usb_data[7:6] == 3) state <= 'd3; else state <= 0; //write internal data 'd25: begin ib_req <= 1; state <= state + 1; end 'd26: state <= state + ib_gnt; 'd27: begin ib_write <= 1; state <= state + 1; end 'd28: begin ib_write <= 0; state <= 0; end //read internal data 'd32: begin ib_req <= 1; state <= state + 1; end 'd33: state <= state + ib_gnt; 'd34: begin ib_read <= 1; state <= state + 1; end 'd35: state <= state + 1; 'd36: begin ib_read <= 0; data <= ib_data; state <= state + 1; end 'd37: begin ib_req <= 0; wait_timer <= 4; state <= state + 1; end 'd38: begin wait_timer <= wait_timer -1; state <= state + (wait_timer == 0); end //write byte 3 'd39: state <= state + usb_txe; 'd40: begin usb_wr <= 1; out_msb <= 1; state <= state + 1; end 'd41: state <= state + 1; 'd42: begin usb_wr <= 0; state <= state + 1; end //write byte 4 'd43: state <= state + usb_txe; 'd44: begin usb_wr <= 1; out_msb <= 0; state <= state + 1; end 'd45: state <= state + 1; 'd46: begin usb_wr <= 0; state <= 0; end default: state <= 0; endcase end endmodule