Skip to content

Commit

Permalink
Merge pull request #33 from hasheddan/uart-rx
Browse files Browse the repository at this point in the history
Add UART receiving module
  • Loading branch information
hasheddan authored Sep 25, 2022
2 parents 5a211d9 + 45e9607 commit 6ae2245
Show file tree
Hide file tree
Showing 7 changed files with 266 additions and 40 deletions.
35 changes: 35 additions & 0 deletions docs/dev/serial.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Connecting Over Serial Port

The `moss` UART can be used to send information between the system and the host
machine. There are a variety of utilities that can be used to connect over
serial port.

## Screen

```
screen /dev/ttyUSB1 9600
```

Kill screen:
```
CTRL+a k
```

## Minicom

Minicom can be configured using `minirc` files. The following configuration file
supports communicating with `moss`:

`minirc.moss`
```
# Machine-generated file - use "minicom -s" to change parameters.
pu port /dev/ttyUSB1
pu baudrate 9600
pu rtscts No
```

## xxd

```
xxd -b < /dev/ttyUSB1
```
65 changes: 65 additions & 0 deletions docs/dev/verilator.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Verilator

## Resources

- [Verilator Website](https://www.veripool.org/verilator/)
- [It's Embedded: Introduction to
Verilator](https://www.itsembedded.com/dhd/verilator_1/)

## Overview

Verilator is a tool that translates Verilog into a C++ model that can be invoked
to simulate the RTL design.

## Configuration

Verilator supports a large number of flags and configuration values. Those used
in `moss` are detailed below.

- `-Wall`: turns on all Verilator linter warnings
- `--cc`: specifies that we want C++ output
- `--exe`: specifies that we want a executable rather than just a library
- `--build`: instructs Verilator to build library or executable (calls `make` on
the Makefiles it generates)
- `--trace`: enables waveform creation
- `-I<dir>`: add directory to the list that Verilator searches for RTL

## Data Types

Verilator defines packed data types to represent signals in a module.

`verilated.h`
```c++
// Basic types

// P // Packed data of bit type (C/S/I/Q/W)
typedef vluint8_t CData; ///< Verilated pack data, 1-8 bits
typedef vluint16_t SData; ///< Verilated pack data, 9-16 bits
typedef vluint32_t IData; ///< Verilated pack data, 17-32 bits
typedef vluint64_t QData; ///< Verilated pack data, 33-64 bits
typedef vluint32_t EData; ///< Verilated pack element of WData array
typedef EData WData; ///< Verilated pack data, >64 bits, as an array
// float F // No typedef needed; Verilator uses float
// double D // No typedef needed; Verilator uses double
// string N // No typedef needed; Verilator uses string

typedef const WData* WDataInP; ///< Array input to a function
typedef WData* WDataOutP; ///< Array output from a function

typedef void (*VerilatedVoidCb)(void);
```
```c++
# define VL_OUT8(name, msb,lsb) CData name ///< Declare output signal, 1-8 bits
# define VL_OUT16(name, msb,lsb) SData name ///< Declare output signal, 9-16 bits
# define VL_OUT64(name, msb,lsb) QData name ///< Declare output signal, 33-64bits
# define VL_OUT(name, msb,lsb) IData name ///< Declare output signal, 17-32 bits
# define VL_OUTW(name, msb,lsb, words) WData name[words] ///< Declare output signal, 65+ bits
```

For example, `moss` controls LEDs on the Arty A7 using one signal per LED. These
are defined as a `wire` with width 4 (i.e. `[3:0]led`). Verilator represents
these signals using the `CData` type, with bits in each position corresponding
to the index in the `wire`.

The variable is declared using the `VL_OUT8(name, mdb,lsb)` macro, which
instantiates a variable with name `name` and type `CData`.
11 changes: 8 additions & 3 deletions rtl/top.v
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@ limitations under the License.

module top(
input clk,
input [1:0]sw,
output uart_rxd_out
input uart_txd_in,
output uart_rxd_out,
output [1:0]led
);

uart_tx uart_tx(.clk(clk), .send(sw[0]), .reset(sw[1]), .out(uart_rxd_out));
wire [7:0] data;
wire send;

uart_rx uart_rx(.clk(clk), .in(uart_txd_in), .notif(led[0]), .data(data), .send(send));
uart_tx uart_tx(.clk(clk), .send(send), .data(data), .notif(led[1]), .out(uart_rxd_out));

endmodule
128 changes: 128 additions & 0 deletions rtl/uart_rx.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
Copyright 2020 The Moss Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

`timescale 1ns / 1ps

module uart_rx(
input clk,
input in,
// NOTE(hasheddan): the outputs below are declared as registers, which is
// essentially shorthand for instaniating a register and assigning the wire
// to it on every clock cycle.
// See https://stackoverflow.com/a/5360623
output reg notif,
output reg [7:0] data,
output reg send
);

reg [2:0] state;

// states
localparam s_idle = 3'b000;
localparam s_start_bit = 3'b001;
localparam s_data_bit = 3'b010;
localparam s_stop_bit = 3'b011;
localparam s_cleanup = 3'b100;

// clock cycles per bit transmitted
// 100000000 / 9600 ~= 10416
parameter cycles = 10416;

integer clock_count = 0;
integer bit_index = 7;

always @(posedge clk) begin
case (state)
s_idle:
begin
notif <= 1'b0;
send <= 1'b0;
if (in == 1'b0)
begin
state <= s_start_bit;
end
else
begin
state <= s_idle;
end
end
s_start_bit:
begin
notif <= 1'b1;
send <= 1'b0;
if (clock_count < (cycles-1 / 2))
begin
clock_count <= clock_count+1;
state <= s_start_bit;
end
else
begin
clock_count <= 0;
state <= s_data_bit;
end
end
s_data_bit:
begin
notif <= 1'b1;
send <= 1'b0;
data[bit_index] <= in;
if (clock_count < cycles-1)
begin
clock_count <= clock_count+1;
state <= s_data_bit;
end
else
begin
clock_count <= 0;
if (bit_index > 0)
begin
bit_index <= bit_index-1;
state <= s_data_bit;
end
else
begin
bit_index <= 7;
state <= s_stop_bit;
end
end
end
s_stop_bit:
begin
notif <= 1'b1;
send <= 1'b0;
if (clock_count < cycles-1)
begin
clock_count <= clock_count+1;
state <= s_stop_bit;
end
else
begin
clock_count <= 0;
state <= s_cleanup;
end
end
s_cleanup:
begin
notif <= 1'b1;
// Assert send after data has been read.
send <= 1'b1;
state <= s_idle;
end
default:
state <= s_idle;
endcase
end
endmodule
38 changes: 12 additions & 26 deletions rtl/uart_tx.v
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ limitations under the License.
module uart_tx(
input clk,
input send,
input reset,
input [7:0] data,
output reg notif,
output reg out
);

Expand All @@ -37,40 +38,28 @@ module uart_tx(
parameter cycles = 10416;

integer clock_count = 0;
integer word_index = 247;
integer bit_index = 7;
reg [8*31-1:0] tx_data = "Welcome to the Moss Computer!\r\n";
reg stop = 1'b0;

always @(posedge clk) begin
case (state)
s_idle:
begin
notif <= 1'b0;
out <= 1'b1;
if (clock_count < cycles-1)
begin
clock_count <= clock_count+1;
state <= s_idle;
end
else
if (send == 1'b1)
begin
clock_count <= 0;
bit_index <= 7;
state <= s_data_bit;
if (reset)
begin
stop <= 1'b0;
end
if (send == 1'b1 && !stop)
begin
state <= s_start_bit;
end
else
state <= s_idle;
begin
state <= s_idle;
end
end
s_start_bit:
begin
notif <= 1'b1;
out <= 1'b0;
if (clock_count < cycles-1)
begin
Expand All @@ -85,7 +74,8 @@ module uart_tx(
end
s_data_bit:
begin
out <= tx_data[word_index-bit_index];
notif <= 1'b1;
out <= data[bit_index];
if (clock_count < cycles-1)
begin
clock_count <= clock_count+1;
Expand All @@ -102,14 +92,13 @@ module uart_tx(
else
begin
bit_index <= 7;
word_index <= word_index-8;
state <= s_stop_bit;
end
end
end
//
s_stop_bit:
begin
notif <= 1'b1;
out <= 1'b1;
if (clock_count < cycles-1)
begin
Expand All @@ -124,11 +113,8 @@ module uart_tx(
end
s_cleanup:
begin
if (word_index < 7)
begin
word_index <= 247;
stop <= 1'b1;
end
notif <= 1'b1;
out <= 1'b1;
state <= s_idle;
end
default:
Expand Down
22 changes: 11 additions & 11 deletions toolchain/vivado/boards/xc7a35ticsg324-1l/xc7a35ticsg324-1l.xdc
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { clk }]
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports { clk }];

## Switches
set_property -dict { PACKAGE_PIN A8 IOSTANDARD LVCMOS33 } [get_ports { sw[0] }]; #IO_L12N_T1_MRCC_16 Sch=sw[0]
set_property -dict { PACKAGE_PIN C11 IOSTANDARD LVCMOS33 } [get_ports { sw[1] }]; #IO_L13P_T2_MRCC_16 Sch=sw[1]
set_property -dict { PACKAGE_PIN C10 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L13N_T2_MRCC_16 Sch=sw[2]
set_property -dict { PACKAGE_PIN A10 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L14P_T2_SRCC_16 Sch=sw[3]
#set_property -dict { PACKAGE_PIN A8 IOSTANDARD LVCMOS33 } [get_ports { sw[0] }]; #IO_L12N_T1_MRCC_16 Sch=sw[0]
#set_property -dict { PACKAGE_PIN C11 IOSTANDARD LVCMOS33 } [get_ports { sw[1] }]; #IO_L13P_T2_MRCC_16 Sch=sw[1]
#set_property -dict { PACKAGE_PIN C10 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L13N_T2_MRCC_16 Sch=sw[2]
#set_property -dict { PACKAGE_PIN A10 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L14P_T2_SRCC_16 Sch=sw[3]

## RGB LEDs
#set_property -dict { PACKAGE_PIN E1 IOSTANDARD LVCMOS33 } [get_ports { led0_b }]; #IO_L18N_T2_35 Sch=led0_b
Expand All @@ -32,14 +32,14 @@ set_property -dict { PACKAGE_PIN A10 IOSTANDARD LVCMOS33 } [get_ports { sw[3]
## LEDs
set_property -dict { PACKAGE_PIN H5 IOSTANDARD LVCMOS33 } [get_ports { led[0] }]; #IO_L24N_T3_35 Sch=led[4]
set_property -dict { PACKAGE_PIN J5 IOSTANDARD LVCMOS33 } [get_ports { led[1] }]; #IO_25_35 Sch=led[5]
set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { led[2] }]; #IO_L24P_T3_A01_D17_14 Sch=led[6]
set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { led[3] }]; #IO_L24N_T3_A00_D16_14 Sch=led[7]
#set_property -dict { PACKAGE_PIN T9 IOSTANDARD LVCMOS33 } [get_ports { led[2] }]; #IO_L24P_T3_A01_D17_14 Sch=led[6]
#set_property -dict { PACKAGE_PIN T10 IOSTANDARD LVCMOS33 } [get_ports { led[3] }]; #IO_L24N_T3_A00_D16_14 Sch=led[7]

## Buttons
set_property -dict { PACKAGE_PIN D9 IOSTANDARD LVCMOS33 } [get_ports { btn[0] }]; #IO_L6N_T0_VREF_16 Sch=btn[0]
set_property -dict { PACKAGE_PIN C9 IOSTANDARD LVCMOS33 } [get_ports { btn[1] }]; #IO_L11P_T1_SRCC_16 Sch=btn[1]
set_property -dict { PACKAGE_PIN B9 IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; #IO_L11N_T1_SRCC_16 Sch=btn[2]
set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L12P_T1_MRCC_16 Sch=btn[3]
#set_property -dict { PACKAGE_PIN D9 IOSTANDARD LVCMOS33 } [get_ports { btn[0] }]; #IO_L6N_T0_VREF_16 Sch=btn[0]
#set_property -dict { PACKAGE_PIN C9 IOSTANDARD LVCMOS33 } [get_ports { btn[1] }]; #IO_L11P_T1_SRCC_16 Sch=btn[1]
#set_property -dict { PACKAGE_PIN B9 IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; #IO_L11N_T1_SRCC_16 Sch=btn[2]
#set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L12P_T1_MRCC_16 Sch=btn[3]

## Pmod Header JA
#set_property -dict { PACKAGE_PIN G13 IOSTANDARD LVCMOS33 } [get_ports { ja[0] }]; #IO_0_15 Sch=ja[1]
Expand Down Expand Up @@ -83,7 +83,7 @@ set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { btn[3]

## USB-UART Interface
set_property -dict { PACKAGE_PIN D10 IOSTANDARD LVCMOS33 } [get_ports { uart_rxd_out }]; #IO_L19N_T3_VREF_16 Sch=uart_rxd_out
#set_property -dict { PACKAGE_PIN A9 IOSTANDARD LVCMOS33 } [get_ports { uart_txd_in }]; #IO_L14N_T2_SRCC_16 Sch=uart_txd_in
set_property -dict { PACKAGE_PIN A9 IOSTANDARD LVCMOS33 } [get_ports { uart_txd_in }]; #IO_L14N_T2_SRCC_16 Sch=uart_txd_in

## ChipKit Outer Digital Header
#set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { ck_io0 }]; #IO_L16P_T2_CSI_B_14 Sch=ck_io[0]
Expand Down
Loading

0 comments on commit 6ae2245

Please sign in to comment.