blob: 206b9ebec997f073fc42af11e97ffa56dba1e1a0 [file] [log] [blame]
// SPDX-License-Identifier: Apache-2.0
`default_nettype none
/*
* PicoSoC - A simple example SoC using PicoRV32
*
* Copyright (C) 2017 Clifford Wolf <clifford@clifford.at>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
`timescale 1 ns / 1 ps
/* tbuart --- mimic an external UART display, operating at 9600 baud */
/* and accepting ASCII characters for display. */
/* To do: Match a known UART 3.3V 16x2 LCD display. However, it */
/* should be possible on a testing system to interface to the UART */
/* pins on a Raspberry Pi, also running at 3.3V. */
module tbuart (
input ser_rx
);
reg [3:0] recv_state;
reg [2:0] recv_divcnt;
reg [7:0] recv_pattern;
reg [8*50-1:0] recv_buf_data; // 50 characters. Increase as needed for tests.
reg clk;
initial begin
clk <= 1'b0;
recv_state <= 0;
recv_divcnt <= 0;
recv_pattern <= 0;
recv_buf_data <= 0;
end
// NOTE: Running at 3.0us clock period @ 5 clocks per bit = 15.0us per
// bit ~= 64 kbaud. Not tuned to any particular UART. Most run at
// 9600 baud default and will bounce up to higher baud rates when
// passed specific command words.
always #1500 clk <= (clk === 1'b0);
always @(posedge clk) begin
recv_divcnt <= recv_divcnt + 1;
case (recv_state)
0: begin
if (!ser_rx)
recv_state <= 1;
recv_divcnt <= 0;
end
1: begin
if (2*recv_divcnt > 3'd3) begin
recv_state <= 2;
recv_divcnt <= 0;
end
end
10: begin
if (recv_divcnt > 3'd3) begin
// 0x0a = '\n'
if (recv_pattern == 8'h0a) begin
$display("output: %s", recv_buf_data);
end else begin
recv_buf_data <= {recv_buf_data, recv_pattern};
end
recv_state <= 0;
end
end
default: begin
if (recv_divcnt > 3'd3) begin
recv_pattern <= {ser_rx, recv_pattern[7:1]};
recv_state <= recv_state + 1;
recv_divcnt <= 0;
end
end
endcase
end
endmodule