From e063e9f6a3fdbf5598c93271095bc2b9b52ba71c Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Sun, 13 Mar 2022 19:39:59 -0500 Subject: [PATCH] Add basic UART device So far the device only transmits the ASCII set on repeat, but will become fully featured later. --- hw/fpga/hvl/uart_testbench.sv | 24 +++ .../super6502_run_msim_rtl_verilog.do | 17 ++ hw/fpga/simulation/modelsim/uart.do | 14 ++ hw/fpga/super6502.qsf | 163 +++++++++++++----- hw/fpga/super6502.sv | 19 +- hw/fpga/uart.sv | 109 ++++++++++++ 6 files changed, 297 insertions(+), 49 deletions(-) create mode 100644 hw/fpga/hvl/uart_testbench.sv create mode 100644 hw/fpga/simulation/modelsim/super6502_run_msim_rtl_verilog.do create mode 100644 hw/fpga/simulation/modelsim/uart.do create mode 100644 hw/fpga/uart.sv diff --git a/hw/fpga/hvl/uart_testbench.sv b/hw/fpga/hvl/uart_testbench.sv new file mode 100644 index 0000000..183c0d7 --- /dev/null +++ b/hw/fpga/hvl/uart_testbench.sv @@ -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 diff --git a/hw/fpga/simulation/modelsim/super6502_run_msim_rtl_verilog.do b/hw/fpga/simulation/modelsim/super6502_run_msim_rtl_verilog.do new file mode 100644 index 0000000..f0f1614 --- /dev/null +++ b/hw/fpga/simulation/modelsim/super6502_run_msim_rtl_verilog.do @@ -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} + diff --git a/hw/fpga/simulation/modelsim/uart.do b/hw/fpga/simulation/modelsim/uart.do new file mode 100644 index 0000000..585b48f --- /dev/null +++ b/hw/fpga/simulation/modelsim/uart.do @@ -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/* + diff --git a/hw/fpga/super6502.qsf b/hw/fpga/super6502.qsf index 7c3a514..496716f 100644 --- a/hw/fpga/super6502.qsf +++ b/hw/fpga/super6502.qsf @@ -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 \ No newline at end of file diff --git a/hw/fpga/super6502.sv b/hw/fpga/super6502.sv index 1b61440..1411643 100644 --- a/hw/fpga/super6502.sv +++ b/hw/fpga/super6502.sv @@ -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 \ No newline at end of file diff --git a/hw/fpga/uart.sv b/hw/fpga/uart.sv new file mode 100644 index 0000000..2ad48f9 --- /dev/null +++ b/hw/fpga/uart.sv @@ -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