From faf21ffd9fa419621581202c1dd309d2ed21bfbd Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 14 Feb 2019 02:45:25 +0100 Subject: Improve icestick rs232demo example Signed-off-by: Clifford Wolf --- examples/icestick/Makefile | 4 ++ examples/icestick/rs232demo.v | 124 ++++++++++++++++++++++++++++++++++++--- examples/icestick/rs232demo_tb.v | 5 ++ 3 files changed, 125 insertions(+), 8 deletions(-) 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 @@ all: $(PROJ).rpt $(PROJ).bin %_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 @@ module top ( 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 @@ module top ( if (buffer == "5") LED5 <= !LED5; end end +endmodule + +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 = RX; + 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 @@ module testbench; 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"); -- cgit v1.2.3