-
Notifications
You must be signed in to change notification settings - Fork 88
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
examples/ulx3s: serial port demo #80
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
d0db959
examples/ulx3s: add serial uart demo
osresearch 6e1d4e7
examples/ul3xs: make the makefile rules more general to support multi…
osresearch 89bb397
examples/ulx3s: enable rx uart, although it does not receive any data
osresearch 3b93044
examples/ulx3s: include scanlime MIT license header, fix clock crossi…
osresearch b88e522
examples/ulx3s: Use LPF file for pin assignments and remove sudo
osresearch 4408290
examples/ulx3s: Update blinky to use LPF
osresearch ccce3a4
ignore dependency and log files
osresearch 2da96e4
examples/ulx3s: include generated dependency files
osresearch 546dec7
examples/ulx3s: make clean target
osresearch d1c3805
Merge branch 'master' into ulx3s-serial
osresearch 5c2fbaf
examples/ulx3s: use the new -n parameter to ecppll to name the verilo…
osresearch 5ebd691
examples/ulx3s: merge tx/rx uart and fix ordering of pll outputs from…
osresearch File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,3 +7,6 @@ ispTcl.tcl | |
ispTcl.tcl.* | ||
.ispTcl.lock | ||
work_*/ | ||
.*.d | ||
.*.swp | ||
*.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,40 @@ | ||
all: blinky.bit | ||
all: blinky.bit hello.bit | ||
|
||
blinky.json: blinky.v | ||
yosys -p "synth_ecp5 -json blinky.json" blinky.v | ||
hello.json: pll_120.v | ||
|
||
blinky_out.config: blinky.json | ||
nextpnr-ecp5 --json blinky.json --textcfg blinky_out.config --45k | ||
IDCODE ?= 0x21111043 # 12f | ||
|
||
blinky.bit: blinky_out.config | ||
ecppack blinky_out.config blinky.bit | ||
%.json: %.v | ||
yosys \ | ||
-p "synth_ecp5 -json $@" \ | ||
-E .$(basename $@).d \ | ||
$< | ||
|
||
%.config: %.json | ||
nextpnr-ecp5 \ | ||
--json $< \ | ||
--textcfg $@ \ | ||
--lpf ulx3s_v20.lpf \ | ||
--25k | ||
|
||
%.bit: %.config | ||
ecppack --idcode $(IDCODE) $< $@ | ||
|
||
%.svf: %.config | ||
ecppack --idcode $(IDCODE) --input $< --svf $@ | ||
|
||
%.flash: %.bit | ||
ujprog $< | ||
%.terminal: %.bit | ||
ujprog -t -b 3000000 $< | ||
|
||
pll_%.v: | ||
../../libtrellis/ecppll \ | ||
-i 25 \ | ||
-o $(subst pll_,,$(basename $@)) \ | ||
-n $(basename $@) \ | ||
-f $@ | ||
|
||
clean: | ||
$(RM) *.config *.bit .*.d *.svf | ||
-include .*.d |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* | ||
* Hello world on the ulx3s FTDI serial port at 3000000 baud. | ||
*/ | ||
`default_nettype none | ||
`include "uart.v" | ||
`include "pll_120.v" | ||
|
||
module top( | ||
input clk_25mhz, | ||
output [7:0] led, | ||
output wifi_gpio0, | ||
input ftdi_txd, // from the ftdi chip | ||
output ftdi_rxd, // to the ftdi chip | ||
); | ||
// gpio0 must be tied high to prevent board from rebooting | ||
assign wifi_gpio0 = 1; | ||
|
||
reg [7:0] led_reg; | ||
assign led = led_reg; | ||
|
||
// Generate a 120 MHz clock from the 25 MHz reference | ||
wire clk, locked, reset = !locked; | ||
pll_120 pll_120_i(clk_25mhz, clk, locked); | ||
|
||
// send/recv data at on the FTDI port | ||
// 120 MHz / 40 == 3 megabaud | ||
wire uart_txd_ready; | ||
reg [7:0] uart_txd; | ||
reg uart_txd_strobe; | ||
wire uart_rxd_strobe; | ||
wire [7:0] uart_rxd; | ||
|
||
uart #(.DIVISOR(40)) uart_i( | ||
.clk(clk), | ||
.reset(reset), | ||
// physical interface | ||
.serial_txd(ftdi_rxd), // fpga --> ftdi | ||
.serial_rxd(ftdi_txd), // fpga <-- ftdi | ||
// logical interface | ||
.txd(uart_txd), | ||
.txd_ready(uart_txd_ready), | ||
.txd_strobe(uart_txd_strobe), | ||
.rxd(uart_rxd), | ||
.rxd_strobe(uart_rxd_strobe), | ||
); | ||
|
||
reg [31:0] counter; | ||
|
||
always @(posedge clk) | ||
begin | ||
uart_txd_strobe <= 0; | ||
counter <= counter + 1; | ||
|
||
if (reset) begin | ||
counter <= 0; | ||
end else | ||
if (uart_rxd_strobe) | ||
begin | ||
// echo any input on the serial port back to the serial port | ||
led_reg <= uart_rxd; | ||
uart_txd <= uart_rxd; | ||
uart_txd_strobe <= 1; | ||
end else | ||
if (counter[26:0] == 0 | ||
&& uart_txd_ready | ||
&& !uart_txd_strobe) | ||
begin | ||
// periodically print an increasing counter on the serial port | ||
led_reg <= counter[31:23]; | ||
uart_txd <= "0" + counter[31:27]; | ||
uart_txd_strobe <= 1; | ||
end | ||
end | ||
endmodule |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
`ifndef _uart_v_ | ||
osresearch marked this conversation as resolved.
Show resolved
Hide resolved
|
||
`define _uart_v_ | ||
/* | ||
* This module is designed a 3 Mbaud serial port. | ||
* This is the highest data rate supported by | ||
* the popular FT232 USB-to-serial chip. | ||
* | ||
* Copyright (C) 2009 Micah Dowty | ||
* (C) 2018 Trammell Hudson | ||
* | ||
* Permission is hereby granted, free of charge, to any person obtaining a copy | ||
* of this software and associated documentation files (the "Software"), to deal | ||
* in the Software without restriction, including without limitation the rights | ||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
* copies of the Software, and to permit persons to whom the Software is | ||
* furnished to do so, subject to the following conditions: | ||
* | ||
* The above copyright notice and this permission notice shall be included in | ||
* all copies or substantial portions of the Software. | ||
* | ||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
* THE SOFTWARE. | ||
*/ | ||
|
||
|
||
`include "util.v" | ||
|
||
module uart_tx( | ||
input clk, | ||
input reset, | ||
output serial, | ||
output reg ready, | ||
input [7:0] data, | ||
input data_strobe | ||
); | ||
parameter DIVISOR = 100; | ||
wire baud_x1; | ||
divide_by_n #(.N(DIVISOR)) baud_x1_div(clk, reset, baud_x1); | ||
|
||
reg [7+1+1:0] shiftreg; | ||
reg serial_r; | ||
assign serial = !serial_r; | ||
|
||
always @(posedge clk) | ||
if (reset) begin | ||
shiftreg <= 0; | ||
serial_r <= 0; | ||
end | ||
else if (data_strobe) begin | ||
shiftreg <= { | ||
1'b1, // stop bit | ||
data, | ||
1'b0 // start bit (inverted) | ||
}; | ||
ready <= 0; | ||
end | ||
else if (baud_x1) begin | ||
if (shiftreg == 0) | ||
begin | ||
/* Idle state is idle high, serial_r is inverted */ | ||
serial_r <= 0; | ||
ready <= 1; | ||
end else | ||
serial_r <= !shiftreg[0]; | ||
// shift the output register down | ||
shiftreg <= {1'b0, shiftreg[7+1+1:1]}; | ||
end else | ||
ready <= (shiftreg == 0); | ||
|
||
endmodule | ||
|
||
|
||
module uart_rx( | ||
input clk, | ||
input reset, | ||
input serial, | ||
output [7:0] data, | ||
output data_strobe | ||
); | ||
parameter DIVISOR = 25; // should the 1/4 the uart_tx divisor | ||
wire baud_x4; | ||
divide_by_n #(.N(DIVISOR)) baud_x4_div(clk, reset, baud_x4); | ||
|
||
// Clock crossing into clk domain | ||
reg [1:0] serial_buf; | ||
wire serial_sync = serial_buf[1]; | ||
always @(posedge clk) | ||
serial_buf <= { serial_buf[0], serial }; | ||
|
||
/* | ||
* State machine: Four clocks per bit, 10 total bits. | ||
*/ | ||
reg [8:0] shiftreg; | ||
reg [5:0] state; | ||
reg data_strobe; | ||
wire [3:0] bit_count = state[5:2]; | ||
wire [1:0] bit_phase = state[1:0]; | ||
|
||
wire sampling_phase = (bit_phase == 1); | ||
wire start_bit = (bit_count == 0 && sampling_phase); | ||
wire stop_bit = (bit_count == 9 && sampling_phase); | ||
|
||
wire waiting_for_start = (state == 0 && serial_sync == 1); | ||
|
||
wire error = ( (start_bit && serial_sync == 1) || | ||
(stop_bit && serial_sync == 0) ); | ||
|
||
assign data = shiftreg[7:0]; | ||
|
||
always @(posedge clk or posedge reset) | ||
if (reset) begin | ||
state <= 0; | ||
data_strobe <= 0; | ||
end | ||
else if (baud_x4) begin | ||
|
||
if (waiting_for_start || error || stop_bit) | ||
state <= 0; | ||
else | ||
state <= state + 1; | ||
|
||
if (bit_phase == 1) | ||
shiftreg <= { serial_sync, shiftreg[8:1] }; | ||
|
||
data_strobe <= stop_bit && !error; | ||
|
||
end | ||
else begin | ||
data_strobe <= 0; | ||
end | ||
|
||
endmodule | ||
|
||
|
||
module uart( | ||
input clk, | ||
input reset, | ||
// physical interface | ||
input serial_rxd, | ||
output serial_txd, | ||
|
||
// logical interface | ||
output [7:0] rxd, | ||
output rxd_strobe, | ||
input [7:0] txd, | ||
input txd_strobe, | ||
output txd_ready | ||
); | ||
// todo: rx/tx could share a single clock | ||
parameter DIVISOR = 40; // must be divisible by 4 for rx clock | ||
|
||
uart_rx #(.DIVISOR(DIVISOR/4)) rx( | ||
.clk(clk), | ||
.reset(reset), | ||
.serial(serial_rxd), | ||
.data_strobe(rxd_strobe), | ||
.data(rxd), | ||
); | ||
|
||
uart_tx #(.DIVISOR(DIVISOR)) tx( | ||
.clk(clk), | ||
.reset(reset), | ||
.serial(serial_txd), | ||
.data(txd), | ||
.data_strobe(txd_strobe), | ||
.ready(txd_ready), | ||
); | ||
endmodule | ||
|
||
`endif |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we should have a device option here too, that would also change the device passed to nextpnr?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like only (?) the -12f part requires this option. I'm not sure where the right place to fix this is (especially in light of things like https://github.com/SymbiFlow/prjtrellis/issues/55#issuecomment-452689924 ). Should nextpnr-ecp5 know about the 12f and its special id instead?