From b59c56527231dd03248decf9b8229e8f1165e41f Mon Sep 17 00:00:00 2001 From: Steffen Moeller Date: Sat, 6 Aug 2016 03:52:39 +0200 Subject: [PATCH 01/10] Close to USB-facilitated echo --- uart_echo/.gitignore | 1 + uart_echo/Makefile | 63 +++++++++++++++++++++++++ uart_echo/README.md | 18 +++++++ uart_echo/pinmap_ct256.pcf | 13 ++++++ uart_echo/pinmap_tq144.pcf | 10 ++++ uart_echo/top.v | 96 ++++++++++++++++++++++++++++++++++++++ uart_echo/uart_clock.v | 37 +++++++++++++++ uart_echo/uart_clock_top.v | 23 +++++++++ uart_echo/uart_rx.v | 72 ++++++++++++++++++++++++++++ uart_echo/uart_tx.v | 74 +++++++++++++++++++++++++++++ 10 files changed, 407 insertions(+) create mode 100644 uart_echo/.gitignore create mode 100644 uart_echo/Makefile create mode 100644 uart_echo/README.md create mode 100644 uart_echo/pinmap_ct256.pcf create mode 100644 uart_echo/pinmap_tq144.pcf create mode 100644 uart_echo/top.v create mode 100644 uart_echo/uart_clock.v create mode 100644 uart_echo/uart_clock_top.v create mode 100644 uart_echo/uart_rx.v create mode 100644 uart_echo/uart_tx.v diff --git a/uart_echo/.gitignore b/uart_echo/.gitignore new file mode 100644 index 0000000..a007fea --- /dev/null +++ b/uart_echo/.gitignore @@ -0,0 +1 @@ +build/* diff --git a/uart_echo/Makefile b/uart_echo/Makefile new file mode 100644 index 0000000..13086ec --- /dev/null +++ b/uart_echo/Makefile @@ -0,0 +1,63 @@ +# Project setup +PROJ = uart +BUILD = ./build +DEVICE = 1k +#DEVICE = 8k +ifeq (8k,$(DEVICE)) +FOOTPRINT = ct256 +else +FOOTPRINT = tq144 +endif +STICKTTY = /dev/ttyUSB1 + +# Files +FILES = top.v +FILES += uart_tx.v +FILES += uart_rx.v +FILES += uart_clock.v + +FILEStest = uart_clock.v +FILEStest += uart_clock_top.v + +.PHONY: all clean burn + +all:$(BUILD)/$(PROJ).bin + +$(BUILD)/$(PROJ).blif: $(FILES) Makefile + # if build folder doesn't exist, create it + mkdir -p $(BUILD) + # synthesize using Yosys + yosys -p "synth_ice40 -top top -blif $(BUILD)/$(PROJ).blif" $(FILES) + +$(BUILD)/$(PROJ).asc: pinmap_$(FOOTPRINT).pcf $(BUILD)/$(PROJ).blif + # Place and route using arachne + arachne-pnr -d $(DEVICE) -P $(FOOTPRINT) -o $(BUILD)/$(PROJ).asc -p pinmap_$(FOOTPRINT).pcf $(BUILD)/$(PROJ).blif + +$(BUILD)/$(PROJ).bin: $(BUILD)/$(PROJ).asc + # Convert to bitstream using IcePack + icepack $(BUILD)/$(PROJ).asc $(BUILD)/$(PROJ).bin + +burn: $(BUILD)/$(PROJ).bin + iceprog $< + +iverilog: a.out +a.out: $(FILES) + iverilog $(FILES) + + +test: $(BUILD)/$(PROJ)test.bin +$(BUILD)/$(PROJ)test.bin: Makefile $(FILEStest) + iverilog $(FILEStest) + mkdir -p $(BUILD) + yosys -p "synth_ice40 -top uart_clock_top -blif $(BUILD)/$(PROJ)test.blif" $(FILEStest) + arachne-pnr -d $(DEVICE) -P $(FOOTPRINT) -o $(BUILD)/$(PROJ)test.asc -p pinmap_$(FOOTPRINT).pcf $(BUILD)/$(PROJ)test.blif + icepack $(BUILD)/$(PROJ)test.asc $(BUILD)/$(PROJ)test.bin + +burntest: $(BUILD)/$(PROJ)test.bin + iceprog $< + +run: + sudo screen $(STICKTTY) + +clean: + rm -f build/* a.out diff --git a/uart_echo/README.md b/uart_echo/README.md new file mode 100644 index 0000000..930e9c6 --- /dev/null +++ b/uart_echo/README.md @@ -0,0 +1,18 @@ +This bitstream lets the FPGA control the serial line +setting of the FTDI chip, which again is connected to +the USB port. The iCE stick then behaves exactly like +a modem connected with an USB port and can be connected +to with a regular terminal program. + +An important parameter are the number of characters +per second to be transmitted, i.e. BAUD. This example +sets this to 9600 - which is slow. Use the following +commands to adress the FPGA: + +Linux: + + * minicom -b 9600 -D /dev/ttyUSB1 # or alternatively + * screen /dev/ttyUSB1 + + We observed fewer issues with screen wrt to forwarding + input from the keyboard. diff --git a/uart_echo/pinmap_ct256.pcf b/uart_echo/pinmap_ct256.pcf new file mode 100644 index 0000000..7fd3120 --- /dev/null +++ b/uart_echo/pinmap_ct256.pcf @@ -0,0 +1,13 @@ +# example.pcf +set_io --warn-no-port led1 B5 +set_io --warn-no-port led2 B4 +set_io --warn-no-port led3 A2 +set_io --warn-no-port led4 A1 +set_io --warn-no-port led5 C5 +set_io --warn-no-port led6 C4 +set_io --warn-no-port led7 B3 +set_io --warn-no-port led8 C3 +set_io --warn-no-port hwclk J3 +# FTDI / UART pins +set_io --warn-no-port tx B12 +set_io --warn-no-port rx B10 diff --git a/uart_echo/pinmap_tq144.pcf b/uart_echo/pinmap_tq144.pcf new file mode 100644 index 0000000..4891105 --- /dev/null +++ b/uart_echo/pinmap_tq144.pcf @@ -0,0 +1,10 @@ +# example.pcf +set_io --warn-no-port hwclk 21 +set_io --warn-no-port led1 99 +set_io --warn-no-port led2 98 +set_io --warn-no-port led3 97 +set_io --warn-no-port led4 96 +#set_io --warn-no-port led5 95 +# FTDI / UART pins +set_io --warn-no-port tx 8 +set_io --warn-no-port rx 9 diff --git a/uart_echo/top.v b/uart_echo/top.v new file mode 100644 index 0000000..053566c --- /dev/null +++ b/uart_echo/top.v @@ -0,0 +1,96 @@ +/* Top level module for keypad + UART demo */ +module top ( + // input hardware clock (12 MHz) + input wire hwclk, + // all LEDs + output wire led1, + output wire led2, + output wire led3, + output wire led4, + // UART lines + output wire tx, + input wire rx + ); + + // UART registers + wire [7:0] uart_rxbyte; + reg [7:0] uart_txbyte=8'b0; + reg uart_send = 1'b1; // do not send anything by default + reg uart_receive = 1'b1; // listen + wire uart_txed; + wire uart_rxed; + + // LED register + reg ledval1 = 0; + reg ledval2 = 0; + reg ledval3 = 0; + reg ledval4 = 0; + + // wire[1:0] state; + +/* + assign led3 = ~state[1]; + assign led4 = ~state[0]; +*/ + + // 9600 Hz clock generation (from 12 MHz) + parameter period_9600 = 32'd625; + wire clk_9600; + reg clk_9600_reset=0; + uart_clock clock_9600 ( + .hwclk(hwclk), + .reset(clk_9600_reset), + .period(period_9600), + .clk(clk_9600) + ); + + // UART receiver module designed for + // 8 bits, no parity, 1 stop bit. + uart_rx_8n1 receiver ( + .clk (clk_9600), // 9600 baud rate clock + .rx (rx), // input UART rx pin + .recvdata (uart_receive), // allow any incoming bytes + .rxbyte (uart_rxbyte), // byte received + .rxdone (uart_rxed) // input: rx is finished + ); + + // UART transmitter module designed for + // 8 bits, no parity, 1 stop bit. + uart_tx_8n1 transmitter ( + .clk (clk_9600), // 9600 baud rate clock + .tx (tx), // output UART tx pin + //.senddata (uart_rxed), // trigger a UART transmit on baud clock + //.senddata (1'b1), // trigger a UART transmit on baud clock + .senddata (uart_send), // trigger a UART transmit on baud clock + .txbyte (uart_txbyte), // byte to be transmitted + //.txbyte (8'd70), // byte to be transmitted + .txdone (uart_txed) // input: tx is finished + ); + + + + + // Wiring + //assign led1=ledval1; + assign led2=ledval2; + assign led3=ledval3; + assign led4=ledval4; + + always @(posedge rx) begin + ledval2 <= ~ledval2; + end + + always @(posedge uart_txed) begin + ledval3 <= ~ledval3; + //uart_send <= 0; + end + + always @(posedge uart_rxed) begin + ledval4 <= ~ledval4; + // Here the 'echo' operation + uart_txbyte <= uart_rxbyte; + uart_send <= 1; + end + + +endmodule diff --git a/uart_echo/uart_clock.v b/uart_echo/uart_clock.v new file mode 100644 index 0000000..1e6480a --- /dev/null +++ b/uart_echo/uart_clock.v @@ -0,0 +1,37 @@ +/* Top level module for keypad + UART demo */ +module uart_clock ( + input wire hwclk, // input hardware clock (12 MHz) + input wire reset, // reset hardware clock to 0 + input wire [31:0] period, + output wire clk // clock of reduced speed + //, output wire led + ); + + reg [31:0] cntr = 32'b0; + + reg clkval=1'b0; + + initial begin + clkval=1'b0; + end + +/* + // Breaks it - as if ever active + always @ (posedge reset) begin + clkval=1'b0; + cntr <= 32'b0; + end +*/ + + always @ (posedge hwclk) begin + cntr <= cntr + 1; + if (cntr == period) begin + clkval <= ~clkval; + cntr <= 32'b0; + end + end + + assign clk = clkval; + //assign led = clkval; + +endmodule diff --git a/uart_echo/uart_clock_top.v b/uart_echo/uart_clock_top.v new file mode 100644 index 0000000..ca34918 --- /dev/null +++ b/uart_echo/uart_clock_top.v @@ -0,0 +1,23 @@ +module uart_clock_top ( + // input hardware clock (12 MHz) + input wire hwclk, + // all LEDs + output wire led1, + output wire led2, + output wire led3, + output wire led4 +); + + parameter period_1 = 32'd6000000; + wire clk_1; + reg clk_1_reset=0; + uart_clock clock_1 ( + .hwclk(hwclk), + .reset(clk_1_reset), + .period(period_1), + .clk(clk_1), +// .led(led3) + ); + assign led4 = ~clk_1; + +endmodule diff --git a/uart_echo/uart_rx.v b/uart_echo/uart_rx.v new file mode 100644 index 0000000..7e36b7d --- /dev/null +++ b/uart_echo/uart_rx.v @@ -0,0 +1,72 @@ +// 8N1 UART Module, transmit only + +module uart_rx_8n1 ( + input wire clk, // input clock + input wire rx, // rx wire + input wire recvdata, // allow any bytes to come in + output reg[7:0] rxbyte, // incoming byte as output + output reg rxdone // byte received +// , output wire[1:0] stateOut + ); + + /* Parameters */ + parameter STATE_IDLE = 2'd0; + parameter STATE_RXING = 2'd1; + parameter STATE_STOPRX= 2'd2; + parameter STATE_RXDONE= 2'd3; + + /* State variables */ + reg[1:0] state=STATE_IDLE; + reg[7:0] buf_rx=8'b0; + reg[4:0] bits_received=5'b0; + + //assign stateOut=state; + + /* always */ + always @ (posedge clk) begin + + case (state) + + STATE_IDLE: begin + rxdone <= 1'b0; + if (recvdata) begin + // check if startbit was sent + if (1'b0 == rx) begin + state <= STATE_RXING; + // initialise what is to come + rxbyte <= 8'b0; + bits_received <= 5'b0; + end + end + end + + STATE_RXING: begin + if (bits_received < 5'd8) begin + // received a data bit + buf_rx = buf_rx>>1; + buf_rx[7] = rx; + //buf_rx = {rx,buf_rx[7:1]}; + bits_received <= bits_received + 1; + end else begin + // received the stop bit + state <= STATE_RXDONE; + rxbyte <= buf_rx; + //rxbyte <= 8'd69; + end + //rxbyte <= "0"+ bits_received; + end + + STATE_RXDONE: begin + state <= STATE_IDLE; + rxdone <= 1'b1; + end + + default: begin + state <= STATE_IDLE; + end + + endcase + + end // always + +endmodule diff --git a/uart_echo/uart_tx.v b/uart_echo/uart_tx.v new file mode 100644 index 0000000..a7fc730 --- /dev/null +++ b/uart_echo/uart_tx.v @@ -0,0 +1,74 @@ +// 8N1 UART Module, transmit only + +module uart_tx_8n1 ( + input wire clk, // input clock + output wire tx, // tx wire + input wire senddata, // trigger tx + input wire[7:0] txbyte, // outgoing byte + output reg txdone // outgoing byte sent + ); + + /* Parameters */ + parameter STATE_IDLE = 2'd0; + parameter STATE_STARTTX= 2'd1; + parameter STATE_TXING = 2'd2; + parameter STATE_TXDONE = 2'd3; + + /* State variables */ + reg[1:0] state= STATE_IDLE; + reg[7:0] buf_tx=8'b0; + reg[7:0] bits_sent=5'b0; + reg txbit=1'b1; + + /* Wiring */ + assign tx=txbit; + + /* always */ + always @ (posedge clk) begin + + case (state) + + STATE_IDLE: begin + // start sending? + if (senddata == 1) begin + state <= STATE_STARTTX; + buf_tx <= txbyte; + txdone <= 1'b0; + end else if (state == STATE_IDLE) begin + // idle at high + txbit <= 1'b1; + txdone <= 1'b0; + end + end + + STATE_STARTTX: begin + txbit <= 1'b0; + state <= STATE_TXING; + end + + STATE_TXING: begin + if (bits_sent < 5'd8) begin + txbit <= buf_tx[0]; + buf_tx <= buf_tx>>1; + bits_sent = bits_sent + 1; + end else begin + // send stop bit (high) + txbit <= 1'b1; + bits_sent <= 5'b0; + state <= STATE_TXDONE; + end + end + + STATE_TXDONE: begin + txdone <= 1'b1; + state <= STATE_IDLE; + end + + default: begin + state <= STATE_IDLE; + end + + endcase + end + +endmodule From 0d1f7e0f21ed538750e159ddb47286a85e52fc97 Mon Sep 17 00:00:00 2001 From: Ruben Undheim Date: Sun, 7 Aug 2016 10:36:23 +0200 Subject: [PATCH 02/10] Only send once --- uart_echo/top.v | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/uart_echo/top.v b/uart_echo/top.v index 053566c..8c4b800 100644 --- a/uart_echo/top.v +++ b/uart_echo/top.v @@ -76,21 +76,25 @@ module top ( assign led3=ledval3; assign led4=ledval4; - always @(posedge rx) begin - ledval2 <= ~ledval2; + always @(posedge clk_9600) begin + if(uart_rxed) begin + uart_txbyte <= uart_rxbyte; + uart_send <= 1; + ledval4 <= ~ledval4; + end + else begin + uart_send <= 0; + end + + if(uart_txed) begin + ledval3 <= ~ledval3; + end + + if(rx) begin + ledval2 <= ~ledval2; + end end - always @(posedge uart_txed) begin - ledval3 <= ~ledval3; - //uart_send <= 0; - end - - always @(posedge uart_rxed) begin - ledval4 <= ~ledval4; - // Here the 'echo' operation - uart_txbyte <= uart_rxbyte; - uart_send <= 1; - end endmodule From 243c1036c0092698b77e7d9bb86015bec4e55fd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20M=C3=B6ller?= Date: Sun, 7 Aug 2016 12:41:41 +0200 Subject: [PATCH 03/10] Update README.md --- uart_echo/README.md | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/uart_echo/README.md b/uart_echo/README.md index 930e9c6..e6920ff 100644 --- a/uart_echo/README.md +++ b/uart_echo/README.md @@ -2,17 +2,26 @@ This bitstream lets the FPGA control the serial line setting of the FTDI chip, which again is connected to the USB port. The iCE stick then behaves exactly like a modem connected with an USB port and can be connected -to with a regular terminal program. +to with a regular terminal emulator from any operating +system. An important parameter are the number of characters per second to be transmitted, i.e. BAUD. This example -sets this to 9600 - which is slow. Use the following -commands to adress the FPGA: - -Linux: +sets this to 9600 - which is slow. Under Linux, you may +use the following commands to address the FPGA once the +bistream was burnt to it: * minicom -b 9600 -D /dev/ttyUSB1 # or alternatively * screen /dev/ttyUSB1 - We observed fewer issues with screen wrt to forwarding - input from the keyboard. +The use of screen may sound surprising to many. To become +familar with it is however a very good investment and +highly encouraged. Minicom you leave with "CTRL-A x", +screen with "CTRL-A d". + +The 'uart_echo' example was derived from the only writing +example 'uart_transmission' of Paul Martin after an idea +from Stefan Ziegenbalg at http://www.ztex.de/firmware-kit/example.e.html. +It was prepared by Steffen Möller and Ruben Undheim as a donation +to the ice40 example collection of Paul Martin under the +same current or future license as the reminder of his code base. From aeab962cc9ba61c4312b13d98a21fa9867b51449 Mon Sep 17 00:00:00 2001 From: Steffen Moeller Date: Tue, 9 Aug 2016 01:04:09 +0200 Subject: [PATCH 04/10] Introducing host communication with FPGA A small C-implemented program communicates back and forth with the device over USB. --- uart_echo/.gitignore | 2 + uart_echo/Makefile | 36 ++++++++++-- uart_echo/README.md | 22 +++++-- uart_echo/host.c | 136 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 186 insertions(+), 10 deletions(-) create mode 100644 uart_echo/host.c diff --git a/uart_echo/.gitignore b/uart_echo/.gitignore index a007fea..900ccbb 100644 --- a/uart_echo/.gitignore +++ b/uart_echo/.gitignore @@ -1 +1,3 @@ build/* +core +host diff --git a/uart_echo/Makefile b/uart_echo/Makefile index 13086ec..3a9b4b1 100644 --- a/uart_echo/Makefile +++ b/uart_echo/Makefile @@ -1,8 +1,23 @@ # Project setup PROJ = uart BUILD = ./build + +# This code is compatible with the devices +# 1k, short for iCE40 HX1K - the USB stick +# 8k, short for iCE40 HX8K - a small USB-connected development board +# Device-specific files are not overwritten, which which this Makefile +# looks just a bit uncomfortable at a first sight. + +# Uncomment the the line that you want to build the firmware for DEVICE = 1k #DEVICE = 8k + +#### nothing to configure below this line ##### + +# The FOOTPRINT describes what port of the FPGA are connected to what +# feature on the chip. This depends on the device, so this Makefile +# knows how to configures this. + ifeq (8k,$(DEVICE)) FOOTPRINT = ct256 else @@ -21,7 +36,12 @@ FILEStest += uart_clock_top.v .PHONY: all clean burn -all:$(BUILD)/$(PROJ).bin +all:$(BUILD)/$(PROJ).bin host + + +CFLAGS += -g +host: host.c Makefile + $(CC) $(CFLAGS) -o host host.c $(BUILD)/$(PROJ).blif: $(FILES) Makefile # if build folder doesn't exist, create it @@ -29,15 +49,16 @@ $(BUILD)/$(PROJ).blif: $(FILES) Makefile # synthesize using Yosys yosys -p "synth_ice40 -top top -blif $(BUILD)/$(PROJ).blif" $(FILES) -$(BUILD)/$(PROJ).asc: pinmap_$(FOOTPRINT).pcf $(BUILD)/$(PROJ).blif +$(BUILD)/$(PROJ)_$(DEVICE).asc: pinmap_$(FOOTPRINT).pcf $(BUILD)/$(PROJ).blif # Place and route using arachne - arachne-pnr -d $(DEVICE) -P $(FOOTPRINT) -o $(BUILD)/$(PROJ).asc -p pinmap_$(FOOTPRINT).pcf $(BUILD)/$(PROJ).blif + arachne-pnr -d $(DEVICE) -P $(FOOTPRINT) -o $(BUILD)/$(PROJ)_$(DEVICE).asc \ + -p pinmap_$(FOOTPRINT).pcf $(BUILD)/$(PROJ).blif -$(BUILD)/$(PROJ).bin: $(BUILD)/$(PROJ).asc +$(BUILD)/$(PROJ)_$(DEVICE).bin: $(BUILD)/$(PROJ)_$(DEVICE).asc # Convert to bitstream using IcePack - icepack $(BUILD)/$(PROJ).asc $(BUILD)/$(PROJ).bin + icepack $(BUILD)/$(PROJ)_$(DEVICE).asc $(BUILD)/$(PROJ)_$(DEVICE).bin -burn: $(BUILD)/$(PROJ).bin +burn: $(BUILD)/$(PROJ)_$(DEVICE).bin iceprog $< iverilog: a.out @@ -59,5 +80,8 @@ burntest: $(BUILD)/$(PROJ)test.bin run: sudo screen $(STICKTTY) +run2: host + watch -n 0.2 sudo ./host /dev/ttyUSB1 some almost german-like long word + clean: rm -f build/* a.out diff --git a/uart_echo/README.md b/uart_echo/README.md index e6920ff..a3ebcbb 100644 --- a/uart_echo/README.md +++ b/uart_echo/README.md @@ -9,16 +9,30 @@ An important parameter are the number of characters per second to be transmitted, i.e. BAUD. This example sets this to 9600 - which is slow. Under Linux, you may use the following commands to address the FPGA once the -bistream was burnt to it: +bitstream was burnt to it: - * minicom -b 9600 -D /dev/ttyUSB1 # or alternatively - * screen /dev/ttyUSB1 + * sudo minicom -b 9600 -D /dev/ttyUSB1 # or alternatively + * sudo screen /dev/ttyUSB1 -The use of screen may sound surprising to many. To become +If you need the 'sudo' depends on the permissions assigned +to the device. The use of screen may sound surprising to +many. It is a multifunctional tool. To become familar with it is however a very good investment and highly encouraged. Minicom you leave with "CTRL-A x", screen with "CTRL-A d". +Linux users may also run a small C program to perform the +I/O with the device, i.e. to prepare a subsequent embedding +of the device in programms running on the computer. + + * sudo ./host /dev/ttyUSB1 some text + +To evaluate the reliability of the communication, e.g. in a +virtualised environment, we propose to use the here provided +'host' utility repeatedly. The "run2" target of the Makefile +for instance combines it with an invocation of "watch" for a +manual inspection. + The 'uart_echo' example was derived from the only writing example 'uart_transmission' of Paul Martin after an idea from Stefan Ziegenbalg at http://www.ztex.de/firmware-kit/example.e.html. diff --git a/uart_echo/host.c b/uart_echo/host.c new file mode 100644 index 0000000..6622606 --- /dev/null +++ b/uart_echo/host.c @@ -0,0 +1,136 @@ +// Example follows StackOverflow.com +// http://stackoverflow.com/questions/18108932/linux-c-serial-port-reading-writing +// +// Modified by Steffen Moeller, 2016, to work with the iCE40 HX1K + +#include // standard input / output functions +#include +#include // string function definitions +#include // UNIX standard function definitions +#include // File control definitions +#include // Error number definitions +#include // POSIX terminal control definitions + +static const unsigned char cmd[] = "INIT \r"; +static char response[2048]; + +char* const write_and_read(const int device, + char const * const writeme, + char * const readtome) { + + int n_written = 0, + spot_w = 0; + + int n_read = 0, + spot_r = 0; + char buf = '\0'; + + do { + + // Write: + + if (strlen(writeme)>n_written) { + n_written = write( device, writeme+spot_w, 1 ); + fprintf(stderr,"Written: %c\n", *(writeme+spot_w)); + spot_w += n_written; + } + + //It should definitely not be necessary to write byte per byte, + //also int n_written = write( device, cmd, sizeof(cmd) -1) would be nice to work + //It does not, though, our device answers to quickly. + // + // Since this is the echo firmware, and we only sent a single character, + // we also expect to read no more than a single character. + + // Read: + + n_read = read( device, &buf, 1 ); + sprintf( &readtome[spot_r], "%c", buf ); + fprintf(stderr,"Read: %c\n", readtome[spot_r]); + spot_r += n_read; + + if (n_read < 0) { + fprintf(stderr,"Error %d reading: %s\n", errno, strerror(errno)); + } + else if (n_read == 0) { + fprintf(stderr,"Read nothing!\n"); + } + } while (writeme[spot_w] != 0 && n_written > 0); + + readtome[spot_r]=0; + return(readtome); +} + + +char main(int argc, char *argv[]) { + + if (argc < 2 || 0==strcmp("-h",argv[1]) || 0==strcmp("--help",argv[1])) { + printf("Usage: %s some text\n",argv[0]); + exit(0); + } + + // open the device expected to be specified in first argument + + const int USB = open( argv[1], O_RDWR| O_NOCTTY ); + + if (USB<0) { + fprintf(stderr,"Error %d opening %s : %s\n", errno, argv[1], strerror (errno)); + exit(errno); + } + + struct termios tty; + memset (&tty, 0, sizeof tty); + + /* Error Handling */ + if ( tcgetattr ( USB, &tty ) != 0 ) { + fprintf(stderr, "Error %d from tcgetattr: %s\n", errno, strerror(errno)); + exit(errno); + } + + /* Set Baud Rate */ + int ospeed = cfsetospeed (&tty, (speed_t)B9600); + int ispeed = cfsetispeed (&tty, (speed_t)B9600); + // This is seemingly a bug in the man page - those routines return 0, no the speed + //fprintf(stderr,"Set speeds\n input: %d\n output: %d\n",ispeed,ospeed); + + /* Setting other Port Stuff */ + tty.c_cflag &= ~PARENB; // Make 8n1 + tty.c_cflag &= ~CSTOPB; + tty.c_cflag &= ~CSIZE; + tty.c_cflag |= CS8; + + tty.c_cflag &= ~CRTSCTS; // no flow control + tty.c_cc[VMIN] = 1; // read doesn't block + tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout + tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines + + /* Make raw */ + cfmakeraw(&tty); + + /* Flush Port, then applies attributes */ + if (0 != tcflush( USB, TCIFLUSH )) { + fprintf(stderr, "Error %d from tcflush: %s\n", errno, strerror(errno)); + exit(errno); + } + + if ( tcsetattr ( USB, TCSANOW, &tty ) != 0) { + fprintf(stderr, "Error %d from tcsetattr: %s\n", errno, strerror(errno)); + exit(errno); + } + + if (2 >= argc) { + // nothing to write specified by user + write_and_read(USB,cmd,response); + printf("Response: %s\n",response); + } else { + // iterating over all arguments provided + for(int a=2; a Date: Tue, 9 Aug 2016 16:20:20 +0200 Subject: [PATCH 05/10] Also remove core dumps upon clean --- uart_echo/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uart_echo/Makefile b/uart_echo/Makefile index 3a9b4b1..2018dda 100644 --- a/uart_echo/Makefile +++ b/uart_echo/Makefile @@ -84,4 +84,4 @@ run2: host watch -n 0.2 sudo ./host /dev/ttyUSB1 some almost german-like long word clean: - rm -f build/* a.out + rm -f build/* a.out core From 1b06c1b0fabbac7ff2640e0152666a73925d9c32 Mon Sep 17 00:00:00 2001 From: Steffen Moeller Date: Tue, 9 Aug 2016 18:14:12 +0200 Subject: [PATCH 06/10] Makefile - reintroduced omitted DEVICE name in binary --- uart_echo/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uart_echo/Makefile b/uart_echo/Makefile index 2018dda..1406a45 100644 --- a/uart_echo/Makefile +++ b/uart_echo/Makefile @@ -36,7 +36,7 @@ FILEStest += uart_clock_top.v .PHONY: all clean burn -all:$(BUILD)/$(PROJ).bin host +all:$(BUILD)/$(PROJ)_$(DEVICE).bin host CFLAGS += -g From 6310293d1e0757550ba6eceb5fa1eac825b1b813 Mon Sep 17 00:00:00 2001 From: Steffen Moeller Date: Wed, 10 Aug 2016 15:36:22 +0200 Subject: [PATCH 07/10] Give iverilog test file a name --- uart_echo/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/uart_echo/Makefile b/uart_echo/Makefile index 1406a45..763fa25 100644 --- a/uart_echo/Makefile +++ b/uart_echo/Makefile @@ -61,9 +61,9 @@ $(BUILD)/$(PROJ)_$(DEVICE).bin: $(BUILD)/$(PROJ)_$(DEVICE).asc burn: $(BUILD)/$(PROJ)_$(DEVICE).bin iceprog $< -iverilog: a.out -a.out: $(FILES) - iverilog $(FILES) +iverilog: $(BUILD)/$(PROJ).iverilog +$(BUILD)/$(PROJ).iverilog: $(FILES) + iverilog -o $(BUILD)/$(PROJ).iverilog $(FILES) test: $(BUILD)/$(PROJ)test.bin From 93bcd6b8dce53d802a0f064d5cdb33bfcd37bdfd Mon Sep 17 00:00:00 2001 From: Steffen Moeller Date: Wed, 10 Aug 2016 15:58:22 +0200 Subject: [PATCH 08/10] Clock created in uart_rx --- uart_echo/top.v | 16 ++++------------ uart_echo/uart_clock_top.v | 6 ++++-- uart_echo/uart_rx.v | 17 +++++++++++++++-- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/uart_echo/top.v b/uart_echo/top.v index 8c4b800..7199a51 100644 --- a/uart_echo/top.v +++ b/uart_echo/top.v @@ -26,6 +26,8 @@ module top ( reg ledval3 = 0; reg ledval4 = 0; + wire clk_9600; // takes the clock triggeres generated in read + // wire[1:0] state; /* @@ -33,21 +35,11 @@ module top ( assign led4 = ~state[0]; */ - // 9600 Hz clock generation (from 12 MHz) - parameter period_9600 = 32'd625; - wire clk_9600; - reg clk_9600_reset=0; - uart_clock clock_9600 ( - .hwclk(hwclk), - .reset(clk_9600_reset), - .period(period_9600), - .clk(clk_9600) - ); - // UART receiver module designed for // 8 bits, no parity, 1 stop bit. uart_rx_8n1 receiver ( - .clk (clk_9600), // 9600 baud rate clock + .hwclk (hwclk), + .clk_9600 (clk_9600), // 9600 baud rate clock, triggered by reads from host .rx (rx), // input UART rx pin .recvdata (uart_receive), // allow any incoming bytes .rxbyte (uart_rxbyte), // byte received diff --git a/uart_echo/uart_clock_top.v b/uart_echo/uart_clock_top.v index ca34918..6905ce5 100644 --- a/uart_echo/uart_clock_top.v +++ b/uart_echo/uart_clock_top.v @@ -15,9 +15,11 @@ module uart_clock_top ( .hwclk(hwclk), .reset(clk_1_reset), .period(period_1), - .clk(clk_1), -// .led(led3) + .clk(clk_1) +// , .led(led1) ); assign led4 = ~clk_1; + assign led3 = clk_1_reset; + assign led2 = ~clk_1_reset; endmodule diff --git a/uart_echo/uart_rx.v b/uart_echo/uart_rx.v index 7e36b7d..faa5590 100644 --- a/uart_echo/uart_rx.v +++ b/uart_echo/uart_rx.v @@ -1,7 +1,8 @@ // 8N1 UART Module, transmit only module uart_rx_8n1 ( - input wire clk, // input clock + input wire hwclk, // input clock + output wire clk_9600, // self-generated clock input wire rx, // rx wire input wire recvdata, // allow any bytes to come in output reg[7:0] rxbyte, // incoming byte as output @@ -22,8 +23,20 @@ module uart_rx_8n1 ( //assign stateOut=state; + // 9600 Hz clock generation (from 12 MHz) + parameter period_9600 = 32'd625; + wire clk_9600_reset=0; + uart_clock clock_9600 ( + .hwclk(hwclk), + .reset(clk_9600_reset), + .period(period_9600), + .clk(clk_9600) + ); + + assign clk_9600_reset = ~rx; // whenever rx falls, start counting from 0 + /* always */ - always @ (posedge clk) begin + always @ (posedge clk_9600) begin case (state) From aa7c8ba5fb3e9b7c474bf78c2aaf08c4bbb740b2 Mon Sep 17 00:00:00 2001 From: Steffen Moeller Date: Wed, 17 Aug 2016 15:30:01 +0200 Subject: [PATCH 09/10] Emperically correcting clock period to 32'd624 --- uart_echo/uart_rx.v | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uart_echo/uart_rx.v b/uart_echo/uart_rx.v index faa5590..2b6a81d 100644 --- a/uart_echo/uart_rx.v +++ b/uart_echo/uart_rx.v @@ -24,7 +24,7 @@ module uart_rx_8n1 ( //assign stateOut=state; // 9600 Hz clock generation (from 12 MHz) - parameter period_9600 = 32'd625; + parameter period_9600 = 32'd624; wire clk_9600_reset=0; uart_clock clock_9600 ( .hwclk(hwclk), From d9b7a0d26c793b061bd0f58dfcc9c809623dbad8 Mon Sep 17 00:00:00 2001 From: Steffen Moeller Date: Wed, 17 Aug 2016 16:31:19 +0200 Subject: [PATCH 10/10] Ignore a.out files --- uart_echo/.gitignore | 1 + uart_echo/Makefile | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/uart_echo/.gitignore b/uart_echo/.gitignore index 900ccbb..f5df561 100644 --- a/uart_echo/.gitignore +++ b/uart_echo/.gitignore @@ -1,3 +1,4 @@ build/* core +a.out host diff --git a/uart_echo/Makefile b/uart_echo/Makefile index 763fa25..5c92987 100644 --- a/uart_echo/Makefile +++ b/uart_echo/Makefile @@ -68,7 +68,7 @@ $(BUILD)/$(PROJ).iverilog: $(FILES) test: $(BUILD)/$(PROJ)test.bin $(BUILD)/$(PROJ)test.bin: Makefile $(FILEStest) - iverilog $(FILEStest) + iverilog -o $(BUILD)/test.a.out $(FILEStest) mkdir -p $(BUILD) yosys -p "synth_ice40 -top uart_clock_top -blif $(BUILD)/$(PROJ)test.blif" $(FILEStest) arachne-pnr -d $(DEVICE) -P $(FOOTPRINT) -o $(BUILD)/$(PROJ)test.asc -p pinmap_$(FOOTPRINT).pcf $(BUILD)/$(PROJ)test.blif