mirror of https://github.com/YosysHQ/icestorm.git
174 lines
3.2 KiB
Verilog
174 lines
3.2 KiB
Verilog
// 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
|
|
);
|
|
reg [7:0] buffer;
|
|
reg buffer_valid;
|
|
|
|
reg [$clog2(3*HALF_PERIOD):0] cycle_cnt;
|
|
reg [3:0] bit_cnt = 0;
|
|
reg recv = 0;
|
|
|
|
initial begin
|
|
LED1 = 1;
|
|
LED2 = 0;
|
|
LED3 = 1;
|
|
LED4 = 0;
|
|
LED5 = 1;
|
|
end
|
|
|
|
always @(posedge clk) begin
|
|
buffer_valid <= 0;
|
|
if (!recv) begin
|
|
if (!RX) begin
|
|
cycle_cnt <= HALF_PERIOD;
|
|
bit_cnt <= 0;
|
|
recv <= 1;
|
|
end
|
|
end else begin
|
|
if (cycle_cnt == 2*HALF_PERIOD) begin
|
|
cycle_cnt <= 0;
|
|
bit_cnt <= bit_cnt + 1;
|
|
if (bit_cnt == 9) begin
|
|
buffer_valid <= 1;
|
|
recv <= 0;
|
|
end else begin
|
|
buffer <= {RX, buffer[7:1]};
|
|
end
|
|
end else begin
|
|
cycle_cnt <= cycle_cnt + 1;
|
|
end
|
|
end
|
|
end
|
|
|
|
always @(posedge clk) begin
|
|
if (buffer_valid) begin
|
|
if (buffer == "1") LED1 <= !LED1;
|
|
if (buffer == "2") LED2 <= !LED2;
|
|
if (buffer == "3") LED3 <= !LED3;
|
|
if (buffer == "4") LED4 <= !LED4;
|
|
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 = data_bit;
|
|
endmodule
|