learn-fpga icon indicating copy to clipboard operation
learn-fpga copied to clipboard

FOMU: UART over USB

Open BrunoLevy opened this issue 4 years ago • 7 comments

Add a UART to the FOMU (needs a USB core + UART over USB)

BrunoLevy avatar Jan 11 '21 10:01 BrunoLevy

Hi Bruno,

I have an USB-Serial core adapted from a mix of USB logic by Luke Valenty, Lawrie Griffiths and David Williams in Mecrisp-Ice.

https://github.com/tinyfpga/TinyFPGA-Bootloader https://github.com/lawrie/tiny_usb_examples https://github.com/davidthings/tinyfpga_bx_usbserial

See mecrisp-ice-1.9/common-verilog/usb. It's a drop-in UART core with the usual interface:

module usb_uart (
  input clk_48mhz,
  input resetq,
  output host_presence,

  // USB pins
  inout  pin_usb_p,
  inout  pin_usb_n,

  // UART interface
  input  uart_wr,
  input  uart_rd,
  input  [7:0] uart_tx_data,
  output [7:0] uart_rx_data,
  output uart_busy,
  output uart_valid
);

Matthias

Mecrisp avatar Jan 11 '21 10:01 Mecrisp

Hi Matthias, Awesome ! I'll try it asap !

BrunoLevy avatar Jan 11 '21 10:01 BrunoLevy

We are working on it: https://github.com/ulixxe/usb_cdc/issues/1

Mecrisp avatar Oct 19 '21 22:10 Mecrisp

Hi Bruno, this one works perfectly now: https://github.com/ulixxe/usb_cdc I already have ported Mecrisp-Ice (my Swapforth/J1a descendant) to the FOMU using the @ulixxe code for terminal, and I can recommend it. Matthias

Mecrisp avatar Nov 09 '21 23:11 Mecrisp

Bonus points for allowing different clocks for USB and for the rest of the logic. Furthermore, it is very compact and it does not need any BRAM blocks.

Mecrisp avatar Nov 09 '21 23:11 Mecrisp

See https://github.com/ulixxe/usb_cdc, included here for a complete example:

https://sourceforge.net/projects/mecrisp/files/mecrisp-ice-2.2.tar.gz/download

mecrisp-ice-2.2/fomu/icestorm/j1a.v mecrisp-ice-2.2/common-verilog/usb_cdc/

Done :-)

Mecrisp avatar Jan 08 '22 08:01 Mecrisp

  // ######   USB-CDC terminal   ##############################

  assign usb_dp_pu = resetq;

  wire usb_p_tx;
  wire usb_n_tx;
  wire usb_p_rx;
  wire usb_n_rx;
  wire usb_tx_en;

   SB_IO #(
       .PIN_TYPE(6'b 1010_01), // PIN_OUTPUT_TRISTATE - PIN_INPUT
       .PULLUP(1'b 0)
   ) iobuf_usbp (
       .PACKAGE_PIN(usb_dp),
       .OUTPUT_ENABLE(usb_tx_en),
       .D_OUT_0(usb_p_tx),
       .D_IN_0(usb_p_rx)
   );

   SB_IO #(
       .PIN_TYPE(6'b 1010_01), // PIN_OUTPUT_TRISTATE - PIN_INPUT
       .PULLUP(1'b 0)
   ) iobuf_usbn (
       .PACKAGE_PIN(usb_dn),
       .OUTPUT_ENABLE(usb_tx_en),
       .D_OUT_0(usb_n_tx),
       .D_IN_0(usb_n_rx)
   );

  usb_cdc #(.VENDORID(16'h0483), .PRODUCTID(16'h5740), .BIT_SAMPLES(4), .USE_APP_CLK(1), .APP_CLK_RATIO(4)) _terminal
  (
    // Part running on 48 MHz:

    .clk_i(clk_usb),
    .tx_en_o(usb_tx_en),
    .tx_dp_o(usb_p_tx),
    .tx_dn_o(usb_n_tx),
    .rx_dp_i(usb_p_rx),
    .rx_dn_i(usb_n_rx),

    // Part running on 12 MHz:

    .app_clk_i(clk),
    .rstn_i(resetq),

    .out_data_o(terminal_data),
    .out_valid_o(terminal_valid),
    .out_ready_i(terminal_rd),

    .in_data_i(io_dout[7:0]),
    .in_ready_o(terminal_ready),
    .in_valid_i(terminal_wr)
  );

  wire terminal_valid, terminal_ready;
  wire [7:0] terminal_data;
  wire terminal_wr = io_wr & io_addr[12];
  wire terminal_rd = io_rd & io_addr[12];

Mecrisp avatar Jan 08 '22 08:01 Mecrisp