Improve icestick rs232demo example

Signed-off-by: Clifford Wolf <clifford@clifford.at>
diff --git a/examples/icestick/Makefile b/examples/icestick/Makefile
index 8b8e741..58f26b9 100644
--- a/examples/icestick/Makefile
+++ b/examples/icestick/Makefile
@@ -34,6 +34,10 @@
 %_syntb.vcd: %_syntb
 	vvp -N $< +vcd=$@
 
+sim: $(PROJ)_tb.vcd
+
+postsim: $(PROJ)_syntb.vcd
+
 prog: $(PROJ).bin
 	iceprog $<
 
diff --git a/examples/icestick/rs232demo.v b/examples/icestick/rs232demo.v
index 40347e8..9f66f97 100644
--- a/examples/icestick/rs232demo.v
+++ b/examples/icestick/rs232demo.v
@@ -1,17 +1,59 @@
+// A simple design demonstrating receiving and sending of RS232 signals
+//
+// With this design loaded, connect with a serial terminal to the USB serial
+// port of the icestick (with 9600 BAUD) and use the number keys 1..5 to toggle
+// the LEDs.
+
 module top (
 	input  clk,
 	input  RX,
 	output TX,
+	output LED1,
+	output LED2,
+	output LED3,
+	output LED4,
+	output LED5
+);
+	parameter integer BAUD_RATE = 9600;
+	parameter integer CLOCK_FREQ_HZ = 12000000;
+	localparam integer PERIOD = CLOCK_FREQ_HZ / BAUD_RATE;
+
+	rs232_recv #(
+		.HALF_PERIOD(PERIOD / 2)
+	) recv (
+		.clk  (clk ),
+		.RX   (RX  ),
+		.LED1 (LED1),
+		.LED2 (LED2),
+		.LED3 (LED3),
+		.LED4 (LED4),
+		.LED5 (LED5)
+	);
+
+	rs232_send #(
+		.PERIOD(PERIOD)
+	) send (
+		.clk  (clk ),
+		.TX   (TX  ),
+		.LED1 (LED1),
+		.LED2 (LED2),
+		.LED3 (LED3),
+		.LED4 (LED4),
+		.LED5 (LED5)
+	);
+endmodule
+
+module rs232_recv #(
+	parameter integer HALF_PERIOD = 5
+) (
+	input  clk,
+	input  RX,
 	output reg LED1,
 	output reg LED2,
 	output reg LED3,
 	output reg LED4,
 	output reg LED5
 );
-	parameter integer BAUD_RATE = 9600;
-	parameter integer CLOCK_FREQ_HZ = 12000000;
-	localparam integer HALF_PERIOD = CLOCK_FREQ_HZ / (2 * BAUD_RATE);
-
 	reg [7:0] buffer;
 	reg buffer_valid;
 
@@ -20,11 +62,11 @@
 	reg recv = 0;
 
 	initial begin
-		LED1 = 0;
+		LED1 = 1;
 		LED2 = 0;
-		LED3 = 0;
+		LED3 = 1;
 		LED4 = 0;
-		LED5 = 0;
+		LED5 = 1;
 	end
 
 	always @(posedge clk) begin
@@ -60,6 +102,72 @@
 			if (buffer == "5") LED5 <= !LED5;
 		end
 	end
+endmodule
 
-	assign TX = RX;
+module rs232_send #(
+	parameter integer PERIOD = 10
+) (
+	input  clk,
+	output TX,
+	input  LED1,
+	input  LED2,
+	input  LED3,
+	input  LED4,
+	input  LED5
+);
+	reg [7:0] buffer;
+	reg buffer_valid;
+
+	reg [$clog2(PERIOD):0] cycle_cnt = 0;
+	reg [4:0] bit_cnt = 0;
+	reg [5:0] byte_cnt = 60;
+
+	always @(posedge clk) begin
+		cycle_cnt <= cycle_cnt + 1;
+		if (cycle_cnt == PERIOD-1) begin
+			cycle_cnt <= 0;
+			bit_cnt <= bit_cnt + 1;
+			if (bit_cnt == 10) begin
+				bit_cnt <= 0;
+				byte_cnt <= byte_cnt + 1;
+			end
+		end
+	end
+
+	reg [7:0] data_byte;
+	reg data_bit;
+
+	always @* begin
+		data_byte = 'bx;
+		case (byte_cnt)
+			0: data_byte <= "\r";
+			1: data_byte <= LED1 ? "*" : "-";
+			2: data_byte <= LED2 ? "*" : "-";
+			3: data_byte <= LED3 ? "*" : "-";
+			4: data_byte <= LED4 ? "*" : "-";
+			5: data_byte <= LED5 ? "*" : "-";
+		endcase
+	end
+
+	always @(posedge clk) begin
+		data_bit = 'bx;
+		case (bit_cnt)
+			0: data_bit <= 0; // start bit
+			1: data_bit <= data_byte[0];
+			2: data_bit <= data_byte[1];
+			3: data_bit <= data_byte[2];
+			4: data_bit <= data_byte[3];
+			5: data_bit <= data_byte[4];
+			6: data_bit <= data_byte[5];
+			7: data_bit <= data_byte[6];
+			8: data_bit <= data_byte[7];
+			9: data_bit <= 1;  // stop bit
+			10: data_bit <= 1; // stop bit
+		endcase
+		if (byte_cnt > 5) begin
+			data_bit <= 1;
+		end
+	end
+
+	assign TX = data_bit;
 endmodule
diff --git a/examples/icestick/rs232demo_tb.v b/examples/icestick/rs232demo_tb.v
index 5b9aee1..fd3a0cf 100644
--- a/examples/icestick/rs232demo_tb.v
+++ b/examples/icestick/rs232demo_tb.v
@@ -53,6 +53,11 @@
 
 		repeat (10 * PERIOD) @(posedge clk);
 
+		// turn all LEDs off
+		send_byte("1");
+		send_byte("3");
+		send_byte("5");
+
 		// turn all LEDs on
 		send_byte("1");
 		send_byte("2");