Add basic UART device

So far the device only transmits the ASCII set on repeat, but will
become fully featured later.
This commit is contained in:
Byron Lathi
2022-03-13 19:39:59 -05:00
parent 5834f179d2
commit e063e9f6a3
6 changed files with 297 additions and 49 deletions

View File

@@ -0,0 +1,24 @@
module testbench();
timeunit 10ns;
timeprecision 1ns;
logic clk_50, clk, rst, cs;
logic [1:0] addr;
logic [7:0] data_in, data_out;
logic rw;
logic RXD, TXD;
uart dut(.*);
always #1 clk_50 = clk_50 === 1'b0;
initial begin
rst <= '1;
repeat(5) @(posedge clk_50);
rst <= '0;
@(posedge clk_50);
end
endmodule

View File

@@ -0,0 +1,17 @@
transcript on
if {[file exists rtl_work]} {
vdel -lib rtl_work -all
}
vlib rtl_work
vmap work rtl_work
vlog -vlog01compat -work work +incdir+/home/byron/Projects/super6502/hw/fpga {/home/byron/Projects/super6502/hw/fpga/ram.v}
vlog -vlog01compat -work work +incdir+/home/byron/Projects/super6502/hw/fpga {/home/byron/Projects/super6502/hw/fpga/rom.v}
vlog -vlog01compat -work work +incdir+/home/byron/Projects/super6502/hw/fpga {/home/byron/Projects/super6502/hw/fpga/cpu_clk.v}
vlog -vlog01compat -work work +incdir+/home/byron/Projects/super6502/hw/fpga/db {/home/byron/Projects/super6502/hw/fpga/db/cpu_clk_altpll.v}
vlog -sv -work work +incdir+/home/byron/Projects/super6502/hw/fpga {/home/byron/Projects/super6502/hw/fpga/uart.sv}
vlog -sv -work work +incdir+/home/byron/Projects/super6502/hw/fpga {/home/byron/Projects/super6502/hw/fpga/addr_decode.sv}
vlog -sv -work work +incdir+/home/byron/Projects/super6502/hw/fpga {/home/byron/Projects/super6502/hw/fpga/super6502.sv}
vlog -sv -work work +incdir+/home/byron/Projects/super6502/hw/fpga {/home/byron/Projects/super6502/hw/fpga/HexDriver.sv}
vlog -sv -work work +incdir+/home/byron/Projects/super6502/hw/fpga {/home/byron/Projects/super6502/hw/fpga/SevenSeg.sv}

View File

@@ -0,0 +1,14 @@
transcript on
if {[file exists rtl_work]} {
vdel -lib rtl_work -all
}
vlib rtl_work
vmap work rtl_work
vlog -sv -work work {../../uart.sv}
vlog -sv -work work {../../hvl/uart_testbench.sv}
vsim -t 1ps -L altera_ver -L lpm_ver -L sgate_ver -L altera_mf_ver -L altera_lnsim_ver -L stratixv_ver -L stratixv_hssi_ver -L stratixv_pcie_hip_ver -L rtl_work -L work -voptargs="+acc" testbench
add wave -group {dut} -radix hexadecimal sim:/testbench/dut/*

View File

@@ -140,15 +140,6 @@ set_location_assignment PIN_C16 -to HEX0[3]
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW"
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
set_global_assignment -name SYSTEMVERILOG_FILE addr_decode.sv
set_global_assignment -name SYSTEMVERILOG_FILE bb_spi_controller.sv
set_global_assignment -name SYSTEMVERILOG_FILE super6502.sv
set_global_assignment -name QIP_FILE ram.qip
set_global_assignment -name SDC_FILE super6502.sdc
set_global_assignment -name QIP_FILE rom.qip
set_global_assignment -name SYSTEMVERILOG_FILE HexDriver.sv
set_global_assignment -name SYSTEMVERILOG_FILE SevenSeg.sv
set_global_assignment -name QIP_FILE cpu_clk.qip
set_location_assignment PIN_B8 -to rst_n
set_location_assignment PIN_P11 -to clk_50
set_global_assignment -name ENABLE_OCT_DONE OFF
@@ -160,46 +151,45 @@ set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_vpb
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_addr[15]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_addr[14]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_addr[13]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_addr[12]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_addr[11]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_addr[10]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_addr[9]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_addr[8]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_addr[7]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_addr[6]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_addr[5]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_addr[4]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_addr[3]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_addr[2]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_addr[1]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_addr[0]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_be
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_data[7]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_data[6]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_data[5]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_data[4]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_data[3]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_data[2]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_data[1]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_data[0]
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_irqb
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_led
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_mlb
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_nmib
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_phi2
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_rdy
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_resb
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_rwb
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_sob
set_instance_assignment -name IO_STANDARD "2.5 V" -to cpu_sync
set_instance_assignment -name IO_STANDARD "2.5 V" -to clk_50
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_vpb
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_addr[15]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_addr[14]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_addr[13]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_addr[12]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_addr[11]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_addr[10]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_addr[9]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_addr[8]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_addr[7]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_addr[6]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_addr[5]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_addr[4]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_addr[3]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_addr[2]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_addr[1]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_addr[0]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_be
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_data[7]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_data[6]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_data[5]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_data[4]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_data[3]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_data[2]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_data[1]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_data[0]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_irqb
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_led
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_mlb
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_nmib
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_phi2
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_rdy
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_resb
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_rwb
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_sob
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to cpu_sync
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to clk_50
set_global_assignment -name ENABLE_SIGNALTAP OFF
set_global_assignment -name USE_SIGNALTAP_FILE output_files/stp1.stp
set_global_assignment -name SIGNALTAP_FILE output_files/stp1.stp
set_location_assignment PIN_F20 -to HEX4[6]
set_location_assignment PIN_F19 -to HEX4[5]
set_location_assignment PIN_H19 -to HEX4[4]
@@ -214,4 +204,83 @@ set_location_assignment PIN_N19 -to HEX5[5]
set_location_assignment PIN_N20 -to HEX5[6]
set_location_assignment PIN_F18 -to HEX4[0]
set_location_assignment PIN_E20 -to HEX4[1]
set_location_assignment PIN_AB5 -to UART_RXD
set_location_assignment PIN_AB6 -to UART_TXD
set_global_assignment -name SYSTEMVERILOG_FILE uart.sv
set_global_assignment -name SYSTEMVERILOG_FILE addr_decode.sv
set_global_assignment -name SYSTEMVERILOG_FILE bb_spi_controller.sv
set_global_assignment -name SYSTEMVERILOG_FILE super6502.sv
set_global_assignment -name QIP_FILE ram.qip
set_global_assignment -name SDC_FILE super6502.sdc
set_global_assignment -name QIP_FILE rom.qip
set_global_assignment -name SYSTEMVERILOG_FILE HexDriver.sv
set_global_assignment -name SYSTEMVERILOG_FILE SevenSeg.sv
set_global_assignment -name QIP_FILE cpu_clk.qip
set_global_assignment -name SIGNALTAP_FILE output_files/stp1.stp
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to UART_RXD
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to UART_TXD
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX0[6]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX0[5]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX0[4]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX0[3]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX0[2]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX0[1]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX0[0]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1[6]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1[5]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1[4]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1[3]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1[2]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1[1]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX1[0]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2[6]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2[5]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2[4]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2[3]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2[2]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2[1]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX2[0]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[6]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[5]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[4]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[3]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[2]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[1]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX3[0]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[6]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[5]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[4]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[3]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[2]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[1]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX4[0]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[6]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[5]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[4]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[3]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[2]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[1]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to HEX5[0]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to rst_n
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[0]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[1]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[2]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[3]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[4]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[5]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[6]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[7]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[8]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to SW[9]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to Run
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[0]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[1]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[2]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[3]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[4]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[5]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[6]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[7]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[8]
set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to LED[9]
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@@ -20,7 +20,10 @@ module super6502(
output logic cpu_be,
output logic cpu_nmib,
output logic [6:0] HEX0, HEX1, HEX2, HEX3, HEX4, HEX5
output logic [6:0] HEX0, HEX1, HEX2, HEX3, HEX4, HEX5,
input logic UART_RXD,
output logic UART_TXD
);
logic rst;
@@ -102,7 +105,19 @@ SevenSeg segs(
.addr(cpu_addr[1:0]),
.HEX0(HEX0), .HEX1(HEX1), .HEX2(HEX2), .HEX3(HEX3), .HEX4(HEX4), .HEX5(HEX5)
);
uart uart(
.clk_50(clk_50),
.clk(clk),
.rst(rst),
.rw(cpu_rwb),
.data_in(cpu_data_in),
.cs(),
.addr(cpu_addr[1:0]),
.RXD(UART_RXD),
.TXD(UART_TXD),
.data_out()
);
endmodule

109
hw/fpga/uart.sv Normal file
View File

@@ -0,0 +1,109 @@
module uart(
input clk_50,
input clk,
input rst,
input cs,
input rw,
input [7:0] data_in,
input [1:0] addr,
input RXD,
output logic TXD,
output logic [7:0] data_out
);
//Handle reading and writing registers
logic [7:0] _data [3:0];
assign data_out = _data[addr];
always_ff @(posedge clk) begin
if (rst)
_data = '{default:'0};
if (~rw & cs)
_data[addr] <= data_in;
end
// state controller
typedef enum bit [1:0] {START, DATA, PARITY, STOP} macro_t;
struct packed {
macro_t macro;
logic [3:0] count;
} state, next_state;
localparam logic [3:0] maxcount = 4'h7;
logic [7:0] testval, next_testval;
// baud rate: 9600
logic [14:0] clkdiv;
always_ff @(posedge clk_50) begin
if (rst) begin
clkdiv <= 0;
state.macro <= STOP;
state.count <= 3'b0;
testval <= '0;
end else begin
if (clkdiv == 5207) begin
clkdiv <= 0;
state <= next_state;
testval <= next_testval;
end else begin
clkdiv <= clkdiv + 15'b1;
end
end
end
always_comb begin
next_state = state;
unique case (state.macro)
START: begin
next_state.macro = DATA;
next_state.count = 3'b0;
end
DATA: begin
if (state.count == maxcount) begin
next_state.macro = STOP; // or PARITY
next_state.count = 3'b0;
end else begin
next_state.count = state.count + 3'b1;
next_state.macro = DATA;
end
end
PARITY: begin
end
STOP: begin
next_state.macro = START;
next_state.count = '0;
end
endcase
end
always_comb begin
TXD = '1;
next_testval = testval;
unique case (state.macro)
START: begin
TXD = '0;
end
DATA: begin
TXD = testval[state.count];
end
PARITY: begin
end
STOP: begin
next_testval = testval + 8'b1;
TXD = '1;
end
endcase
end
endmodule