From 5834f179d24499cc205db17574fa9eb997d760a0 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Sun, 13 Mar 2022 19:38:12 -0500 Subject: [PATCH 1/9] Ignore more modelsim files Ignore all bak files and msim_transcript --- hw/fpga/simulation/modelsim/.gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/fpga/simulation/modelsim/.gitignore b/hw/fpga/simulation/modelsim/.gitignore index f397c9b..38bbc77 100644 --- a/hw/fpga/simulation/modelsim/.gitignore +++ b/hw/fpga/simulation/modelsim/.gitignore @@ -8,7 +8,7 @@ *.dat *.dbs *.psm -*.bak +*.bak* *.cmp *.jpg *.html @@ -20,7 +20,7 @@ wlf* *.vstf *.ucdb cov*/ -transcript* +*transcript* sc_dpiheader.h vsim.dbg *.sft From e063e9f6a3fdbf5598c93271095bc2b9b52ba71c Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Sun, 13 Mar 2022 19:39:59 -0500 Subject: [PATCH 2/9] 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 From f8da9206d960de13d50014b36df00260e2972641 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Mon, 14 Mar 2022 00:00:55 -0500 Subject: [PATCH 3/9] Refactor uart.sv to better allow cpu control Added new signal tx_flag, which indicates whether the transmitter is ready for new data. Added status register, which when read will return the tx_flag bit, as well as others that can be implemented. Added new state IDLE, which resets the TX flag and allows new data to be written. Added code to allow for different baud rates, though it is still fixed currently. --- hw/fpga/uart.sv | 78 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 18 deletions(-) diff --git a/hw/fpga/uart.sv b/hw/fpga/uart.sv index 2ad48f9..9c86ffb 100644 --- a/hw/fpga/uart.sv +++ b/hw/fpga/uart.sv @@ -17,42 +17,71 @@ module uart( //Handle reading and writing registers -logic [7:0] _data [3:0]; +logic [7:0] tx_buf; +logic [7:0] rx_buf; +logic [7:0] status; -assign data_out = _data[addr]; +logic tx_flag; + +logic tx_flag_set; +logic tx_flag_clear; + +assign status[0] = tx_flag | tx_flag_clear; always_ff @(posedge clk) begin - if (rst) - _data = '{default:'0}; - if (~rw & cs) - _data[addr] <= data_in; + if (rst) begin + tx_flag_set <= '0; + tx_buf <= '0; + rx_buf <= '0; + status[7:1] <= '0; + end + + if (cs) begin + if (~rw) begin + if (addr == 0) + tx_buf <= data_in; + end else begin + if (addr == 0) + data_out <= rx_buf; + if (addr == 1) + data_out <= status; + end + end + + if (~rw & cs && addr == 0) + tx_flag_set <= '1; + else + tx_flag_set <= '0; end // state controller -typedef enum bit [1:0] {START, DATA, PARITY, STOP} macro_t; +typedef enum bit [2:0] {START, DATA, PARITY, STOP, IDLE} 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 +localparam baud = 9600; +localparam count = (50000000/baud)-1; logic [14:0] clkdiv; always_ff @(posedge clk_50) begin if (rst) begin clkdiv <= 0; - state.macro <= STOP; + state.macro <= IDLE; state.count <= 3'b0; - testval <= '0; + tx_flag <= '0; end else begin - if (clkdiv == 5207) begin + if (tx_flag_set) + tx_flag <= '1; + else if (tx_flag_clear) + tx_flag <= '0; + + if (clkdiv == count) begin clkdiv <= 0; state <= next_state; - testval <= next_testval; end else begin clkdiv <= clkdiv + 15'b1; end @@ -79,30 +108,43 @@ always_comb begin PARITY: begin end STOP: begin - next_state.macro = START; + next_state.macro = IDLE; next_state.count = '0; end + IDLE: begin + if (tx_flag) + next_state.macro = START; + else + next_state.macro = IDLE; + end + + default:; endcase end always_comb begin TXD = '1; - next_testval = testval; + tx_flag_clear = '0; unique case (state.macro) START: begin TXD = '0; end DATA: begin - TXD = testval[state.count]; + TXD = tx_buf[state.count]; end PARITY: begin end STOP: begin - next_testval = testval + 8'b1; + tx_flag_clear = '1; TXD = '1; end + IDLE: begin + TXD = '1; + end + + default:; endcase end From b48438f6b2949688b9a41028afd2ba0f9bdb4cb2 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Mon, 14 Mar 2022 00:04:04 -0500 Subject: [PATCH 4/9] Add write and puts tasks to the uart testbench The write task will transmit a single byte, the puts task will transmit a string of length n. These do not do any verification, you still have to look at the output. --- hw/fpga/hvl/uart_testbench.sv | 40 +++++++++++++++++++++++++++-- hw/fpga/simulation/modelsim/uart.do | 3 +++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/hw/fpga/hvl/uart_testbench.sv b/hw/fpga/hvl/uart_testbench.sv index 183c0d7..8e1a05d 100644 --- a/hw/fpga/hvl/uart_testbench.sv +++ b/hw/fpga/hvl/uart_testbench.sv @@ -10,15 +10,51 @@ logic [7:0] data_in, data_out; logic rw; logic RXD, TXD; +logic [7:0] status; + uart dut(.*); always #1 clk_50 = clk_50 === 1'b0; +always #100 clk = clk === 1'b0; + +task write(logic [7:0] data); + @(negedge clk); + cs <= '1; + addr <= '0; + data_in <= data; + rw <= '0; + + @(negedge clk); + cs <= '0; + addr <= '0; + data_in <= 8'hxx; + rw <= '1; + + do begin + @(negedge clk); + cs <= '1; + addr <= 1'b1; + rw <= '1; + @(negedge clk); + end while (data_out != 8'h0); +endtask + +task puts(string s, int n); + for (int i = 0; i < n; i++) + write(s[i]); +endtask initial begin rst <= '1; - repeat(5) @(posedge clk_50); + repeat(5) @(posedge clk); rst <= '0; - @(posedge clk_50); + rw <= '1; + cs <= '0; + status <= '0; + + puts("Hello, world!\n", 14); + + $finish(); end endmodule diff --git a/hw/fpga/simulation/modelsim/uart.do b/hw/fpga/simulation/modelsim/uart.do index 585b48f..dde4bcd 100644 --- a/hw/fpga/simulation/modelsim/uart.do +++ b/hw/fpga/simulation/modelsim/uart.do @@ -12,3 +12,6 @@ vsim -t 1ps -L altera_ver -L lpm_ver -L sgate_ver -L altera_mf_ver -L altera_lns add wave -group {dut} -radix hexadecimal sim:/testbench/dut/* +onfinish stop +run -all + From 0b5ccf48b8ea9804016d77fe072820ac7ccb7c33 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Mon, 14 Mar 2022 00:24:08 -0500 Subject: [PATCH 5/9] Add basic UART driver This didn't have a chance to get tested so I hope it works. There is not fancy stuff here, just write to the register and wait till it is done. --- sw/io.inc65 | 7 ++++++- sw/uart.h | 11 +++++++++++ sw/uart.s | 29 +++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 sw/uart.h create mode 100644 sw/uart.s diff --git a/sw/io.inc65 b/sw/io.inc65 index 4bf4736..9192cff 100644 --- a/sw/io.inc65 +++ b/sw/io.inc65 @@ -1 +1,6 @@ -SEVEN_SEG = $7ff0 +SEVEN_SEG = $7ff0 + +UART = $7ff4 +UART_TXB = UART +UART_RXB = UART +UART_STATUS = UART + 1 diff --git a/sw/uart.h b/sw/uart.h new file mode 100644 index 0000000..c96b48c --- /dev/null +++ b/sw/uart.h @@ -0,0 +1,11 @@ +#ifndef _UART_H +#define _UART_H + +#include + +void uart_txb(uint8_t val); +void uart_txb_block(uint8_t val); + +uint8_t uart_status(); + +#endif \ No newline at end of file diff --git a/sw/uart.s b/sw/uart.s new file mode 100644 index 0000000..80b5563 --- /dev/null +++ b/sw/uart.s @@ -0,0 +1,29 @@ +.include "io.inc65" + +.importzp sp, sreg + +.export _uart_txb +.export _uart_txb_block +.export _uart_status + +.autoimport on + +.code + +; @in A: byte to transmit +; Transmits a byte over the UART +_uart_txb: + sta UART_TXB ; Just write value, don't wait + rts + +_uart_txb_block: + sta UART_TXB ; Write value +@1: lda UART_STATUS ; Wait for status[0] to be 0 + bit #$01 + bne @1 + rts + +_uart_status: + lda UART_STATUS + ldx #$00 + rts From da4d5f0fe747260adf4aaedf5c86ccda3b548fcb Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Mon, 14 Mar 2022 00:47:26 -0500 Subject: [PATCH 6/9] Add uart tests --- sw/tests/test_main.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/sw/tests/test_main.c b/sw/tests/test_main.c index 2f32592..50e3d85 100644 --- a/sw/tests/test_main.c +++ b/sw/tests/test_main.c @@ -1,6 +1,7 @@ #include #include "sevenseg.h" +#include "uart.h" int main(void) { @@ -56,6 +57,23 @@ int main(void) } printf("Done!\n\n"); + printf("Testing uart_txb_block...\n"); + *(uint8_t*)0x7ff5 = 0; + uart_txb_block(0xa5); + if (*(uint8_t*)0x7ff4 != 0xa5) { + printf("Incorrect value!\n", i); + retval++; + } + printf("Done!\n\n"); + + printf("Testing uart_status...\n"); + *(uint8_t*)0x7ff5 = 0xa5; + if (uart_status() != 0xa5) { + printf("Incorrect value!\n", i); + retval++; + } + printf("Done!\n\n"); + return retval != 0; } \ No newline at end of file From cfcf94a8757a0ac4e701342045f1879dcb44e5dd Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Mon, 14 Mar 2022 10:45:45 -0500 Subject: [PATCH 7/9] Integrate uart controller into top level module Adds new chip select for the UART, and a new entry in the data_out mux for the UART. --- hw/fpga/addr_decode.sv | 4 +++- hw/fpga/super6502.sv | 11 ++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/hw/fpga/addr_decode.sv b/hw/fpga/addr_decode.sv index 1b4dd5e..83f3c57 100644 --- a/hw/fpga/addr_decode.sv +++ b/hw/fpga/addr_decode.sv @@ -2,11 +2,13 @@ module addr_decode( input logic [15:0] addr, output logic ram_cs, output logic rom_cs, - output logic hex_cs + output logic hex_cs, + output logic uart_cs ); assign rom_cs = addr[15]; assign ram_cs = ~addr[15] && addr < 16'h7ff0; assign hex_cs = addr >= 16'h7ff0 && addr < 16'h7ff4; +assign uart_cs = addr >= 16'h7ff4 && addr < 16'h7ff6; endmodule diff --git a/hw/fpga/super6502.sv b/hw/fpga/super6502.sv index 1411643..54bcf61 100644 --- a/hw/fpga/super6502.sv +++ b/hw/fpga/super6502.sv @@ -40,10 +40,12 @@ assign cpu_data = cpu_rwb ? cpu_data_out : 'z; logic [7:0] rom_data_out; logic [7:0] ram_data_out; +logic [7:0] uart_data_out; logic ram_cs; logic rom_cs; logic hex_cs; +logic uart_cs; cpu_clk cpu_clk( .inclk0(clk_50), @@ -65,7 +67,8 @@ addr_decode decode( .addr(cpu_addr), .ram_cs(ram_cs), .rom_cs(rom_cs), - .hex_cs(hex_cs) + .hex_cs(hex_cs), + .uart_cs(uart_cs) ); @@ -74,6 +77,8 @@ always_comb begin cpu_data_out = ram_data_out; else if (rom_cs) cpu_data_out = rom_data_out; + else if (uart_cs) + cpu_data_out = uart_data_out; else cpu_data_out = 'x; end @@ -112,11 +117,11 @@ uart uart( .rst(rst), .rw(cpu_rwb), .data_in(cpu_data_in), - .cs(), + .cs(uart_cs), .addr(cpu_addr[1:0]), .RXD(UART_RXD), .TXD(UART_TXD), - .data_out() + .data_out(uart_data_out) ); endmodule From a671fda51c8a74d7e3657d6ba6808aee3fd58725 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Mon, 14 Mar 2022 10:46:36 -0500 Subject: [PATCH 8/9] Add sample puts function "Hello, world!" :) --- sw/main.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sw/main.c b/sw/main.c index c7a5217..b72826f 100644 --- a/sw/main.c +++ b/sw/main.c @@ -1,10 +1,24 @@ #include #include "sevenseg.h" +#include "uart.h" + +void puts(const char* s) +{ + while (*s) { + uart_txb_block(*s); + if (*s == '\n') + uart_txb_block('\r'); + + s++; + } +} int main() { hex_enable(0x3f); hex_set_24(0xabcdef); + + puts("Hello, World!\n"); while(1); return 0; } From 4fb73f8e9746a8b41a322b8981f55b524c65e767 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Mon, 14 Mar 2022 10:56:10 -0500 Subject: [PATCH 9/9] Update cs_testbench.sv Add uart_cs and fix error messages --- hw/fpga/hvl/cs_testbench.sv | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/hw/fpga/hvl/cs_testbench.sv b/hw/fpga/hvl/cs_testbench.sv index b552abb..b764c0f 100644 --- a/hw/fpga/hvl/cs_testbench.sv +++ b/hw/fpga/hvl/cs_testbench.sv @@ -8,8 +8,9 @@ logic [15:0] addr; logic ram_cs; logic rom_cs; logic hex_cs; +logic uart_cs; -int cs_count = ram_cs + rom_cs + hex_cs; +int cs_count = ram_cs + rom_cs + hex_cs + uart_cs; addr_decode dut(.*); @@ -29,7 +30,12 @@ initial begin : TEST_VECTORS if (i >= 16'h7ff0 && i < 16'h7ff4) begin assert(hex_cs == '1) else - $error("Bad CS! addr=%4x should have io_cs!", addr); + $error("Bad CS! addr=%4x should have hex_cs!", addr); + end + if (i >= 16'h7ff4 && i < 16'6) begin + assert(uart_cs == '1) + else + $error("Bad CS! addr=%4x should have uart_cs!", addr); end if (i >= 2**15) begin assert(rom_cs == '1)