diff --git a/boards/TinyFPGA_BX/Makefile b/boards/TinyFPGA_BX/Makefile index 6ea0de9..eb006a1 100644 --- a/boards/TinyFPGA_BX/Makefile +++ b/boards/TinyFPGA_BX/Makefile @@ -22,12 +22,22 @@ PKG = cm81 all: $(PROJ).rpt fw.bin +%.json: %.v ../../common/*.v + yosys -q -p 'synth_ice40 -top $(PROJ) -json $@' $^ %.blif: %.v ../../common/*.v - yosys -p 'synth_ice40 -top $(PROJ) -blif $@' $^ + yosys -q -p 'synth_ice40 -top $(PROJ) -blif $@' $^ -%.asc: $(PIN_DEF) %.blif +NO-%.asc: $(PIN_DEF) %.blif arachne-pnr -d 8k -P $(PKG) -o $@ -p $^ +%.asc: $(PIN_DEF) %.json + nextpnr-ice40 \ + --$(DEVICE) \ + --package $(PKG) \ + --asc $@ \ + --pcf $(PIN_DEF) \ + --json $(basename $@).json \ + %.bin: %.asc icepack $< $@ diff --git a/boards/TinyFPGA_BX/bootloader.v b/boards/TinyFPGA_BX/bootloader.v index bf7a601..e35fcbd 100644 --- a/boards/TinyFPGA_BX/bootloader.v +++ b/boards/TinyFPGA_BX/bootloader.v @@ -20,6 +20,8 @@ module bootloader ( //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// wire clk_48mhz; + wire lock; + wire reset = !lock; SB_PLL40_CORE #( .DIVR(4'b0000), @@ -43,13 +45,18 @@ module bootloader ( .RESETB(1'b1), .BYPASS(1'b0), .LATCHINPUTVALUE(), - .LOCK(), + .LOCK(lock), .SDI(), .SDO(), .SCLK() ); + reg clk_24mhz; + reg clk_12mhz; + always @(posedge clk_48mhz) clk_24mhz = !clk_24mhz; + always @(posedge clk_24mhz) clk_12mhz = !clk_12mhz; + wire clk = clk_12mhz; // quarter speed clock //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// @@ -74,7 +81,6 @@ module bootloader ( //////// //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// - wire reset; wire usb_p_tx; wire usb_n_tx; wire usb_p_rx; @@ -85,6 +91,7 @@ module bootloader ( tinyfpga_bootloader tinyfpga_bootloader_inst ( .clk_48mhz(clk_48mhz), + .clk(clk), .reset(reset), .usb_p_tx(usb_p_tx), .usb_n_tx(usb_n_tx), @@ -100,44 +107,39 @@ module bootloader ( ); assign pin_pu = 1'b1; + + wire usb_p_rx_io; + wire usb_n_rx_io; assign usb_p_rx = usb_tx_en ? 1'b1 : usb_p_rx_io; assign usb_n_rx = usb_tx_en ? 1'b0 : usb_n_rx_io; - SB_IO #( - .PIN_TYPE(6'b101001), - .PULLUP(1'b0), - .NEG_TRIGGER(1'b0), - .IO_STANDARD("SB_LVCMOS") - ) io_dp_I ( - .PACKAGE_PIN(pin_usbp), - .LATCH_INPUT_VALUE(1'b0), - .CLOCK_ENABLE(1'b1), - .INPUT_CLK(1'b0), - .OUTPUT_CLK(1'b0), - .OUTPUT_ENABLE(usb_tx_en), - .D_OUT_0(usb_p_tx), - .D_OUT_1(1'b0), - .D_IN_0(usb_p_rx_io), - .D_IN_1() + tristate usbn_buffer( + .pin(pin_usbn), + .enable(usb_tx_en), + .data_in(usb_n_rx_io), + .data_out(usb_n_tx) ); - SB_IO #( - .PIN_TYPE(6'b101001), - .PULLUP(1'b0), - .NEG_TRIGGER(1'b0), - .IO_STANDARD("SB_LVCMOS") - ) io_dn_I ( - .PACKAGE_PIN(pin_usbn), - .LATCH_INPUT_VALUE(1'b0), - .CLOCK_ENABLE(1'b1), - .INPUT_CLK(1'b0), - .OUTPUT_CLK(1'b0), - .OUTPUT_ENABLE(usb_tx_en), - .D_OUT_0(usb_n_tx), - .D_OUT_1(1'b0), - .D_IN_0(usb_n_rx_io), - .D_IN_1() + tristate usbp_buffer( + .pin(pin_usbp), + .enable(usb_tx_en), + .data_in(usb_p_rx_io), + .data_out(usb_p_tx) ); +endmodule - assign reset = 1'b0; +module tristate( + inout pin, + input enable, + input data_out, + output data_in +); + SB_IO #( + .PIN_TYPE(6'b1010_01) // tristatable output + ) buffer( + .PACKAGE_PIN(pin), + .OUTPUT_ENABLE(enable), + .D_IN_0(data_in), + .D_OUT_0(data_out) + ); endmodule diff --git a/boards/TinyFPGA_BX/pins.pcf b/boards/TinyFPGA_BX/pins.pcf index 2a024b7..6fa7e18 100644 --- a/boards/TinyFPGA_BX/pins.pcf +++ b/boards/TinyFPGA_BX/pins.pcf @@ -3,46 +3,46 @@ # Package: CM81 ############################################################################### -#set_io pin_1 A2 -#set_io pin_2 A1 -#set_io pin_3 B1 -#set_io pin_4 C2 -#set_io pin_5 C1 -#set_io pin_6 D2 -#set_io pin_7 D1 -#set_io pin_8 E2 -#set_io pin_9 E1 -#set_io pin_10 G2 -#set_io pin_11 H1 -#set_io pin_12 J1 -#set_io pin_13 H2 -#set_io pin_14 H9 -#set_io pin_15 D9 -#set_io pin_16 D8 -#set_io pin_17 C9 -#set_io pin_18 A9 -#set_io pin_19 B8 -#set_io pin_20 A8 -#set_io pin_21 B7 -#set_io pin_22 A7 -#set_io pin_23 B6 -#set_io pin_24 A6 -#set_io pin_25 G1 -#set_io pin_26 J3 -#set_io pin_27 J4 -#set_io pin_28 H4 -set_io pin_29_miso H7 -set_io pin_30_cs F7 -set_io pin_31_mosi G6 -set_io pin_32_sck G7 -#set_io pin_33 J8 -#set_io pin_34 G9 -#set_io pin_35 J9 -#set_io pin_36 E8 -#set_io pin_37 J2 -set_io pin_led B3 -set_io pin_usbp B4 -set_io pin_usbn A4 -set_io pin_pu A3 -set_io pin_clk B2 +set_io -nowarn pin_1 A2 +set_io -nowarn pin_2 A1 +set_io -nowarn pin_3 B1 +set_io -nowarn pin_4 C2 +set_io -nowarn pin_5 C1 +set_io -nowarn pin_6 D2 +set_io -nowarn pin_7 D1 +set_io -nowarn pin_8 E2 +set_io -nowarn pin_9 E1 +set_io -nowarn pin_10 G2 +set_io -nowarn pin_11 H1 +set_io -nowarn pin_12 J1 +set_io -nowarn pin_13 H2 +set_io -nowarn pin_14 H9 +set_io -nowarn pin_15 D9 +set_io -nowarn pin_16 D8 +set_io -nowarn pin_17 C9 +set_io -nowarn pin_18 A9 +set_io -nowarn pin_19 B8 +set_io -nowarn pin_20 A8 +set_io -nowarn pin_21 B7 +set_io -nowarn pin_22 A7 +set_io -nowarn pin_23 B6 +set_io -nowarn pin_24 A6 +set_io -nowarn pin_25 G1 +set_io -nowarn pin_26 J3 +set_io -nowarn pin_27 J4 +set_io -nowarn pin_28 H4 +set_io -nowarn pin_29_miso H7 +set_io -nowarn pin_30_cs F7 +set_io -nowarn pin_31_mosi G6 +set_io -nowarn pin_32_sck G7 +set_io -nowarn pin_33 J8 +set_io -nowarn pin_34 G9 +set_io -nowarn pin_35 J9 +set_io -nowarn pin_36 E8 +set_io -nowarn pin_37 J2 +set_io -nowarn pin_led B3 +set_io -nowarn pin_usbp B4 +set_io -nowarn pin_usbn A4 +set_io -nowarn pin_pu A3 +set_io -nowarn pin_clk B2 diff --git a/boards/Tomu_Fomu/Makefile b/boards/Tomu_Fomu/Makefile new file mode 100644 index 0000000..a3d76a6 --- /dev/null +++ b/boards/Tomu_Fomu/Makefile @@ -0,0 +1,69 @@ +# Makefile borrowed from https://github.com/cliffordwolf/icestorm/blob/master/examples/icestick/Makefile +# +# The following license is from the icestorm project and specifically applies to this file only: +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +PROJ = bootloader + +PIN_DEF = pins.pcf +DEVICE = up5k +PKG = uwg30 +SEED ?= 12345678 + +#all: $(PROJ).rpt multiboot.bin +all: multiboot.bin + +%.json: %.v ../../common/*.v + yosys -q -p 'synth_ice40 -top $(PROJ) -json $@' $^ +%.blif: %.v ../../common/*.v + yosys -q -p 'synth_ice40 -top $(PROJ) -blif $@' $^ + +%.asc: $(PIN_DEF) %.json + nextpnr-ice40 \ + --seed $(SEED) \ + --up5k \ + --package $(PKG) \ + --json $(basename $@).json \ + --pcf $(PIN_DEF) \ + --asc $@ \ + +no-%.asc: $(PIN_DEF) %.blif + arachne-pnr -d 5k -P $(PKG) -o $@ -p $^ + +%.bin: %.asc + icepack $< $@ + +multiboot.bin: bootloader.bin + cp bootloader.bin bootloader_0.bin + cp bootloader.bin bootloader_1.bin + icemulti -v -o multiboot.bin -a16 -p0 bootloader_0.bin bootloader_1.bin + +%.rpt: %.asc + icetime -d $(DEVICE) -mtr $@ $< + +%_syn.v: %.blif + yosys -p 'read_blif -wideports $^; write_verilog $@' + +prog: multiboot.bin + iceprog $< + +sudo-prog: multiboot.bin + @echo 'Executing prog as root!!!' + sudo iceprog $< + +clean: + rm -f $(PROJ).blif $(PROJ).asc $(PROJ).rpt $(PROJ).bin multiboot.bin + +.SECONDARY: +.PHONY: all prog clean diff --git a/boards/Tomu_Fomu/boardmeta.json b/boards/Tomu_Fomu/boardmeta.json new file mode 100644 index 0000000..dd68dfd --- /dev/null +++ b/boards/Tomu_Fomu/boardmeta.json @@ -0,0 +1,6 @@ +{"boardmeta":{ + "name": "Tomu Fomu Hacker", + "fpga": "ice40up5k-uwg30", + "hver": "0.0", + "serial": 1234 +}} diff --git a/boards/Tomu_Fomu/bootloader.v b/boards/Tomu_Fomu/bootloader.v new file mode 100644 index 0000000..fe132f5 --- /dev/null +++ b/boards/Tomu_Fomu/bootloader.v @@ -0,0 +1,146 @@ +module bootloader ( + input pin_clk, + + inout pin_usbp, + inout pin_usbn, + output pin_pu, + + output pin_led_r, + output pin_led_g, + output pin_led_b, + + input flash_miso, + output flash_cs, + output flash_mosi, + output flash_sck +); + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////// + //////// generate 48 mhz clock + //////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + wire clk_48mhz; + wire locked; + +`define USE_HFOSC_NO +`ifdef USE_HFOSC + SB_HFOSC u_hfosc ( + .CLKHFPU(1'b1), + .CLKHFEN(1'b1), + .CLKHF(clk_48mhz) + ); + assign locked = 1; +`else + // the Tomu hacker verison has an external 48 MHz oscillator + // so there is no need for a PLL. + assign locked = 1; + assign clk_48mhz = pin_clk; +`endif + + reg clk_24mhz; + reg clk_12mhz; + wire clk = clk_12mhz; + always @(posedge clk_48mhz) clk_24mhz = !clk_24mhz; + always @(posedge clk_24mhz) clk_12mhz = !clk_12mhz; + + + assign pin_led_g = 1; + +/* + reg [23:0] counter; + always @(posedge clk_48mhz) + if (counter == 24'h7FFFFF) + pin_led_r <= 1; + else begin + counter <= counter + 1; + pin_led_r <= 0; + end +*/ + assign pin_led_r = 1; + + + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////// + //////// interface with iCE40 warmboot/multiboot capability + //////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + wire boot; + + SB_WARMBOOT warmboot_inst ( + .S1(1'b0), + .S0(1'b1), + .BOOT(boot) + ); + + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////// + //////// instantiate tinyfpga bootloader + //////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + wire reset = !locked; + wire usb_p_tx; + wire usb_n_tx; + wire usb_p_rx; + wire usb_n_rx; + wire usb_tx_en; + + tinyfpga_bootloader tinyfpga_bootloader_inst ( + .clk_48mhz(clk_48mhz), + .clk(clk), + .reset(reset), + .usb_p_tx(usb_p_tx), + .usb_n_tx(usb_n_tx), + .usb_p_rx(usb_p_rx), + .usb_n_rx(usb_n_rx), + .usb_tx_en(usb_tx_en), + .led(pin_led_b), + .spi_miso(flash_miso), + .spi_cs(flash_cs), + .spi_mosi(flash_mosi), + .spi_sck(flash_sck), + .boot(boot) + ); + + assign pin_pu = 1'b1; + + wire usb_p_rx_io; + wire usb_n_rx_io; + assign usb_p_rx = usb_tx_en ? 1'b1 : usb_p_rx_io; + assign usb_n_rx = usb_tx_en ? 1'b0 : usb_n_rx_io; + + tristate usbn_buffer( + .pin(pin_usbn), + .enable(usb_tx_en), + .data_in(usb_n_rx_io), + .data_out(usb_n_tx) + ); + + tristate usbp_buffer( + .pin(pin_usbp), + .enable(usb_tx_en), + .data_in(usb_p_rx_io), + .data_out(usb_p_tx) + ); +endmodule + +module tristate( + inout pin, + input enable, + input data_out, + output data_in +); + SB_IO #( + .PIN_TYPE(6'b1010_01) // tristatable output + ) buffer( + .PACKAGE_PIN(pin), + .OUTPUT_ENABLE(enable), + .D_IN_0(data_in), + .D_OUT_0(data_out) + ); +endmodule diff --git a/boards/Tomu_Fomu/bootmeta.json b/boards/Tomu_Fomu/bootmeta.json new file mode 100644 index 0000000..28e3256 --- /dev/null +++ b/boards/Tomu_Fomu/bootmeta.json @@ -0,0 +1,9 @@ +{"bootmeta" : { +"bootloader": "TinyFPGA USB Bootloader", +"bver": "2.0.0", +"update": "https://tomu.im/", +"addrmap": { +"bootloader": "0x000a0-0x20000", +"userimage": "0x20000-0x40000", +"userdata": "0x40000-0x100000" +}}} diff --git a/boards/Tomu_Fomu/pins.pcf b/boards/Tomu_Fomu/pins.pcf new file mode 100644 index 0000000..248f768 --- /dev/null +++ b/boards/Tomu_Fomu/pins.pcf @@ -0,0 +1,17 @@ +# +# Pinmap for the Fomu hacker version 0.0 +# +set_io -nowarn pin_clk F5 # IOB_3b +set_io -nowarn BTN_N F4 # IOB_11b / pin1 +set_io -nowarn pin_led_r C5 # Red +set_io -nowarn pin_led_g B5 # Green +set_io -nowarn pin_led_b A5 # Blue + +set_io -nowarn flash_sck D1 # IOB_35a +set_io -nowarn flash_cs C1 # IOB_35b +set_io -nowarn flash_mosi F1 # IOB_32a +set_io -nowarn flash_miso E1 # IOB_33b + +set_io -nowarn pin_usbp A4 # IOT_47a +set_io -nowarn pin_usbn A2 # IOT_37a +set_io -nowarn pin_pu D5 # IOT_2a ? diff --git a/common/strobe.v b/common/strobe.v new file mode 100644 index 0000000..2791ad9 --- /dev/null +++ b/common/strobe.v @@ -0,0 +1,53 @@ +module strobe( + input clk_in, + input clk_out, + input strobe_in, + output strobe_out, + input [WIDTH-1:0] data_in, + output [WIDTH-1:0] data_out +); + parameter WIDTH = 1; + parameter DELAY = 2; // 2 for metastability, larger for testing + +`define CLOCK_CROSS +`ifdef CLOCK_CROSS + reg flag; + reg prev_strobe; + reg [DELAY:0] sync; + reg [WIDTH-1:0] data; + + // flip the flag and clock in the data when strobe is high + always @(posedge clk_in) begin + //if ((strobe_in && !prev_strobe) + //|| (!strobe_in && prev_strobe)) + flag <= flag ^ strobe_in; + + if (strobe_in) + data <= data_in; + + prev_strobe <= strobe_in; + end + + // shift through a chain of flipflop to ensure stability + always @(posedge clk_out) + sync <= { sync[DELAY-1:0], flag }; + + assign strobe_out = sync[DELAY] ^ sync[DELAY-1]; + assign data_out = data; +`else + assign strobe_out = strobe_in; + assign data_out = data_in; +`endif +endmodule + + +module dflip( + input clk, + input in, + output out +); + reg [2:0] d; + always @(posedge clk) + d <= { d[1:0], in }; + assign out = d[2]; +endmodule diff --git a/common/tinyfpga_bootloader.v b/common/tinyfpga_bootloader.v index 578ca22..7649bfa 100644 --- a/common/tinyfpga_bootloader.v +++ b/common/tinyfpga_bootloader.v @@ -1,5 +1,6 @@ module tinyfpga_bootloader ( input clk_48mhz, + input clk, input reset, // USB lines. Split into input vs. output and oe control signal to maintain @@ -26,6 +27,7 @@ module tinyfpga_bootloader ( // function. output boot ); + //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////// @@ -38,7 +40,7 @@ module tinyfpga_bootloader ( reg [5:0] ns_cnt = 0; wire ns_rst = (ns_cnt == 48); - always @(posedge clk_48mhz) begin + always @(posedge clk) begin if (ns_rst) begin ns_cnt <= 0; end else begin @@ -48,7 +50,7 @@ module tinyfpga_bootloader ( reg [9:0] us_cnt = 0; wire us_rst = (us_cnt == 1000); - always @(posedge clk_48mhz) begin + always @(posedge clk) begin if (us_rst) begin us_cnt <= 0; end else if (ns_rst) begin @@ -57,7 +59,7 @@ module tinyfpga_bootloader ( end reg count_down = 0; - always @(posedge clk_48mhz) begin + always @(posedge clk) begin if (us_rst) begin if (count_down) begin if (led_pwm == 0) begin @@ -74,11 +76,10 @@ module tinyfpga_bootloader ( end end end - always @(posedge clk_48mhz) pwm_cnt <= pwm_cnt + 1'b1; + always @(posedge clk) pwm_cnt <= pwm_cnt + 1'b1; assign led = led_pwm > pwm_cnt; - //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////// @@ -136,7 +137,7 @@ module tinyfpga_bootloader ( assign boot = host_presence_timeout || boot_to_user_design; usb_serial_ctrl_ep ctrl_ep_inst ( - .clk(clk_48mhz), + .clk(clk), .reset(reset), .dev_addr(dev_addr), @@ -163,7 +164,7 @@ module tinyfpga_bootloader ( ); usb_spi_bridge_ep usb_spi_bridge_ep_inst ( - .clk(clk_48mhz), + .clk(clk), .reset(reset), // out endpoint interface @@ -204,7 +205,8 @@ module tinyfpga_bootloader ( .NUM_OUT_EPS(5'd2), .NUM_IN_EPS(5'd3) ) usb_fs_pe_inst ( - .clk(clk_48mhz), + .clk_48mhz(clk_48mhz), + .clk(clk), .reset(reset), .usb_p_tx(usb_p_tx), @@ -246,7 +248,7 @@ module tinyfpga_bootloader ( // host presence detection //////////////////////////////////////////////////////////////////////////////// - always @(posedge clk_48mhz) begin + always @(posedge clk) begin if (sof_valid) begin host_presence_timer <= 0; host_presence_timeout <= 0; @@ -254,8 +256,8 @@ module tinyfpga_bootloader ( host_presence_timer <= host_presence_timer + 1; end - if (host_presence_timer > 48000000) begin + if (host_presence_timer > 196000000) begin host_presence_timeout <= 1; end end -endmodule \ No newline at end of file +endmodule diff --git a/common/usb_fs_in_pe.v b/common/usb_fs_in_pe.v index 16b9faf..d69176e 100644 --- a/common/usb_fs_in_pe.v +++ b/common/usb_fs_in_pe.v @@ -41,12 +41,12 @@ module usb_fs_in_pe #( //////////////////// // Strobe to send new packet. - output reg tx_pkt_start = 0, + output reg tx_pkt_start, input tx_pkt_end, // Packet type to send - output reg [3:0] tx_pid = 0, + output reg [3:0] tx_pid, // Data payload to send if any output tx_data_avail, @@ -100,13 +100,13 @@ module usb_fs_in_pe #( integer i = 0; initial begin for (i = 0; i < NUM_IN_EPS; i = i + 1) begin - ep_put_addr[i] = 0; - ep_get_addr[i] = 0; - ep_state[i] = 0; + ep_put_addr[i] <= 0; + ep_get_addr[i] <= 0; + ep_state[i] <= 0; end end - reg [3:0] in_ep_num = 0; + reg [3:0] in_ep_num; wire [8:0] buffer_put_addr = {in_ep_num[3:0], ep_put_addr[in_ep_num][4:0]}; wire [8:0] buffer_get_addr = {current_endp[3:0], ep_get_addr[current_endp][4:0]}; @@ -400,4 +400,4 @@ module usb_fs_in_pe #( end end -endmodule \ No newline at end of file +endmodule diff --git a/common/usb_fs_out_pe.v b/common/usb_fs_out_pe.v index 26d0802..17f46c7 100644 --- a/common/usb_fs_out_pe.v +++ b/common/usb_fs_out_pe.v @@ -12,7 +12,7 @@ module usb_fs_out_pe #( // endpoint interface //////////////////// output [NUM_OUT_EPS-1:0] out_ep_data_avail, - output reg [NUM_OUT_EPS-1:0] out_ep_setup = 0, + output reg [NUM_OUT_EPS-1:0] out_ep_setup, input [NUM_OUT_EPS-1:0] out_ep_data_get, output reg [7:0] out_ep_data, input [NUM_OUT_EPS-1:0] out_ep_stall, @@ -44,9 +44,9 @@ module usb_fs_out_pe #( //////////////////// // Strobe to send new packet. - output reg tx_pkt_start = 0, + output reg tx_pkt_start, input tx_pkt_end, - output reg [3:0] tx_pid = 0 + output reg [3:0] tx_pid ); //////////////////////////////////////////////////////////////////////////////// // endpoint state machine @@ -71,12 +71,12 @@ module usb_fs_out_pe #( reg [1:0] out_xfr_state = IDLE; reg [1:0] out_xfr_state_next; - reg out_xfr_start = 0; + reg out_xfr_start; reg new_pkt_end = 0; reg rollback_data = 0; - reg [3:0] out_ep_num = 0; + reg [3:0] out_ep_num; reg [NUM_OUT_EPS - 1:0] out_ep_data_avail_i = 0; @@ -287,7 +287,6 @@ module usb_fs_out_pe #( if (out_token_received || setup_token_received) begin out_xfr_state_next <= RCVD_OUT; out_xfr_start <= 1; - end else begin out_xfr_state_next <= IDLE; end @@ -296,7 +295,6 @@ module usb_fs_out_pe #( RCVD_OUT : begin if (rx_pkt_start) begin out_xfr_state_next <= RCVD_DATA_START; - end else begin out_xfr_state_next <= RCVD_OUT; end @@ -410,4 +408,4 @@ module usb_fs_out_pe #( end end -endmodule \ No newline at end of file +endmodule diff --git a/common/usb_fs_pe.v b/common/usb_fs_pe.v index dadb719..dee04c6 100644 --- a/common/usb_fs_pe.v +++ b/common/usb_fs_pe.v @@ -2,10 +2,10 @@ module usb_fs_pe #( parameter [4:0] NUM_OUT_EPS = 1, parameter [4:0] NUM_IN_EPS = 1 ) ( + input clk_48mhz, input clk, input [6:0] dev_addr, - //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// /// USB Endpoint Interface @@ -187,7 +187,8 @@ module usb_fs_pe #( ); usb_fs_rx usb_fs_rx_inst ( - .clk_48mhz(clk), + .clk_48mhz(clk_48mhz), + .clk(clk), .reset(reset), .dp(usb_p_rx), .dn(usb_n_rx), @@ -218,7 +219,8 @@ module usb_fs_pe #( ); usb_fs_tx usb_fs_tx_inst ( - .clk_48mhz(clk), + .clk_48mhz(clk_48mhz), + .clk(clk), .reset(reset), .bit_strobe(bit_strobe), .oe(usb_tx_en), @@ -231,4 +233,4 @@ module usb_fs_pe #( .tx_data_get(tx_data_get), .tx_data(tx_data) ); -endmodule \ No newline at end of file +endmodule diff --git a/common/usb_fs_rx.v b/common/usb_fs_rx.v index 8c73f68..ab9c73c 100644 --- a/common/usb_fs_rx.v +++ b/common/usb_fs_rx.v @@ -1,36 +1,39 @@ module usb_fs_rx ( // A 48MHz clock is required to recover the clock from the incoming data. input clk_48mhz, + input clk, input reset, - // USB data+ and data- lines. + // USB data+ and data- lines (clk_48mhz domain) input dp, input dn, - // pulse on every bit transition. + // pulse on every bit transition (clk_48mhz domain) output bit_strobe, - // Pulse on beginning of new packet. + // Pulse on beginning of new packet (clk domain) output pkt_start, - // Pulse on end of current packet. + // Pulse on end of current packet (clk domain) output pkt_end, - // Most recent packet decoded. + // Most recent packet decoded (clk domain) output [3:0] pid, - output reg [6:0] addr = 0, - output reg [3:0] endp = 0, - output reg [10:0] frame_num = 0, + output [6:0] addr, + output [3:0] endp, + output [10:0] frame_num, - // Pulse on valid data on rx_data. + // Pulse on valid data on rx_data (clk domain) output rx_data_put, output [7:0] rx_data, - // Most recent packet passes PID and CRC checks + // Most recent packet passes PID and CRC checks (clk domain) output valid_packet ); - wire clk = clk_48mhz; - + wire [3:0] pid_48; + reg [6:0] addr_48; + reg [3:0] endp_48; + reg [10:0] frame_num_48; //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// //////// @@ -51,7 +54,7 @@ module usb_fs_rx ( reg [3:0] dpair_q = 0; - always @(posedge clk) begin + always @(posedge clk_48mhz) begin dpair_q[3:0] <= {dpair_q[1:0], dp, dn}; end @@ -78,7 +81,7 @@ module usb_fs_rx ( wire [1:0] dpair = dpair_q[3:2]; - always @(posedge clk) begin + always @(posedge clk_48mhz) begin case (line_state) // if we are in a transition state, then we can sample the pair and // move to the next corresponding line state @@ -122,7 +125,7 @@ module usb_fs_rx ( wire line_state_valid = (bit_phase == 1); assign bit_strobe = (bit_phase == 2); - always @(posedge clk) begin + always @(posedge clk_48mhz) begin // keep track of phase within each bit if (line_state == DT) begin bit_phase <= 0; @@ -165,7 +168,7 @@ module usb_fs_rx ( end end - always @(posedge clk) begin + always @(posedge clk_48mhz) begin if (reset) begin line_history <= 6'b101010; packet_valid <= 0; @@ -214,7 +217,7 @@ module usb_fs_rx ( reg [5:0] bitstuff_history = 0; - always @(posedge clk) begin + always @(posedge clk_48mhz) begin if (reset || packet_end) begin bitstuff_history <= 6'b000000; end else begin @@ -224,7 +227,7 @@ module usb_fs_rx ( end end - assign dvalid = dvalid_raw && !(bitstuff_history == 6'b111111); + wire dvalid = dvalid_raw && !(bitstuff_history == 6'b111111); //////////////////////////////////////////////////////////////////////////////// @@ -237,7 +240,7 @@ module usb_fs_rx ( wire pid_valid = full_pid[4:1] == ~full_pid[8:5]; wire pid_complete = full_pid[0]; - always @(posedge clk) begin + always @(posedge clk_48mhz) begin if (packet_start) begin full_pid <= 9'b100000000; end @@ -253,7 +256,7 @@ module usb_fs_rx ( reg [4:0] crc5 = 0; wire crc5_valid = crc5 == 5'b01100; wire crc5_invert = din ^ crc5[4]; - always @(posedge clk) begin + always @(posedge clk_48mhz) begin if (packet_start) begin crc5 <= 5'b11111; end @@ -274,7 +277,7 @@ module usb_fs_rx ( wire crc16_valid = crc16 == 16'b1000000000001101; wire crc16_invert = din ^ crc16[15]; - always @(posedge clk) begin + always @(posedge clk_48mhz) begin if (packet_start) begin crc16 <= 16'b1111111111111111; end @@ -309,17 +312,19 @@ module usb_fs_rx ( // TODO: need to check for data packet babble // TODO: do i need to check for bitstuff error? - assign valid_packet = pid_valid && ( + wire valid_packet_48 = pid_valid && ( (pkt_is_handshake) || (pkt_is_data && crc16_valid) || (pkt_is_token && crc5_valid) ); + // valid is level, not a strobe + dflip valid_buffer(clk, valid_packet_48, valid_packet); reg [11:0] token_payload = 0; wire token_payload_done = token_payload[0]; - always @(posedge clk) begin + always @(posedge clk_48mhz) begin if (packet_start) begin token_payload <= 12'b100000000000; end @@ -329,17 +334,31 @@ module usb_fs_rx ( end end - always @(posedge clk) begin + always @(posedge clk_48mhz) begin if (token_payload_done && pkt_is_token) begin - addr <= token_payload[7:1]; - endp <= token_payload[11:8]; - frame_num <= token_payload[11:1]; + addr_48 <= token_payload[7:1]; + endp_48 <= token_payload[11:8]; + frame_num_48 <= token_payload[11:1]; end end - assign pkt_start = packet_start; - assign pkt_end = packet_end; - assign pid = full_pid[4:1]; + // cross the packet start signal to the endpoint clk domain + strobe pkt_start_strobe( + .clk_in(clk_48mhz), + .clk_out(clk), + .strobe_in(packet_start), + .strobe_out(pkt_start) + ); + + // at the end of the packet, capture the parameters to the clk domain + strobe #(.WIDTH(26)) pkt_end_strobe( + clk_48mhz, clk, + packet_end, pkt_end, + { pid_48, addr_48, endp_48, frame_num_48 }, + { pid, addr, endp, frame_num } + ); + assign pid_48 = full_pid[4:1]; + //assign addr = token_payload[7:1]; //assign endp = token_payload[11:8]; //assign frame_num = token_payload[11:1]; @@ -350,10 +369,15 @@ module usb_fs_rx ( //assign rx_data_put = dvalid && pid_complete && pkt_is_data; reg [8:0] rx_data_buffer = 0; wire rx_data_buffer_full = rx_data_buffer[0]; - assign rx_data_put = rx_data_buffer_full; - assign rx_data = rx_data_buffer[8:1]; - always @(posedge clk) begin + // convert the rx_data_put to clk domain + strobe #(.WIDTH(8)) rx_data_strobe( + clk_48mhz, clk, + rx_data_buffer_full, rx_data_put, + rx_data_buffer[8:1], rx_data + ); + + always @(posedge clk_48mhz) begin if (packet_start || rx_data_buffer_full) begin rx_data_buffer <= 9'b100000000; end diff --git a/common/usb_fs_tx.v b/common/usb_fs_tx.v index c9ba07a..34d2377 100644 --- a/common/usb_fs_tx.v +++ b/common/usb_fs_tx.v @@ -2,9 +2,10 @@ module usb_fs_tx ( // A 48MHz clock is required to receive USB data at 12MHz // it's simpler to juse use 48MHz everywhere input clk_48mhz, + input clk, input reset, - // bit strobe from rx to align with senders clock + // bit strobe from rx to align with senders clock (in clk_48mhz domain) input bit_strobe, // output enable to take ownership of bus and data out @@ -12,28 +13,43 @@ module usb_fs_tx ( output reg dp = 0, output reg dn = 0, - // pulse to initiate new packet transmission + // pulse to initiate new packet transmission (clk domain) input pkt_start, + + // pulse to indicate end of packet transmission (clk domain) output pkt_end, - // pid to send + // pid to send (clk domain) input [3:0] pid, // tx logic pulls data until there is nothing available input tx_data_avail, - output reg tx_data_get = 0, + output tx_data_get, input [7:0] tx_data ); - wire clk = clk_48mhz; - + // convert pkt_start to clk_48mhz domain // save packet parameters at pkt_start - reg [3:0] pidq = 0; - - always @(posedge clk) begin - if (pkt_start) begin - pidq <= pid; - end - end + wire pkt_start_48; + wire [3:0] pidq; + strobe #(.WIDTH(4)) pkt_start_strobe( + clk, clk_48mhz, + pkt_start, pkt_start_48, + pid, pidq + ); + + wire tx_data_avail_48; + dflip tx_data_avail_buffer(clk_48mhz, tx_data_avail, tx_data_avail_48); + //wire tx_data_avail_48 = tx_data_avail; + + // convert tx_data_get from 48 to clk + //wire tx_data_get_48 = tx_data_get; + reg tx_data_get_48; + strobe tx_data_get_strobe( + .clk_in(clk_48mhz), + .clk_out(clk), + .strobe_in(tx_data_get_48), + .strobe_out(tx_data_get) + ); reg [7:0] data_shift_reg = 0; reg [7:0] oe_shift_reg = 0; @@ -58,14 +74,20 @@ module usb_fs_tx ( reg bitstuff_qqqq = 0; - always @(posedge clk) begin + always @(posedge clk_48mhz) begin bitstuff_q <= bitstuff; bitstuff_qq <= bitstuff_q; bitstuff_qqq <= bitstuff_qq; bitstuff_qqqq <= bitstuff_qqq; end - assign pkt_end = bit_strobe && se0_shift_reg[1:0] == 2'b01; + wire pkt_end_48 = bit_strobe && se0_shift_reg[1:0] == 2'b01; + strobe pkt_end_strobe( + .clk_in(clk_48mhz), + .clk_out(clk), + .strobe_in(pkt_end_48), + .strobe_out(pkt_end) + ); reg data_payload = 0; @@ -79,10 +101,10 @@ module usb_fs_tx ( reg [15:0] crc16 = 0; - always @(posedge clk) begin + always @(posedge clk_48mhz) begin case (pkt_state) IDLE : begin - if (pkt_start) begin + if (pkt_start_48) begin pkt_state <= SYNC; end end @@ -112,23 +134,23 @@ module usb_fs_tx ( DATA_OR_CRC16_0 : begin if (byte_strobe) begin - if (tx_data_avail) begin + if (tx_data_avail_48) begin pkt_state <= DATA_OR_CRC16_0; data_payload <= 1; - tx_data_get <= 1; + tx_data_get_48 <= 1; data_shift_reg <= tx_data; oe_shift_reg <= 8'b11111111; se0_shift_reg <= 8'b00000000; end else begin pkt_state <= CRC16_1; data_payload <= 0; - tx_data_get <= 0; + tx_data_get_48 <= 0; data_shift_reg <= ~{crc16[8], crc16[9], crc16[10], crc16[11], crc16[12], crc16[13], crc16[14], crc16[15]}; oe_shift_reg <= 8'b11111111; se0_shift_reg <= 8'b00000000; end end else begin - tx_data_get <= 0; + tx_data_get_48 <= 0; end end @@ -156,7 +178,7 @@ module usb_fs_tx ( byte_strobe <= 0; end - if (pkt_start) begin + if (pkt_start_48) begin bit_count <= 1; bit_history_q <= 0; @@ -184,12 +206,12 @@ module usb_fs_tx ( // calculate crc16 wire crc16_invert = serial_tx_data ^ crc16[15]; - always @(posedge clk) begin - if (pkt_start) begin + always @(posedge clk_48mhz) begin + if (pkt_start_48) begin crc16 <= 16'b1111111111111111; end - if (bit_strobe && data_payload && !bitstuff_qqqq && !pkt_start) begin + if (bit_strobe && data_payload && !bitstuff_qqqq && !pkt_start_48) begin crc16[15] <= crc16[14] ^ crc16_invert; crc16[14] <= crc16[13]; crc16[13] <= crc16[12]; @@ -213,8 +235,8 @@ module usb_fs_tx ( // nrzi and differential driving - always @(posedge clk) begin - if (pkt_start) begin + always @(posedge clk_48mhz) begin + if (pkt_start_48) begin // J dp <= 1; dn <= 0; diff --git a/common/usb_serial_ctrl_ep.v b/common/usb_serial_ctrl_ep.v index 0d5da0f..a104f4f 100644 --- a/common/usb_serial_ctrl_ep.v +++ b/common/usb_serial_ctrl_ep.v @@ -23,7 +23,7 @@ module usb_serial_ctrl_ep ( input in_ep_grant, input in_ep_data_free, output in_ep_data_put, - output reg [7:0] in_ep_data = 0, + output [7:0] in_ep_data, output in_ep_data_done, output reg in_ep_stall, input in_ep_acked @@ -42,10 +42,10 @@ module usb_serial_ctrl_ep ( - reg setup_stage_end = 0; - reg data_stage_end = 0; - reg status_stage_end = 0; - reg send_zero_length_data_pkt = 0; + reg setup_stage_end; + reg data_stage_end; + reg status_stage_end; + reg send_zero_length_data_pkt; @@ -59,7 +59,7 @@ module usb_serial_ctrl_ep ( always @(posedge clk) out_ep_data_valid <= out_ep_data_avail && out_ep_grant; // need to record the setup data - reg [3:0] setup_data_addr = 0; + reg [3:0] setup_data_addr; reg [9:0] raw_setup_data [7:0]; wire [7:0] bmRequestType = raw_setup_data[0]; @@ -338,132 +338,129 @@ module usb_serial_ctrl_ep ( `define CDC_RX_ENDPOINT 1 `define CDC_TX_ENDPOINT 1 + reg [7:0] ep_rom[255:0]; + assign in_ep_data = ep_rom[rom_addr]; - always @* begin - case (rom_addr) + initial begin // device descriptor - 'h000 : in_ep_data <= 18; // bLength - 'h001 : in_ep_data <= 1; // bDescriptorType - 'h002 : in_ep_data <= 'h00; // bcdUSB[0] - 'h003 : in_ep_data <= 'h02; // bcdUSB[1] - 'h004 : in_ep_data <= 'h02; // bDeviceClass (Communications Device Class) - 'h005 : in_ep_data <= 'h00; // bDeviceSubClass (Abstract Control Model) - 'h006 : in_ep_data <= 'h00; // bDeviceProtocol (No class specific protocol required) - 'h007 : in_ep_data <= 32; // bMaxPacketSize0 - - 'h008 : in_ep_data <= 'h50; // idVendor[0] http://wiki.openmoko.org/wiki/USB_Product_IDs - 'h009 : in_ep_data <= 'h1d; // idVendor[1] - 'h00A : in_ep_data <= 'h30; // idProduct[0] - 'h00B : in_ep_data <= 'h61; // idProduct[1] + ep_rom['h000] <= 18; // bLength + ep_rom['h001] <= 1; // bDescriptorType + ep_rom['h002] <= 'h00; // bcdUSB[0] + ep_rom['h003] <= 'h02; // bcdUSB[1] + ep_rom['h004] <= 'h02; // bDeviceClass (Communications Device Class) + ep_rom['h005] <= 'h00; // bDeviceSubClass (Abstract Control Model) + ep_rom['h006] <= 'h00; // bDeviceProtocol (No class specific protocol required) + ep_rom['h007] <= 32; // bMaxPacketSize0 + + ep_rom['h008] <= 'h50; // idVendor[0] http://wiki.openmoko.org/wiki/USB_Product_IDs + ep_rom['h009] <= 'h1d; // idVendor[1] + ep_rom['h00A] <= 'h30; // idProduct[0] + ep_rom['h00B] <= 'h61; // idProduct[1] - 'h00C : in_ep_data <= 0; // bcdDevice[0] - 'h00D : in_ep_data <= 0; // bcdDevice[1] - 'h00E : in_ep_data <= 0; // iManufacturer - 'h00F : in_ep_data <= 0; // iProduct - 'h010 : in_ep_data <= 0; // iSerialNumber - 'h011 : in_ep_data <= 1; // bNumConfigurations + ep_rom['h00C] <= 0; // bcdDevice[0] + ep_rom['h00D] <= 0; // bcdDevice[1] + ep_rom['h00E] <= 0; // iManufacturer + ep_rom['h00F] <= 0; // iProduct + ep_rom['h010] <= 0; // iSerialNumber + ep_rom['h011] <= 1; // bNumConfigurations // configuration descriptor - 'h012 : in_ep_data <= 9; // bLength - 'h013 : in_ep_data <= 2; // bDescriptorType - 'h014 : in_ep_data <= (9+9+5+5+4+5+7+9+7+7); // wTotalLength[0] - 'h015 : in_ep_data <= 0; // wTotalLength[1] - 'h016 : in_ep_data <= 2; // bNumInterfaces - 'h017 : in_ep_data <= 1; // bConfigurationValue - 'h018 : in_ep_data <= 0; // iConfiguration - 'h019 : in_ep_data <= 'hC0; // bmAttributes - 'h01A : in_ep_data <= 50; // bMaxPower + ep_rom['h012] <= 9; // bLength + ep_rom['h013] <= 2; // bDescriptorType + ep_rom['h014] <= (9+9+5+5+4+5+7+9+7+7); // wTotalLength[0] + ep_rom['h015] <= 0; // wTotalLength[1] + ep_rom['h016] <= 2; // bNumInterfaces + ep_rom['h017] <= 1; // bConfigurationValue + ep_rom['h018] <= 0; // iConfiguration + ep_rom['h019] <= 'hC0; // bmAttributes + ep_rom['h01A] <= 50; // bMaxPower // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 - 'h01B : in_ep_data <= 9; // bLength - 'h01C : in_ep_data <= 4; // bDescriptorType - 'h01D : in_ep_data <= 0; // bInterfaceNumber - 'h01E : in_ep_data <= 0; // bAlternateSetting - 'h01F : in_ep_data <= 1; // bNumEndpoints - 'h020 : in_ep_data <= 2; // bInterfaceClass (Communications Device Class) - 'h021 : in_ep_data <= 2; // bInterfaceSubClass (Abstract Control Model) - 'h022 : in_ep_data <= 1; // bInterfaceProtocol (AT Commands: V.250 etc) - 'h023 : in_ep_data <= 0; // iInterface + ep_rom['h01B] <= 9; // bLength + ep_rom['h01C] <= 4; // bDescriptorType + ep_rom['h01D] <= 0; // bInterfaceNumber + ep_rom['h01E] <= 0; // bAlternateSetting + ep_rom['h01F] <= 1; // bNumEndpoints + ep_rom['h020] <= 2; // bInterfaceClass (Communications Device Class) + ep_rom['h021] <= 2; // bInterfaceSubClass (Abstract Control Model) + ep_rom['h022] <= 1; // bInterfaceProtocol (AT Commands: V.250 etc) + ep_rom['h023] <= 0; // iInterface // CDC Header Functional Descriptor, CDC Spec 5.2.3.1, Table 26 - 'h024 : in_ep_data <= 5; // bFunctionLength - 'h025 : in_ep_data <= 'h24; // bDescriptorType - 'h026 : in_ep_data <= 'h00; // bDescriptorSubtype - 'h027 : in_ep_data <= 'h10; - 'h028 : in_ep_data <= 'h01; // bcdCDC + ep_rom['h024] <= 5; // bFunctionLength + ep_rom['h025] <= 'h24; // bDescriptorType + ep_rom['h026] <= 'h00; // bDescriptorSubtype + ep_rom['h027] <= 'h10; + ep_rom['h028] <= 'h01; // bcdCDC // Call Management Functional Descriptor, CDC Spec 5.2.3.2, Table 27 - 'h029 : in_ep_data <= 5; // bFunctionLength - 'h02A : in_ep_data <= 'h24; // bDescriptorType - 'h02B : in_ep_data <= 'h01; // bDescriptorSubtype - 'h02C : in_ep_data <= 'h00; // bmCapabilities - 'h02D : in_ep_data <= 1; // bDataInterface + ep_rom['h029] <= 5; // bFunctionLength + ep_rom['h02A] <= 'h24; // bDescriptorType + ep_rom['h02B] <= 'h01; // bDescriptorSubtype + ep_rom['h02C] <= 'h00; // bmCapabilities + ep_rom['h02D] <= 1; // bDataInterface // Abstract Control Management Functional Descriptor, CDC Spec 5.2.3.3, Table 28 - 'h02E : in_ep_data <= 4; // bFunctionLength - 'h02F : in_ep_data <= 'h24; // bDescriptorType - 'h030 : in_ep_data <= 'h02; // bDescriptorSubtype - 'h031 : in_ep_data <= 'h06; // bmCapabilities + ep_rom['h02E] <= 4; // bFunctionLength + ep_rom['h02F] <= 'h24; // bDescriptorType + ep_rom['h030] <= 'h02; // bDescriptorSubtype + ep_rom['h031] <= 'h06; // bmCapabilities // Union Functional Descriptor, CDC Spec 5.2.3.8, Table 33 - 'h032 : in_ep_data <= 5; // bFunctionLength - 'h033 : in_ep_data <= 'h24; // bDescriptorType - 'h034 : in_ep_data <= 'h06; // bDescriptorSubtype - 'h035 : in_ep_data <= 0; // bMasterInterface - 'h036 : in_ep_data <= 1; // bSlaveInterface0 + ep_rom['h032] <= 5; // bFunctionLength + ep_rom['h033] <= 'h24; // bDescriptorType + ep_rom['h034] <= 'h06; // bDescriptorSubtype + ep_rom['h035] <= 0; // bMasterInterface + ep_rom['h036] <= 1; // bSlaveInterface0 // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 - 'h037 : in_ep_data <= 7; // bLength - 'h038 : in_ep_data <= 5; // bDescriptorType - 'h039 : in_ep_data <= `CDC_ACM_ENDPOINT | 'h80; // bEndpointAddress - 'h03A : in_ep_data <= 'h03; // bmAttributes (0x03=intr) - 'h03B : in_ep_data <= 8; // wMaxPacketSize[0] - 'h03C : in_ep_data <= 0; // wMaxPacketSize[1] - 'h03D : in_ep_data <= 64; // bInterval + ep_rom['h037] <= 7; // bLength + ep_rom['h038] <= 5; // bDescriptorType + ep_rom['h039] <= `CDC_ACM_ENDPOINT | 'h80; // bEndpointAddress + ep_rom['h03A] <= 'h03; // bmAttributes (0x03=intr) + ep_rom['h03B] <= 8; // wMaxPacketSize[0] + ep_rom['h03C] <= 0; // wMaxPacketSize[1] + ep_rom['h03D] <= 64; // bInterval // interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12 - 'h03E : in_ep_data <= 9; // bLength - 'h03F : in_ep_data <= 4; // bDescriptorType - 'h040 : in_ep_data <= 1; // bInterfaceNumber - 'h041 : in_ep_data <= 0; // bAlternateSetting - 'h042 : in_ep_data <= 2; // bNumEndpoints - 'h043 : in_ep_data <= 'h0A; // bInterfaceClass - 'h044 : in_ep_data <= 'h00; // bInterfaceSubClass - 'h045 : in_ep_data <= 'h00; // bInterfaceProtocol - 'h046 : in_ep_data <= 0; // iInterface + ep_rom['h03E] <= 9; // bLength + ep_rom['h03F] <= 4; // bDescriptorType + ep_rom['h040] <= 1; // bInterfaceNumber + ep_rom['h041] <= 0; // bAlternateSetting + ep_rom['h042] <= 2; // bNumEndpoints + ep_rom['h043] <= 'h0A; // bInterfaceClass + ep_rom['h044] <= 'h00; // bInterfaceSubClass + ep_rom['h045] <= 'h00; // bInterfaceProtocol + ep_rom['h046] <= 0; // iInterface // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 - 'h047 : in_ep_data <= 7; // bLength - 'h048 : in_ep_data <= 5; // bDescriptorType - 'h049 : in_ep_data <= `CDC_RX_ENDPOINT; // bEndpointAddress - 'h04A : in_ep_data <= 'h02; // bmAttributes (0x02=bulk) - 'h04B : in_ep_data <= 32; // wMaxPacketSize[0] - 'h04C : in_ep_data <= 0; // wMaxPacketSize[1] - 'h04D : in_ep_data <= 0; // bInterval + ep_rom['h047] <= 7; // bLength + ep_rom['h048] <= 5; // bDescriptorType + ep_rom['h049] <= `CDC_RX_ENDPOINT; // bEndpointAddress + ep_rom['h04A] <= 'h02; // bmAttributes (0x02=bulk) + ep_rom['h04B] <= 32; // wMaxPacketSize[0] + ep_rom['h04C] <= 0; // wMaxPacketSize[1] + ep_rom['h04D] <= 0; // bInterval // endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13 - 'h04E : in_ep_data <= 7; // bLength - 'h04F : in_ep_data <= 5; // bDescriptorType - 'h050 : in_ep_data <= `CDC_TX_ENDPOINT | 'h80; // bEndpointAddress - 'h051 : in_ep_data <= 'h02; // bmAttributes (0x02=bulk) + ep_rom['h04E] <= 7; // bLength + ep_rom['h04F] <= 5; // bDescriptorType + ep_rom['h050] <= `CDC_TX_ENDPOINT | 'h80; // bEndpointAddress + ep_rom['h051] <= 'h02; // bmAttributes (0x02=bulk) - 'h052 : in_ep_data <= 32; // wMaxPacketSize[0] - 'h053 : in_ep_data <= 0; // wMaxPacketSize[1] - 'h054 : in_ep_data <= 0; // bInterval + ep_rom['h052] <= 32; // wMaxPacketSize[0] + ep_rom['h053] <= 0; // wMaxPacketSize[1] + ep_rom['h054] <= 0; // bInterval // LINE_CODING - 'h055 : in_ep_data <= 'h80; // dwDTERate[0] - 'h056 : in_ep_data <= 'h25; // dwDTERate[1] - 'h057 : in_ep_data <= 'h00; // dwDTERate[2] - 'h058 : in_ep_data <= 'h00; // dwDTERate[3] - 'h059 : in_ep_data <= 1; // bCharFormat (1 stop bit) - 'h05A : in_ep_data <= 0; // bParityType (None) - 'h05B : in_ep_data <= 8; // bDataBits (8 bits) + ep_rom['h055] <= 'h80; // dwDTERate[0] + ep_rom['h056] <= 'h25; // dwDTERate[1] + ep_rom['h057] <= 'h00; // dwDTERate[2] + ep_rom['h058] <= 'h00; // dwDTERate[3] + ep_rom['h059] <= 1; // bCharFormat (1 stop bit) + ep_rom['h05A] <= 0; // bParityType (None) + ep_rom['h05B] <= 8; // bDataBits (8 bits) - default begin - in_ep_data <= 0; - end - endcase end endmodule diff --git a/common/usb_spi_bridge_ep.v b/common/usb_spi_bridge_ep.v index 4c4d360..36e65c7 100644 --- a/common/usb_spi_bridge_ep.v +++ b/common/usb_spi_bridge_ep.v @@ -32,8 +32,8 @@ module usb_spi_bridge_ep ( //////////////////// // spi interface //////////////////// - output reg spi_cs_b = 0, - output reg spi_sck = 0, + output reg spi_cs_b, + output reg spi_sck, output spi_mosi, input spi_miso, @@ -55,7 +55,7 @@ module usb_spi_bridge_ep ( reg [15:0] data_in_length = 0; reg [8:0] spi_out_data = 0; - reg [8:0] spi_in_data = 0; + reg [8:0] spi_in_data; //////////////////////////////////////////////////////////////////////////////// @@ -79,7 +79,7 @@ module usb_spi_bridge_ep ( reg get_cmd_out_data = 0; reg get_cmd_out_data_q = 0; reg spi_has_more_in_bytes = 0; - reg spi_has_more_out_bytes = 0; + reg spi_has_more_out_bytes; reg spi_start_new_xfr = 0; @@ -95,11 +95,11 @@ module usb_spi_bridge_ep ( localparam SPI_GET_BIT = 3; localparam SPI_END = 4; - reg spi_send_bit = 0; - reg spi_get_bit = 0; + reg spi_send_bit; + reg spi_get_bit; reg get_spi_out_data = 0; reg put_spi_in_data = 0; - reg reset_spi_bit_counter = 0; + reg reset_spi_bit_counter; reg update_spi_byte_counters = 0; reg [3:0] spi_bit_counter = 0; @@ -397,4 +397,4 @@ module usb_spi_bridge_ep ( spi_out_data <= out_ep_data; end end -endmodule \ No newline at end of file +endmodule diff --git a/tests/file_list.txt b/tests/file_list.txt index 1c65819..076f817 100644 --- a/tests/file_list.txt +++ b/tests/file_list.txt @@ -1,5 +1,6 @@ test.v ../../common/edge_detect.v +../../common/strobe.v ../../common/tinyfpga_bootloader.v ../../common/usb_fs_in_arb.v ../../common/usb_fs_in_pe.v diff --git a/tests/top_tb_header.vh b/tests/top_tb_header.vh index 42b66b0..2bf9aaf 100644 --- a/tests/top_tb_header.vh +++ b/tests/top_tb_header.vh @@ -42,6 +42,7 @@ module top_tb; vlog_tap_generator #("test.tap") vtg(); reg clk_48mhz; + reg clk = 0; reg reset = 0; initial begin @@ -51,6 +52,9 @@ module top_tb; end end + // generate the slower clock from the 48 MHz clock + always @(posedge clk_48mhz) clk <= !clk; + // usb interface wire usb_p_tx_raw; wire usb_n_tx_raw; @@ -76,6 +80,7 @@ module top_tb; tinyfpga_bootloader dut ( .clk_48mhz(clk_48mhz), + .clk(clk), .reset(reset), .usb_p_tx(usb_p_tx_raw),