machxo2: Add two new examples: blinky_ext and aforementioned UART.

This commit is contained in:
William D. Jones 2021-02-08 03:27:49 -05:00 committed by gatecat
parent 74b5e846a5
commit 73c851d8e0
3 changed files with 238 additions and 0 deletions

View File

@ -57,6 +57,16 @@ rm -rf *.dot *.json *.png *.vcd *.smt2 *.log *.txt *.bit {pack,place,pnr}*.v bli
* `tinyfpga.v`- Blink the LED on TinyFPA Ax.
* `rgbcount.v`- Blink an RGB LED using TinyFPGA Ax, more closely-based on
[the TinyFPGA Ax guide](https://tinyfpga.com/a-series-guide.html).
* `blinky_ext.v`- Blink the LED on TinyFPA Ax using an external pin (pin 6).
* `uart.v`- UART loopback demo at 19200 baud. Requires the following pins:
* Pin 1- RX LED
* Pin 2- TX (will echo RX)
* Pin 3- RX
* Pin 4- TX LED
* Pin 5- Load LED
* Pin 6- 12 MHz clock input
* Pin 7- Take LED
* Pin 8- Empty LED
## Environment Variables For Scripts

View File

@ -0,0 +1,19 @@
// Modified from:
// https://github.com/tinyfpga/TinyFPGA-A-Series/tree/master/template_a2
module top (
(* LOC="13" *)
output pin1,
(* LOC="21" *)
input clk
);
reg [23:0] led_timer;
always @(posedge clk) begin
led_timer <= led_timer + 1;
end
// left side of board
assign pin1 = led_timer[23];
endmodule

209
machxo2/examples/uart.v Normal file
View File

@ -0,0 +1,209 @@
/* Example UART derived from: https://github.com/cr1901/migen_uart.
Requires 12MHz clock and runs at 19,200 baud. */
/* Machine-generated using Migen */
module top(
(* LOC = "14" *)
output tx,
(* LOC = "16" *)
input rx,
(* LOC = "13" *)
output rx_led,
(* LOC = "17" *)
output tx_led,
(* LOC = "20" *)
output load_led,
(* LOC = "23" *)
output take_led,
(* LOC = "25" *)
output empty_led,
(* LOC = "21" *)
input clk
);
wire [7:0] out_data;
wire [7:0] in_data;
reg wr = 1'd0;
reg rd = 1'd0;
wire tx_empty;
wire rx_empty;
wire tx_ov;
wire rx_ov;
wire sout_load;
wire [7:0] sout_out_data;
wire sout_shift;
reg sout_empty = 1'd1;
reg sout_overrun = 1'd0;
reg [3:0] sout_count = 4'd0;
reg [9:0] sout_reg = 10'd0;
reg sout_tx;
wire sin_rx;
wire sin_shift;
wire sin_take;
reg [7:0] sin_in_data = 8'd0;
wire sin_edge;
reg sin_empty = 1'd1;
reg sin_busy = 1'd0;
reg sin_overrun = 1'd0;
reg sin_sync_rx = 1'd0;
reg [8:0] sin_reg = 9'd0;
reg sin_rx_prev = 1'd0;
reg [3:0] sin_count = 4'd0;
wire out_active;
wire in_active;
reg shift_out_strobe = 1'd0;
reg shift_in_strobe = 1'd0;
reg [9:0] in_counter = 10'd0;
reg [9:0] out_counter = 10'd0;
wire sys_clk;
wire sys_rst;
wire por_clk;
reg int_rst = 1'd1;
// synthesis translate_off
reg dummy_s;
initial dummy_s <= 1'd0;
// synthesis translate_on
assign tx_led = (~tx);
assign rx_led = (~rx);
assign load_led = sout_load;
assign take_led = sin_take;
assign empty_led = sin_empty;
assign out_data = in_data;
assign in_data = sin_in_data;
assign sout_out_data = out_data;
assign sin_take = rd;
assign sout_load = wr;
assign tx = sout_tx;
assign sin_rx = rx;
assign tx_empty = sout_empty;
assign rx_empty = sin_empty;
assign tx_ov = sout_overrun;
assign rx_ov = sin_overrun;
assign sout_shift = shift_out_strobe;
assign sin_shift = shift_in_strobe;
assign out_active = (~sout_empty);
assign in_active = sin_busy;
// synthesis translate_off
reg dummy_d;
// synthesis translate_on
always @(*) begin
sout_tx <= 1'd0;
if (sout_empty) begin
sout_tx <= 1'd1;
end else begin
sout_tx <= sout_reg[0];
end
// synthesis translate_off
dummy_d <= dummy_s;
// synthesis translate_on
end
assign sin_edge = ((sin_rx_prev == 1'd1) & (sin_sync_rx == 1'd0));
assign sys_clk = clk;
assign por_clk = clk;
assign sys_rst = int_rst;
always @(posedge por_clk) begin
int_rst <= 1'd0;
end
always @(posedge sys_clk) begin
wr <= 1'd0;
rd <= 1'd0;
if ((~sin_empty)) begin
wr <= 1'd1;
rd <= 1'd1;
end
if (sout_load) begin
if (sout_empty) begin
sout_reg[0] <= 1'd0;
sout_reg[8:1] <= sout_out_data;
sout_reg[9] <= 1'd1;
sout_empty <= 1'd0;
sout_overrun <= 1'd0;
sout_count <= 1'd0;
end else begin
sout_overrun <= 1'd1;
end
end
if (((~sout_empty) & sout_shift)) begin
sout_reg[8:0] <= sout_reg[9:1];
sout_reg[9] <= 1'd0;
if ((sout_count == 4'd9)) begin
sout_empty <= 1'd1;
sout_count <= 1'd0;
end else begin
sout_count <= (sout_count + 1'd1);
end
end
sin_sync_rx <= sin_rx;
sin_rx_prev <= sin_sync_rx;
if (sin_take) begin
sin_empty <= 1'd1;
sin_overrun <= 1'd0;
end
if (((~sin_busy) & sin_edge)) begin
sin_busy <= 1'd1;
end
if ((sin_shift & sin_busy)) begin
sin_reg[8] <= sin_sync_rx;
sin_reg[7:0] <= sin_reg[8:1];
if ((sin_count == 4'd9)) begin
sin_in_data <= sin_reg[8:1];
sin_count <= 1'd0;
sin_busy <= 1'd0;
if ((~sin_empty)) begin
sin_overrun <= 1'd1;
end else begin
sin_empty <= 1'd0;
end
end else begin
sin_count <= (sin_count + 1'd1);
end
end
out_counter <= 1'd0;
in_counter <= 1'd0;
if (in_active) begin
shift_in_strobe <= 1'd0;
in_counter <= (in_counter + 1'd1);
if ((in_counter == 9'd311)) begin
shift_in_strobe <= 1'd1;
end
if ((in_counter == 10'd623)) begin
in_counter <= 1'd0;
end
end
if (out_active) begin
shift_out_strobe <= 1'd0;
out_counter <= (out_counter + 1'd1);
if ((out_counter == 10'd623)) begin
out_counter <= 1'd0;
shift_out_strobe <= 1'd1;
end
end
if (sys_rst) begin
wr <= 1'd0;
rd <= 1'd0;
sout_empty <= 1'd1;
sout_overrun <= 1'd0;
sout_count <= 4'd0;
sout_reg <= 10'd0;
sin_in_data <= 8'd0;
sin_empty <= 1'd1;
sin_busy <= 1'd0;
sin_overrun <= 1'd0;
sin_sync_rx <= 1'd0;
sin_reg <= 9'd0;
sin_rx_prev <= 1'd0;
sin_count <= 4'd0;
shift_out_strobe <= 1'd0;
shift_in_strobe <= 1'd0;
in_counter <= 10'd0;
out_counter <= 10'd0;
end
end
endmodule