Improve icestick rs232demo example

Signed-off-by: Clifford Wolf <clifford@clifford.at>
This commit is contained in:
Clifford Wolf 2019-02-14 02:45:25 +01:00
parent c0cbae88ab
commit faf21ffd9f
3 changed files with 126 additions and 9 deletions

View File

@ -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 $<

View File

@ -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
assign TX = RX;
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 = data_bit;
endmodule

View File

@ -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");