uart integrated into SOC
diff --git a/openlane/uart/base.sdc b/openlane/uart/base.sdc new file mode 100644 index 0000000..1eab2c3 --- /dev/null +++ b/openlane/uart/base.sdc
@@ -0,0 +1,34 @@ +set_units -time ns +set ::env(CORE_CLOCK_PERIOD) "10" +set ::env(CORE_CLOCK_PORT) "app_clk" + +###################################### +# WB Clock domain input output +###################################### +create_clock [get_ports $::env(CORE_CLOCK_PORT)] -name $::env(CORE_CLOCK_PORT) -period $::env(CORE_CLOCK_PERIOD) +set core_input_delay_value [expr $::env(CORE_CLOCK_PERIOD) * 0.6] +set core_output_delay_value [expr $::env(CORE_CLOCK_PERIOD) * 0.6] +puts "\[INFO\]: Setting wb output delay to:$core_output_delay_value" +puts "\[INFO\]: Setting wb input delay to: $core_input_delay_value" + + +set_input_delay 2.0 -clock [get_clocks $::env(CORE_CLOCK_PORT)] {arst_n} + +set_input_delay $core_input_delay_value -clock [get_clocks $::env(CORE_CLOCK_PORT)] [get_port reg_cs*] +set_input_delay $core_input_delay_value -clock [get_clocks $::env(CORE_CLOCK_PORT)] [get_port reg_addr*] +set_input_delay $core_input_delay_value -clock [get_clocks $::env(CORE_CLOCK_PORT)] [get_port reg_wr*] +set_input_delay $core_input_delay_value -clock [get_clocks $::env(CORE_CLOCK_PORT)] [get_port reg_be*] +set_input_delay $core_input_delay_value -clock [get_clocks $::env(CORE_CLOCK_PORT)] [get_port reg_wdata*] + + +set_output_delay $core_output_delay_value -clock [get_clocks $::env(CORE_CLOCK_PORT)] [get_port reg_rdata*] +set_output_delay $core_output_delay_value -clock [get_clocks $::env(CORE_CLOCK_PORT)] [get_port reg_ack*] + + + +# TODO set this as parameter +set_driving_cell -lib_cell $::env(SYNTH_DRIVING_CELL) -pin $::env(SYNTH_DRIVING_CELL_PIN) [all_inputs] +set cap_load [expr $::env(SYNTH_CAP_LOAD) / 1000.0] +puts "\[INFO\]: Setting load to: $cap_load" +set_load $cap_load [all_outputs] +
diff --git a/openlane/uart/config.tcl b/openlane/uart/config.tcl new file mode 100644 index 0000000..f0aea1f --- /dev/null +++ b/openlane/uart/config.tcl
@@ -0,0 +1,64 @@ +# Global +# ------ + +set script_dir [file dirname [file normalize [info script]]] +# Name +set ::env(DESIGN_NAME) uart_core + + + +# Timing configuration +set ::env(CLOCK_PERIOD) "10" +set ::env(CLOCK_PORT) "app_clk" + + +# Sources +# ------- + +# Local sources + no2usb sources +set ::env(VERILOG_FILES) "\ + $script_dir/../../verilog/rtl/uart/src/uart_core.sv \ + $script_dir/../../verilog/rtl/uart/src/uart_cfg.sv \ + $script_dir/../../verilog/rtl/uart/src/uart_rxfsm.sv \ + $script_dir/../../verilog/rtl/uart/src/uart_txfsm.sv \ + $script_dir/../../verilog/rtl/lib/async_fifo_th.sv \ + $script_dir/../../verilog/rtl/lib/reset_sync.sv \ + " + +#set ::env(VERILOG_INCLUDE_DIRS) [glob $script_dir/../../verilog/rtl/sdram_ctrl/src/defs ] + +set ::env(SDC_FILE) "$script_dir/base.sdc" +set ::env(BASE_SDC_FILE) "$script_dir/base.sdc" + + +# Floorplanning +# ------------- + +set ::env(FP_PIN_ORDER_CFG) $::env(DESIGN_DIR)/pin_order.cfg +set ::env(FP_SIZING) "absolute" +set ::env(DIE_AREA) [list 0.0 0.0 100.0 100.0] + + + + +set ::env(FP_PDN_VPITCH) 50 +set ::env(PDN_CFG) $script_dir/pdn.tcl + +set ::env(FP_VERTICAL_HALO) 6 +set ::env(PL_TARGET_DENSITY) 0.52 +set ::env(PL_TARGET_DENSITY_CELLS) 0.38 +set ::env(PL_OPENPHYSYN_OPTIMIZATIONS) 1 +set ::env(CELL_PAD) 4 + +set ::env(GLB_RT_ADJUSTMENT) 0 +set ::env(GLB_RT_L2_ADJUSTMENT) 0.2 +set ::env(GLB_RT_L3_ADJUSTMENT) 0.25 +set ::env(GLB_RT_L4_ADJUSTMENT) 0.2 +set ::env(GLB_RT_L5_ADJUSTMENT) 0.1 +set ::env(GLB_RT_L6_ADJUSTMENT) 0.1 +set ::env(GLB_RT_TILES) 14 +set ::env(GLB_RT_MAXLAYER) 5 + +set ::env(DIODE_INSERTION_STRATEGY) 4 + +
diff --git a/openlane/uart/pdn.tcl b/openlane/uart/pdn.tcl new file mode 100644 index 0000000..1fe689b --- /dev/null +++ b/openlane/uart/pdn.tcl
@@ -0,0 +1,49 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# SPDX-License-Identifier: Apache-2.0 + +# Power nets +set ::power_nets $::env(VDD_PIN) +set ::ground_nets $::env(GND_PIN) + +set ::macro_blockage_layer_list "li1 met1 met2 met3 met4 met5" + +pdngen::specify_grid stdcell { + name grid + rails { + met1 {width 0.48 pitch $::env(PLACE_SITE_HEIGHT) offset 0} + } + straps { + met4 {width 1.6 pitch $::env(FP_PDN_VPITCH) offset $::env(FP_PDN_VOFFSET)} + met5 {width 1.6 pitch $::env(FP_PDN_HPITCH) offset $::env(FP_PDN_HOFFSET)} + } + connect {{met1 met4} {met4 met5}} +} + +pdngen::specify_grid macro { + power_pins "VPWR" + ground_pins "VGND" + blockages "li1 met1 met2 met3 met4" + straps { + } + connect {{met4_PIN_ver met5}} +} + +set ::halo 5 + +# POWER or GROUND #Std. cell rails starting with power or ground rails at the bottom of the core area +set ::rails_start_with "POWER" ; + +# POWER or GROUND #Upper metal stripes starting with power or ground rails at the left/bottom of the core area +set ::stripes_start_with "POWER" ;
diff --git a/openlane/uart/pin_order.cfg b/openlane/uart/pin_order.cfg new file mode 100644 index 0000000..f7b568d --- /dev/null +++ b/openlane/uart/pin_order.cfg
@@ -0,0 +1,16 @@ +#BUS_SORT + +#N +app_clk +arst_n +si +so + +#S +reg_cs +reg_wr +reg_addr.* +reg_be +reg_wdata.* +reg_rdata.* +reg_ack
diff --git a/verilog/dv/agents/uart_agent.v b/verilog/dv/agents/uart_agent.v new file mode 100644 index 0000000..4c9d05d --- /dev/null +++ b/verilog/dv/agents/uart_agent.v
@@ -0,0 +1,321 @@ + +module uart_agent ( + mclk, + txd, + rxd + ); + +input mclk; +output txd; + +input rxd; + +event uart_read_done, uart_write_done; +event error_detected,uart_parity_error, uart_stop_error1, uart_stop_error2; +event uart_timeout_error; +event abort; + +reg [15:0] rx_count; +reg [15:0] tx_count; +reg [15:0] par_err_count; +reg [15:0] stop_err1_cnt; +reg [15:0] stop_err2_cnt; +reg [15:0] timeout_err_cnt; +reg [15:0] err_cnt; + +reg txd, read, write; +wire uart_rx_clk; +reg uart_clk; +reg stop_err_check; + +integer timeout_count; +integer data_bit_number; +reg [15:0] clk_count; + +reg error_ind; // 1 indicate error + +initial +begin + txd = 1'b1; + uart_clk = 0; + clk_count = 0; + stop_err_check = 0; + error_ind = 0; +end + +always @(posedge mclk) +begin + if (clk_count == 'h0) begin + uart_clk = ~uart_clk; + clk_count = control_setup.divisor; + end else begin + clk_count = clk_count - 1; + end +end +assign uart_rx_clk = ~uart_clk; + +always @(posedge mclk) +begin + timeout_count = timeout_count + 1; + if (timeout_count == (control_setup.maxtime * 16)) + -> abort; +end + +always @uart_read_done + rx_count = rx_count + 1; + +always @uart_write_done + tx_count = tx_count + 1; + +always @uart_parity_error begin + error_ind = 1; + par_err_count = par_err_count + 1; +end + +always @uart_stop_error1 begin + error_ind = 1; + stop_err1_cnt = stop_err1_cnt + 1; +end + +always @uart_stop_error2 begin + error_ind = 1; + stop_err2_cnt = stop_err2_cnt + 1; +end + +always @uart_timeout_error begin + error_ind = 1; + timeout_err_cnt = timeout_err_cnt + 1; +end + + +always @error_detected begin + error_ind = 1; + err_cnt = err_cnt + 1; +end + + +//////////////////////////////////////////////////////////////////////////////// +task uart_init; +begin + read = 0; + write = 0; + tx_count = 0; + rx_count = 0; + stop_err_check = 0; + par_err_count = 0; + stop_err1_cnt = 0; + stop_err2_cnt = 0; + timeout_err_cnt = 0; + err_cnt = 0; + +end +endtask + + +//////////////////////////////////////////////////////////////////////////////// +task read_char_chk; +input expected_data; + +integer i; +reg [7:0] expected_data; +reg [7:0] data; +reg parity; + +begin + data <= 8'h0; + parity <= 1; + timeout_count = 0; + +fork + begin : loop_1 + @(abort) + $display ("%m: >>>>> Exceed time limit, uart no responce.\n"); + ->uart_timeout_error; + disable loop_2; + end + + begin : loop_2 + +// start cycle + @(negedge rxd) + disable loop_1; + read <= 1; + +// data cycle + @(posedge uart_rx_clk); + for (i = 0; i < data_bit_number; i = i + 1) + begin + @(posedge uart_rx_clk) + data[i] <= rxd; + parity <= parity ^ rxd; + end + +// parity cycle + if(control_setup.parity_en) + begin + @(posedge uart_rx_clk); + if ((control_setup.even_odd_parity && (rxd == parity)) || + (!control_setup.even_odd_parity && (rxd != parity))) + begin + $display ("%m: >>>>> Parity Error"); + -> error_detected; + -> uart_parity_error; + end + end + +// stop cycle 1 + @(posedge uart_rx_clk); + if (!rxd) + begin + $display ("%m: >>>>> Stop signal 1 Error"); + -> error_detected; + -> uart_stop_error1; + end + +// stop cycle 2 + if (control_setup.stop_bit_number) + begin + @(posedge uart_rx_clk); // stop cycle 2 + if (!rxd) + begin + $display ("%m: >>>>> Stop signal 2 Error"); + -> error_detected; + -> uart_stop_error2; + end + end + + +// wait another half cycle for tx_done signal + @(negedge uart_rx_clk); + read <= 0; + -> uart_read_done; + + if (expected_data != data) + begin + $display ("%m: Error! Data return is %h, expecting %h", data, expected_data); + -> error_detected; + end + else + $display ("%m: Data match %h", expected_data); + + $display ("%m:... Read Data from UART done cnt :%d...",rx_count +1); + end +join + +end + +endtask + + +//////////////////////////////////////////////////////////////////////////////// +task write_char; +input [7:0] data; + +integer i; +reg parity; // 0: odd parity, 1: even parity + +begin + parity <= #1 1; + +// start cycle + @(posedge uart_clk) + begin + txd <= #1 0; + write <= #1 1; + end + +// data cycle + begin + for (i = 0; i < data_bit_number; i = i + 1) + begin + @(posedge uart_clk) + txd <= #1 data[i]; + parity <= parity ^ data[i]; + end + end + +// parity cycle + if (control_setup.parity_en) + begin + @(posedge uart_clk) + txd <= #1 +// control_setup.stick_parity ? ~control_setup.even_odd_parity : + control_setup.even_odd_parity ? !parity : parity; + end + +// stop cycle 1 + @(posedge uart_clk) + txd <= #1 stop_err_check ? 0 : 1; + +// stop cycle 2 + @(posedge uart_clk); + txd <= #1 1; + if (data_bit_number == 5) + @(negedge uart_clk); + else if (control_setup.stop_bit_number) + @(posedge uart_clk); + + write <= #1 0; + $display ("%m:... Write data %h to UART done cnt : %d ...\n", data,tx_count+1); + -> uart_write_done; +end +endtask + + +//////////////////////////////////////////////////////////////////////////////// +task control_setup; +input [1:0] data_bit_set; +input stop_bit_number; +input parity_en; +input even_odd_parity; +input stick_parity; +input [15:0] maxtime; +input [15:0] divisor; + +begin + clk_count = divisor; + data_bit_number = data_bit_set + 5; +end +endtask + + +//////////////////////////////////////////////////////////////////////////////// +task report_status; +output [15:0] rx_nu; +output [15:0] tx_nu; +begin + $display ("-------------------- UART Reporting Configuration --------------------"); + $display (" Data bit number setting is : %0d", data_bit_number); + $display (" Stop bit number setting is : %0d", control_setup.stop_bit_number + 1); + $display (" Divisor of Uart clock is : %0d", control_setup.divisor); + if (control_setup.parity_en) + $display (" Parity is enable"); + else + $display (" Parity is disable"); + + if (control_setup.even_odd_parity) + $display (" Even parity setting"); + else + $display (" Odd parity setting"); + + + $display ("-----------------------------------------------------------------"); + + $display ("-------------------- Reporting Status --------------------\n"); + $display (" Number of character received is : %d", rx_count); + $display (" Number of character sent is : %d", tx_count); + $display (" Number of parity error rxd is : %d", par_err_count); + $display (" Number of stop1 error rxd is : %d", stop_err1_cnt); + $display (" Number of stop2 error rxd is : %d", stop_err2_cnt); + $display (" Number of timeout error is : %d", timeout_err_cnt); + $display (" Number of error is : %d", err_cnt); + $display ("-----------------------------------------------------------------"); + + rx_nu = rx_count; + tx_nu = tx_count; +end +endtask + + +//////////////////////////////////////////////////////////////////////////////// +endmodule
diff --git a/verilog/dv/user_uart/.user_uart.c.un~ b/verilog/dv/user_uart/.user_uart.c.un~ new file mode 100644 index 0000000..5835313 --- /dev/null +++ b/verilog/dv/user_uart/.user_uart.c.un~ Binary files differ
diff --git a/verilog/dv/user_uart/Makefile b/verilog/dv/user_uart/Makefile new file mode 100644 index 0000000..1ec201f --- /dev/null +++ b/verilog/dv/user_uart/Makefile
@@ -0,0 +1,83 @@ +# SPDX-FileCopyrightText: 2020 Efabless Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +## Caravel Pointers +CARAVEL_ROOT ?= ../../../caravel +CARAVEL_PATH ?= $(CARAVEL_ROOT) +CARAVEL_FIRMWARE_PATH = $(CARAVEL_PATH)/verilog/dv/caravel +CARAVEL_VERILOG_PATH = $(CARAVEL_PATH)/verilog +CARAVEL_RTL_PATH = $(CARAVEL_VERILOG_PATH)/rtl +CARAVEL_BEHAVIOURAL_MODELS = $(CARAVEL_VERILOG_PATH)/dv/caravel + +## User Project Pointers +UPRJ_VERILOG_PATH ?= ../../../verilog +UPRJ_RTL_PATH = $(UPRJ_VERILOG_PATH)/rtl +UPRJ_BEHAVIOURAL_MODELS = ../model +UPRJ_INCLUDE_PATH1 = $(UPRJ_RTL_PATH)/syntacore/scr1/src/includes +UPRJ_INCLUDE_PATH2 = $(UPRJ_RTL_PATH)/sdram_ctrl/src/defs + +## RISCV GCC +GCC_PATH?=/ef/apps/bin +GCC_PREFIX?=riscv64-unknown-elf +PDK_PATH?=/ef/tech/SW/sky130A + +## Simulation mode: RTL/GL +SIM?=RTL + +.SUFFIXES: + +PATTERN = user_uart + +all: ${PATTERN:=.vcd} + +hex: ${PATTERN:=.hex} + +vvp: ${PATTERN:=.vvp} + +%.vvp: %_tb.v %.hex +ifeq ($(SIM),RTL) + iverilog -g2005-sv -DFUNCTIONAL -DSIM -I $(PDK_PATH) \ + -I $(CARAVEL_BEHAVIOURAL_MODELS) -I $(CARAVEL_RTL_PATH) \ + -I $(UPRJ_BEHAVIOURAL_MODELS) -I $(UPRJ_RTL_PATH) \ + -I $(UPRJ_INCLUDE_PATH1) -I $(UPRJ_INCLUDE_PATH2) \ + $< -o $@ +else + iverilog -DFUNCTIONAL -DSIM -DGL -I $(PDK_PATH) \ + -I $(CARAVEL_BEHAVIOURAL_MODELS) -I $(CARAVEL_RTL_PATH) -I $(CARAVEL_VERILOG_PATH) \ + -I $(UPRJ_BEHAVIOURAL_MODELS) -I$(UPRJ_RTL_PATH) -I $(UPRJ_VERILOG_PATH) \ + $< -o $@ +endif + +%.vcd: %.vvp + vvp $< + +%.elf: %.c $(CARAVEL_FIRMWARE_PATH)/sections.lds $(CARAVEL_FIRMWARE_PATH)/start.s + ${GCC_PREFIX}-gcc -I $(CARAVEL_PATH) -march=rv32imc -mabi=ilp32 -Wl,-Bstatic,-T,$(CARAVEL_FIRMWARE_PATH)/sections.lds,--strip-debug -ffreestanding -nostdlib -o $@ $(CARAVEL_FIRMWARE_PATH)/start.s $< + +%.hex: %.elf + ${GCC_PREFIX}-objcopy -O verilog $< $@ + # to fix flash base address + sed -i 's/@10000000/@00000000/g' $@ + +%.bin: %.elf + ${GCC_PREFIX}-objcopy -O binary $< /dev/stdout | tail -c +1048577 > $@ + +# ---- Clean ---- + +clean: + rm -f *.elf *.hex *.bin *.vvp *.vcd *.log + +.PHONY: clean hex all
diff --git a/verilog/dv/user_uart/run_iverilog b/verilog/dv/user_uart/run_iverilog new file mode 100644 index 0000000..6f95c23 --- /dev/null +++ b/verilog/dv/user_uart/run_iverilog
@@ -0,0 +1,20 @@ +riscv64-unknown-elf-gcc -O2 -funroll-loops -fpeel-loops -fgcse-sm -fgcse-las -D__RVC_EXT -static -std=gnu99 -fno-common -fno-builtin-printf -DTCM=1 -Wa,-march=rv32imc -march=rv32imc -mabi=ilp32 -DFLAGS_STR=\""-O2 -funroll-loops -fpeel-loops -fgcse-sm -fgcse-las "\" -c -I./ -I../../rtl/syntacore/scr1/sim/tests/common user_uart.c -o user_uart.o + +riscv64-unknown-elf-gcc -O2 -funroll-loops -fpeel-loops -fgcse-sm -fgcse-las -D__RVC_EXT -static -std=gnu99 -fno-common -fno-builtin-printf -DTCM=1 -Wa,-march=rv32imc -march=rv32imc -mabi=ilp32 -DFLAGS_STR=\""-O2 -funroll-loops -fpeel-loops -fgcse-sm -fgcse-las "\" -D__ASSEMBLY__=1 -c -I./ -I../../rtl/syntacore/scr1/sim/tests/common/ ../../rtl/syntacore/scr1/sim/tests/common/crt_tcm.S -o crt_tcm.o + +riscv64-unknown-elf-gcc -o user_uart.elf -T ../../rtl/syntacore/scr1/sim/tests/common/link_tcm.ld user_uart.o crt_tcm.o -nostartfiles -nostdlib -lc -lgcc -march=rv32imc -mabi=ilp32 + +riscv64-unknown-elf-objcopy -O verilog user_uart.elf user_uart.hex + +riscv64-unknown-elf-objdump -D user_uart.elf > user_uart.dump + +rm crt_tcm.o user_uart.o + +#iverilog with waveform dump +#iverilog -g2005-sv -DWFDUMP -I $PDK_PATH -I ../ -I ../../../verilog/rtl -I ../../../verilog/rtl/syntacore/scr1/src/includes -I ../../../verilog/rtl/sdram_ctrl/src/defs -I $$CARAVEL_ROOT/verilog/dv/caravel -I ../model ../agents user_uart_tb.v -o user_uart_tb.vvp + +iverilog -g2005-sv -I $PDK_PATH -I ../ -I ../../../verilog/rtl -I ../../../verilog/rtl/syntacore/scr1/src/includes -I ../../../verilog/rtl/sdram_ctrl/src/defs -I $CARAVEL_ROOT/verilog/dv/caravel -I ../model -I ../agents user_uart_tb.v -o user_uart_tb.vvp + +vvp user_uart_tb.vvp | tee test.log + +\rm -rf user_uart_tb.vvp
diff --git a/verilog/dv/user_uart/uprj_netlists.v b/verilog/dv/user_uart/uprj_netlists.v new file mode 100644 index 0000000..0aa46db --- /dev/null +++ b/verilog/dv/user_uart/uprj_netlists.v
@@ -0,0 +1,82 @@ +// SPDX-FileCopyrightText: 2020 Efabless Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// SPDX-License-Identifier: Apache-2.0 + +// Include caravel global defines for the number of the user project IO pads +`define USE_POWER_PINS + + `include "spi_master/src/spim_top.sv" + `include "spi_master/src/spim_regs.sv" + `include "spi_master/src/spim_clkgen.sv" + `include "spi_master/src/spim_ctrl.sv" + `include "spi_master/src/spim_rx.sv" + `include "spi_master/src/spim_tx.sv" + + `include "uart/src/uart_core.sv" + `include "uart/src/uart_cfg.sv" + `include "uart/src/uart_rxfsm.sv" + `include "uart/src/uart_txfsm.sv" + `include "lib/async_fifo_th.sv" + `include "lib/reset_sync.sv" + + `include "sdram_ctrl/src/top/sdrc_top.v" + `include "sdram_ctrl/src/wb2sdrc/wb2sdrc.v" + `include "lib/async_fifo.sv" + `include "sdram_ctrl/src/core/sdrc_core.v" + `include "sdram_ctrl/src/core/sdrc_bank_ctl.v" + `include "sdram_ctrl/src/core/sdrc_bank_fsm.v" + `include "sdram_ctrl/src/core/sdrc_bs_convert.v" + `include "sdram_ctrl/src/core/sdrc_req_gen.v" + `include "sdram_ctrl/src/core/sdrc_xfr_ctl.v" + + `include "lib/registers.v" + `include "lib/clk_ctl.v" + `include "digital_core/src/glbl_cfg.sv" + `include "digital_core/src/digital_core.sv" + + `include "lib/wb_stagging.sv" + `include "wb_interconnect/src/wb_arb.sv" + `include "wb_interconnect/src/wb_interconnect.sv" + + + `include "syntacore/scr1/src/core/pipeline/scr1_pipe_hdu.sv" + `include "syntacore/scr1/src/core/pipeline/scr1_pipe_tdu.sv" + `include "syntacore/scr1/src/core/pipeline/scr1_ipic.sv" + `include "syntacore/scr1/src/core/pipeline/scr1_pipe_csr.sv" + `include "syntacore/scr1/src/core/pipeline/scr1_pipe_exu.sv" + `include "syntacore/scr1/src/core/pipeline/scr1_pipe_ialu.sv" + `include "syntacore/scr1/src/core/pipeline/scr1_pipe_idu.sv" + `include "syntacore/scr1/src/core/pipeline/scr1_pipe_ifu.sv" + `include "syntacore/scr1/src/core/pipeline/scr1_pipe_lsu.sv" + `include "syntacore/scr1/src/core/pipeline/scr1_pipe_mprf.sv" + `include "syntacore/scr1/src/core/pipeline/scr1_pipe_top.sv" + `include "syntacore/scr1/src/core/primitives/scr1_reset_cells.sv" + `include "syntacore/scr1/src/core/primitives/scr1_cg.sv" + `include "syntacore/scr1/src/core/scr1_clk_ctrl.sv" + `include "syntacore/scr1/src/core/scr1_tapc_shift_reg.sv" + `include "syntacore/scr1/src/core/scr1_tapc.sv" + `include "syntacore/scr1/src/core/scr1_tapc_synchronizer.sv" + `include "syntacore/scr1/src/core/scr1_core_top.sv" + `include "syntacore/scr1/src/core/scr1_dm.sv" + `include "syntacore/scr1/src/core/scr1_dmi.sv" + `include "syntacore/scr1/src/core/scr1_scu.sv" + + `include "syntacore/scr1/src/top/scr1_dmem_router.sv" + `include "syntacore/scr1/src/top/scr1_dp_memory.sv" + `include "syntacore/scr1/src/top/scr1_tcm.sv" + `include "syntacore/scr1/src/top/scr1_timer.sv" + `include "syntacore/scr1/src/top/scr1_dmem_wb.sv" + `include "syntacore/scr1/src/top/scr1_imem_wb.sv" + `include "syntacore/scr1/src/top/scr1_top_wb.sv" + `include "lib/sync_fifo.sv"
diff --git a/verilog/dv/user_uart/user_uart.c b/verilog/dv/user_uart/user_uart.c new file mode 100644 index 0000000..cb8c107 --- /dev/null +++ b/verilog/dv/user_uart/user_uart.c
@@ -0,0 +1,43 @@ + +#define SC_SIM_OUTPORT (0xf0000000) +#define uint32_t long + +#define reg_mprj_globl_reg0 (*(volatile uint32_t*)0x30000000) +#define reg_mprj_globl_reg1 (*(volatile uint32_t*)0x30000004) +#define reg_mprj_globl_reg2 (*(volatile uint32_t*)0x30000008) +#define reg_mprj_globl_reg3 (*(volatile uint32_t*)0x3000000C) +#define reg_mprj_globl_reg4 (*(volatile uint32_t*)0x30000010) +#define reg_mprj_globl_reg5 (*(volatile uint32_t*)0x30000014) +#define reg_mprj_globl_reg6 (*(volatile uint32_t*)0x30000018) +#define reg_mprj_globl_reg7 (*(volatile uint32_t*)0x3000001C) +#define reg_mprj_globl_reg8 (*(volatile uint32_t*)0x30000020) +#define reg_mprj_globl_reg9 (*(volatile uint32_t*)0x30000024) +#define reg_mprj_globl_reg10 (*(volatile uint32_t*)0x30000028) +#define reg_mprj_globl_reg11 (*(volatile uint32_t*)0x3000002C) +#define reg_mprj_globl_reg12 (*(volatile uint32_t*)0x30000030) +#define reg_mprj_globl_reg13 (*(volatile uint32_t*)0x30000034) +#define reg_mprj_globl_reg14 (*(volatile uint32_t*)0x30000038) +#define reg_mprj_globl_reg15 (*(volatile uint32_t*)0x3000003C) + +#define reg_mprj_uart_reg0 (*(volatile uint32_t*)0x30010000) +#define reg_mprj_uart_reg1 (*(volatile uint32_t*)0x30010004) +#define reg_mprj_uart_reg2 (*(volatile uint32_t*)0x30010008) +#define reg_mprj_uart_reg3 (*(volatile uint32_t*)0x3001000C) +#define reg_mprj_uart_reg4 (*(volatile uint32_t*)0x30010010) +#define reg_mprj_uart_reg5 (*(volatile uint32_t*)0x30010014) +#define reg_mprj_uart_reg6 (*(volatile uint32_t*)0x30010018) +#define reg_mprj_uart_reg7 (*(volatile uint32_t*)0x3001001C) +#define reg_mprj_uart_reg8 (*(volatile uint32_t*)0x30010020) + +int main() +{ + + while(1) { + // Check UART RX fifo has data, if available loop back the data + if(reg_mprj_uart_reg8 != 0) { + reg_mprj_uart_reg5 = reg_mprj_uart_reg6; + } + } + + return 0; +}
diff --git a/verilog/dv/user_uart/user_uart_tb.v b/verilog/dv/user_uart/user_uart_tb.v new file mode 100644 index 0000000..84938f5 --- /dev/null +++ b/verilog/dv/user_uart/user_uart_tb.v
@@ -0,0 +1,423 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Standalone User validation Test bench //// +//// //// +//// This file is part of the YIFive cores project //// +//// http://www.opencores.org/cores/yifive/ //// +//// //// +//// Description //// +//// This is a standalone test bench to validate the //// +//// Digital core. //// +//// 1. User Risc core is booted using compiled code of //// +//// user_risc_boot.c //// +//// 2. User Risc core uses Serial Flash and SDRAM to boot //// +//// 3. After successful boot, Risc core will check the UART //// +//// RX Data, If it's available then it loop back the same //// +//// data in uart tx //// +//// 4. Test bench send random 40 character towards User uart //// +//// and expect same data to return back //// +//// //// +//// To Do: //// +//// nothing //// +//// //// +//// Author(s): //// +//// - Dinesh Annayya, dinesha@opencores.org //// +//// //// +//// Revision : //// +//// 0.1 - 16th Feb 2021, Dinesh A //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + +`default_nettype none + +`timescale 1 ns / 1 ps + +`include "uprj_netlists.v" +`include "spiflash.v" +`include "mt48lc8m8a2.v" +`include "uart_agent.v" + + +`define ADDR_SPACE_UART = 32'h3001_0000; + + +task user_uart_tb; + +reg clock ; +reg RSTB ; +reg power1, power2; +reg power3, power4; + +reg wbd_ext_cyc_i ; // strobe/request +reg wbd_ext_stb_i ; // strobe/request +reg [31:0] wbd_ext_adr_i ; // address +reg wbd_ext_we_i ; // write +reg [31:0] wbd_ext_dat_i ; // data output +reg [3:0] wbd_ext_sel_i ; // byte enable + +wire [31:0] wbd_ext_dat_o ; // data input +wire wbd_ext_ack_o ; // acknowlegement +wire wbd_ext_err_o ; // error + +// User I/O +wire [37:0] io_oeb ; +wire [37:0] io_out ; +wire [37:0] io_in ; + +wire [37:0] mprj_io ; +wire [7:0] mprj_io_0 ; +reg test_fail ; +reg [31:0] read_data ; +//---------------------------------- +// Uart Configuration +// --------------------------------- +reg [1:0] uart_data_bit ; +reg uart_stop_bits ; // 0: 1 stop bit; 1: 2 stop bit; +reg uart_stick_parity ; // 1: force even parity +reg uart_parity_en ; // parity enable +reg uart_even_odd_parity ; // 0: odd parity; 1: even parity + +reg [7:0] uart_data ; +reg [15:0] uart_divisor ; // divided by n * 16 +reg [15:0] uart_timeout ;// wait time limit + +reg [15:0] uart_rx_nu ; +reg [15:0] uart_tx_nu ; +reg [7:0] uart_write_data [0:39]; +reg uart_fifo_enable ; // fifo mode disable + +integer i,j; + + + +initial +begin + uart_data_bit = 2'b11; + uart_stop_bits = 0; // 0: 1 stop bit; 1: 2 stop bit; + uart_stick_parity = 0; // 1: force even parity + uart_parity_en = 0; // parity enable + uart_even_odd_parity = 1; // 0: odd parity; 1: even parity + uart_divisor = 15;// divided by n * 16 + uart_timeout = 500;// wait time limit + uart_fifo_enable = 0; // fifo mode disable + + #200; // Wait for reset removal + repeat (10) @(posedge clock); + $display("Monitor: Standalone User Risc Boot Test Started"); + + #1; + //------------ SDRAM Config - 2 + wb_user_core_write('h3000_0014,'h100_019E); + + repeat (2) @(posedge clock); + #1; + //------------ SDRAM Config - 1 + wb_user_core_write('h3000_0010,'h2F17_2242); + + repeat (2) @(posedge clock); + #1; + // Remove all the reset + wb_user_core_write('h3000_0000,'h7); + + repeat (2000) @(posedge app_clk); // wait for Processor Get Ready + tb_uart.uart_init; + wb_user_core_write(`ADDR_SPACE_UART+8'h0,{3'h0,2'b00,1'b1,1'b1,1'b1}); + + + for (i=0; i<40; i=i+1) + uart_write_data[i] = $random; + + + tb_top.tb_uart.control_setup (uart_data_bit, uart_stop_bits, uart_parity_en, uart_even_odd_parity, + uart_stick_parity, uart_timeout, uart_divisor, uart_fifo_enable); + + fork + begin + for (i=0; i<40; i=i+1) + begin + $display ("\n... UART Agent Writing char %x ...", write_data[i]); + tb_top.tb_uart.write_char (uart_write_data[i]); + end + end + + begin + for (j=0; j<40; j=j+1) + begin + tb_top.tb_uart.read_char_chk(uart_write_data[j]); + end + end + join + + #100 + tb_top.tb_uart.report_status(rx_nu, tx_nu); + + test_fail = 0; + wb_user_core_read(32'h30000018,read_data); + + // Check + // if all the 40 byte transmitted + // if all the 40 byte received + // if no error + if(tx_nu != 40) test_fail = 1; + if(rx_nu != 40) test_fail = 1; + if(tb_top.tb_uart.err_cnt != 0) test_fail = 1; + + $display("###################################################"); + if(test_fail == 0) begin + `ifdef GL + $display("Monitor: Standalone User UART Test (GL) Passed"); + `else + $display("Monitor: Standalone User UART Test (RTL) Passed"); + `endif + end else begin + `ifdef GL + $display("Monitor: Standalone User UART Test (GL) Failed"); + `else + $display("Monitor: Standalone User UART Test (RTL) Failed"); + `endif + end + $display("###################################################"); + #100 + $finish; +end + + +digital_core u_core( +`ifdef USE_POWER_PINS + .vdda1(), // User area 1 3.3V supply + .vdda2(), // User area 2 3.3V supply + .vssa1(), // User area 1 analog ground + .vssa2(), // User area 2 analog ground + .vccd1(), // User area 1 1.8V supply + .vccd2(), // User area 2 1.8v supply + .vssd1(), // User area 1 digital ground + .vssd2(), // User area 2 digital ground +`endif + .wb_clk_i (clock), // System clock + .rtc_clk (1'b1), // Real-time clock + .wb_rst_i (RSTB), // Regular Reset signal + + .wbd_ext_cyc_i (wbd_ext_cyc_i), // strobe/request + .wbd_ext_stb_i (wbd_ext_stb_i), // strobe/request + .wbd_ext_adr_i (wbd_ext_adr_i), // address + .wbd_ext_we_i (wbd_ext_we_i), // write + .wbd_ext_dat_i (wbd_ext_dat_i), // data output + .wbd_ext_sel_i (wbd_ext_sel_i), // byte enable + + .wbd_ext_dat_o (wbd_ext_dat_o), // data input + .wbd_ext_ack_o (wbd_ext_ack_o), // acknowlegement + .wbd_ext_err_o (wbd_ext_err_o), // error + + + // Logic Analyzer Signals + .la_data_in ('0) , + .la_data_out (), + .la_oenb ('0), + + + // IOs + .io_in (io_in) , + .io_out (io_out) , + .io_oeb (io_oeb) , + + .user_irq () + +); + +//------------------------------------------------------ +// Integrate the Serial flash with qurd support to +// user core using the gpio pads +// ---------------------------------------------------- + + wire flash_clk = io_out[30]; + wire flash_csb = io_out[31]; + tri flash_io0 = (io_oeb[32]== 1'b0) ? io_out[32] : 1'bz; + tri flash_io1 = (io_oeb[33]== 1'b0) ? io_out[33] : 1'bz; + tri flash_io2 = (io_oeb[34]== 1'b0) ? io_out[34] : 1'bz; + tri flash_io3 = (io_oeb[35]== 1'b0) ? io_out[35] : 1'bz; + + assign io_in[32] = flash_io0; + assign io_in[33] = flash_io1; + assign io_in[34] = flash_io2; + assign io_in[35] = flash_io3; + + + // Quard flash + spiflash #( + .FILENAME("user_uart.hex") + ) u_user_spiflash ( + .csb(flash_csb), + .clk(flash_clk), + .io0(flash_io0), + .io1(flash_io1), + .io2(flash_io2), + .io3(flash_io3) + ); + + +//------------------------------------------------ +// Integrate the SDRAM 8 BIT Memory +// ----------------------------------------------- + +wire [7:0] Dq ; // SDRAM Read/Write Data Bus +wire [0:0] sdr_dqm ; // SDRAM DATA Mask +wire [1:0] sdr_ba ; // SDRAM Bank Select +wire [12:0] sdr_addr ; // SDRAM ADRESS +wire sdr_cs_n ; // chip select +wire sdr_cke ; // clock gate +wire sdr_ras_n ; // ras +wire sdr_cas_n ; // cas +wire sdr_we_n ; // write enable +wire sdram_clk ; + +assign Dq[7:0] = (io_oeb[7:0] == 8'h0) ? io_out [7:0] : 8'hZZ; +assign sdr_addr[12:0] = io_out [20:8] ; +assign sdr_ba[1:0] = io_out [22:21] ; +assign sdr_dqm[0] = io_out [23] ; +assign sdr_we_n = io_out [24] ; +assign sdr_cas_n = io_out [25] ; +assign sdr_ras_n = io_out [26] ; +assign sdr_cs_n = io_out [27] ; +assign sdr_cke = io_out [28] ; +assign sdram_clk = io_out [29] ; +assign io_in[29] = sdram_clk; +assign #(1) io_in[7:0] = Dq; + +// to fix the sdram interface timing issue +wire #(1) sdram_clk_d = sdram_clk; + + // SDRAM 8bit +mt48lc8m8a2 #(.data_bits(8)) u_sdram8 ( + .Dq (Dq ) , + .Addr (sdr_addr[11:0] ), + .Ba (sdr_ba ), + .Clk (sdram_clk_d ), + .Cke (sdr_cke ), + .Cs_n (sdr_cs_n ), + .Ras_n (sdr_ras_n ), + .Cas_n (sdr_cas_n ), + .We_n (sdr_we_n ), + .Dqm (sdr_dqm ) + ); + + +//--------------------------- +// UART Agent integration +// -------------------------- +wire uart_txd,uart_rxd; + +assign uart_txd = io_out[37]; +assign io_in[36] = uart_rxd ; + +uart_agent tb_uart( + .mclk (clock ), + .txd (uart_rxd ), + .rxd (uart_txd ) + ); + + +task wb_user_core_write; +input [31:0] address; +input [31:0] data; +begin + repeat (1) @(posedge clock); + wbd_ext_adr_i =address; // address + wbd_ext_we_i ='h1; // write + wbd_ext_dat_i =data; // data output + wbd_ext_sel_i ='hF; // byte enable + wbd_ext_cyc_i ='h1; // strobe/request + wbd_ext_stb_i ='h1; // strobe/request + wait(wbd_ext_ack_o == 1); + repeat (1) @(posedge clock); + wbd_ext_cyc_i ='h0; // strobe/request + wbd_ext_stb_i ='h0; // strobe/request + wbd_ext_adr_i ='h0; // address + wbd_ext_we_i ='h0; // write + wbd_ext_dat_i ='h0; // data output + wbd_ext_sel_i ='h0; // byte enable + $display("DEBUG WB USER ACCESS WRITE Address : %x, Data : %x",address,data); + repeat (2) @(posedge clock); +end +endtask + +task wb_user_core_read; +input [31:0] address; +output [31:0] data; +reg [31:0] data; +begin + repeat (1) @(posedge clock); + wbd_ext_adr_i =address; // address + wbd_ext_we_i ='h0; // write + wbd_ext_dat_i ='0; // data output + wbd_ext_sel_i ='hF; // byte enable + wbd_ext_cyc_i ='h1; // strobe/request + wbd_ext_stb_i ='h1; // strobe/request + wait(wbd_ext_ack_o == 1); + data = wbd_ext_dat_o; + repeat (1) @(posedge clock); + wbd_ext_cyc_i ='h0; // strobe/request + wbd_ext_stb_i ='h0; // strobe/request + wbd_ext_adr_i ='h0; // address + wbd_ext_we_i ='h0; // write + wbd_ext_dat_i ='h0; // data output + wbd_ext_sel_i ='h0; // byte enable + $display("DEBUG WB USER ACCESS READ Address : %x, Data : %x",address,data); + repeat (2) @(posedge clock); +end +endtask + + + + +////----------------------------------------------------------------------------- +//// RISC IMEM amd DMEM Monitoring TASK +////----------------------------------------------------------------------------- +//logic [`SCR1_DMEM_AWIDTH-1:0] core2imem_addr_o_r; // DMEM address +//logic [`SCR1_DMEM_AWIDTH-1:0] core2dmem_addr_o_r; // DMEM address +//logic core2dmem_cmd_o_r; +// +//`define RISC_CORE user_uart_tb.u_core.u_riscv_top.i_core_top +// +//always@(posedge `RISC_CORE.clk) begin +// if(`RISC_CORE.imem2core_req_ack_i && `RISC_CORE.core2imem_req_o) +// core2imem_addr_o_r <= `RISC_CORE.core2imem_addr_o; +// +// if(`RISC_CORE.dmem2core_req_ack_i && `RISC_CORE.core2dmem_req_o) begin +// core2dmem_addr_o_r <= `RISC_CORE.core2dmem_addr_o; +// core2dmem_cmd_o_r <= `RISC_CORE.core2dmem_cmd_o; +// end +// +// if(`RISC_CORE.imem2core_resp_i !=0) +// $display("RISCV-DEBUG => IMEM ADDRESS: %x Read Data : %x Resonse: %x", core2imem_addr_o_r,`RISC_CORE.imem2core_rdata_i,`RISC_CORE.imem2core_resp_i); +// if((`RISC_CORE.dmem2core_resp_i !=0) && core2dmem_cmd_o_r) +// $display("RISCV-DEBUG => DMEM ADDRESS: %x Write Data: %x Resonse: %x", core2dmem_addr_o_r,`RISC_CORE.core2dmem_wdata_o,`RISC_CORE.dmem2core_resp_i); +// if((`RISC_CORE.dmem2core_resp_i !=0) && !core2dmem_cmd_o_r) +// $display("RISCV-DEBUG => DMEM ADDRESS: %x READ Data : %x Resonse: %x", core2dmem_addr_o_r,`RISC_CORE.dmem2core_rdata_i,`RISC_CORE.dmem2core_resp_i); +//end +endmodule +`default_nettype wire
diff --git a/verilog/rtl/digital_core/src/digital_core.sv b/verilog/rtl/digital_core/src/digital_core.sv index 41fbf83..405df05 100644 --- a/verilog/rtl/digital_core/src/digital_core.sv +++ b/verilog/rtl/digital_core/src/digital_core.sv
@@ -31,15 +31,18 @@ //// 4. buswidth warning are fixed inside spi_master //// //// modified rtl files are //// //// verilog/rtl/digital_core/src/digital_core.sv //// -/// verilog/rtl/digital_core/src/glbl_cfg.sv //// -/// verilog/rtl/lib/wb_stagging.sv //// -/// verilog/rtl/syntacore/scr1/src/top/scr1_dmem_wb.sv //// -/// verilog/rtl/syntacore/scr1/src/top/scr1_imem_wb.sv //// -/// verilog/rtl/syntacore/scr1/src/top/scr1_top_wb.sv //// -/// verilog/rtl/user_project_wrapper.v //// -/// verilog/rtl/wb_interconnect/src/wb_interconnect.sv //// -/// verilog/rtl/spi_master/src/spim_clkgen.sv //// -/// verilog/rtl/spi_master/src/spim_ctrl.sv //// +//// verilog/rtl/digital_core/src/glbl_cfg.sv //// +//// verilog/rtl/lib/wb_stagging.sv //// +//// verilog/rtl/syntacore/scr1/src/top/scr1_dmem_wb.sv //// +//// verilog/rtl/syntacore/scr1/src/top/scr1_imem_wb.sv //// +//// verilog/rtl/syntacore/scr1/src/top/scr1_top_wb.sv //// +//// verilog/rtl/user_project_wrapper.v //// +//// verilog/rtl/wb_interconnect/src/wb_interconnect.sv //// +//// verilog/rtl/spi_master/src/spim_clkgen.sv //// +//// verilog/rtl/spi_master/src/spim_ctrl.sv //// +//// 0.3 - 20th June 2021, Dinesh A //// +//// 1. uart core is integrated //// +//// 2. 3rd Slave ported added to wishbone interconnect //// //// //// ////////////////////////////////////////////////////////////////////// //// //// @@ -188,6 +191,18 @@ logic wbd_glbl_ack_i; // acknowlegement logic wbd_glbl_err_i; // error +//--------------------------------------------------------------------- +// Global Register Wishbone Interface +//--------------------------------------------------------------------- +logic wbd_uart_stb_o; // strobe/request +logic [7:0] wbd_uart_adr_o; // address +logic wbd_uart_we_o; // write +logic [7:0] wbd_uart_dat_o; // data output +logic wbd_uart_sel_o; // byte enable +logic wbd_uart_cyc_o ; +logic 7:0] wbd_uart_dat_i; // data input +logic wbd_uart_ack_i; // acknowlegement +logic wbd_uart_err_i; // error //---------------------------------------------------- // CPU Configuration @@ -200,6 +215,8 @@ logic [15:0] irq_lines ; logic soft_irq ; + .si ( uart_rx ), + .so ( uart_tx ) //------------------------------------------------ // Configuration Parameter //------------------------------------------------ @@ -296,12 +313,25 @@ assign io_oeb[34] = !spi_en_tx; // spi_dio2 assign io_oeb[35] = !spi_en_tx; // spi_dio3 +///////////////////////////////////////////////////////// +// uart interface +/////////////////////////////////////////////////////// + +logic uart_rx ; +logic uart_tx ; // for uart -assign io_oeb[36] = 1'b1; // Unused -assign io_oeb[37] = 1'b1; // Unused +assign io_oeb[36] = 1'b1; // Uart RX +assign uart_rx = io_in[36]; + +assign io_oeb[37] = 1'b0; // Uart TX +assign io_out[37] = uart_tx; + +///////////////////////////////////////////////////////// +// Generating acive low wishbone reset +// ////////////////////////////////////////////////////// wire wb_rst_n = !wb_rst_i; @@ -549,6 +579,17 @@ .s2_wbd_we_o (wbd_glbl_we_o ), .s2_wbd_cyc_o (wbd_glbl_cyc_o ), .s2_wbd_stb_o (wbd_glbl_stb_o ) + + // Slave 3 Interface + .s2_wbd_err_i (1'b0 ), + .s2_wbd_dat_i (wbd_uart_dat_i ), + .s2_wbd_ack_i (wbd_uart_ack_i ), + .s2_wbd_dat_o (wbd_uart_dat_o ), + .s2_wbd_adr_o (wbd_uart_adr_o ), + .s2_wbd_sel_o (wbd_uart_sel_o ), + .s2_wbd_we_o (wbd_uart_we_o ), + .s2_wbd_cyc_o (wbd_uart_cyc_o ), + .s2_wbd_stb_o (wbd_uart_stb_o ) ); glbl_cfg u_glbl_cfg ( @@ -607,6 +648,26 @@ ); +uart_core u_uart_core ( + arst_n (wb_rst_n ), // async reset + app_clk (wb_clk_i ), + + // Reg Bus Interface Signal + .reg_cs (wbd_uart_stb_o ), + .reg_wr (wbd_uart_we_o ), + .reg_addr (wbd_uart_adr_o[5:2] ), + .reg_wdata (wbd_uart_dat_o[7:0] ), + .reg_be (wbd_uart_sel_o ), + + // Outputs + .reg_rdata (wbd_uart_dat_i[7:0] ), + .reg_ack (wbd_uart_ack_i ), + + // Line Interface + .si ( uart_rx ), + .so ( uart_tx ) + + ); endmodule : digital_core
diff --git a/verilog/rtl/lib/reset_sync.sv b/verilog/rtl/lib/reset_sync.sv new file mode 100644 index 0000000..ea99a4a --- /dev/null +++ b/verilog/rtl/lib/reset_sync.sv
@@ -0,0 +1,83 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// Active low reset synchronization //// +//// //// +//// This file is part of the yifive cores project //// +//// http://www.opencores.org/cores/yifive/ //// +//// //// +//// Description: //// +//// Synchronize the active low reset to destination clock //// +//// //// +//// To Do: //// +//// nothing //// +//// //// +//// Author(s): //// +//// - Dinesh Annayya, dinesha@opencores.org //// +//// //// +//// Revision : //// +//// v0: June 17, 2021, Dinesh A //// +//// Initial version //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + +module reset_sync ( + scan_mode , + dclk , // Destination clock domain + arst_n , // active low async reset + srst_n + ); + +parameter WIDTH = 1; + +input scan_mode ; // test mode +input dclk ; // Destination clock +input arst_n ; // Async Reset +input srst_n ; // Sync Reset w.r.t dclk + + +reg in_data_s ; // One Cycle sync +reg in_data_2s ; // two Cycle sync + +assign srst_n = (scan_mode) ? arst_n : in_data_2s; + +always @(negedge arst_n or posedge dclk) +begin + if(arst_n == 1'b0) + begin + in_data_s <= 1'b0; + in_data_2s <= 1'b0; + end + else + begin + in_data_s <= 1'b1; + in_data_2s <= in_data_s; + end +end + + +endmodule
diff --git a/verilog/rtl/uart/src/uart_cfg.sv b/verilog/rtl/uart/src/uart_cfg.sv new file mode 100644 index 0000000..a979c77 --- /dev/null +++ b/verilog/rtl/uart/src/uart_cfg.sv
@@ -0,0 +1,387 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// UART Configuration //// +//// //// +//// This file is part of the YIFive cores project //// +//// http://www.opencores.org/cores/yifive/ //// +//// //// +//// Description //// +//// //// +//// To Do: //// +//// nothing //// +//// //// +//// Author(s): //// +//// - Dinesh Annayya, dinesha@opencores.org //// +//// //// +//// Revision : //// +//// 0.1 - 20th June 2021, Dinesh A //// +//// 1. initial version picked from //// +//// http://www.opencores.org/cores/oms8051mini //// +//// 0.2 - 20th June 2021, Dinesh A //// +//// tx and rx buffer status added into reg7 and reg8 //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + +module uart_cfg ( + + mclk, + reset_n, + + // Reg Bus Interface Signal + reg_cs, + reg_wr, + reg_addr, + reg_wdata, + reg_be, + + // Outputs + reg_rdata, + reg_ack, + + // Uart Tx fifo interface + tx_fifo_full, + tx_fifo_fspace, + tx_fifo_wr_en, + tx_fifo_data, + + // Uart Rx fifo interface + rx_fifo_empty, + rx_fifo_dval , + rx_fifo_rd_en, + rx_fifo_data , + + // configuration + cfg_tx_enable, + cfg_rx_enable, + cfg_stop_bit , + cfg_pri_mod , + cfg_baud_16x , + + frm_error_o, + par_error_o, + rx_fifo_full_err_o + + ); + + + +input mclk; +input reset_n; + +//-------------------------------- +// Uart Tx fifo interface +//-------------------------------- +input tx_fifo_full; +input [4:0] tx_fifo_fspace ; // Total Tx fifo Free Space +output tx_fifo_wr_en; +output [7:0] tx_fifo_data; + +//-------------------------------- +// Uart Rx fifo interface +//-------------------------------- +input rx_fifo_empty; +wire [4:0] rx_fifo_dval ; // Total Rx fifo Data Available +output rx_fifo_rd_en; +input [7:0] rx_fifo_data; + +//---------------------------------- +// configuration +//---------------------------------- +output cfg_tx_enable ; // Tx Enable +output cfg_rx_enable ; // Rx Enable +output cfg_stop_bit ; // 0 -> 1 Stop, 1 -> 2 Stop +output [1:0] cfg_pri_mod ; // priority mode, 0 -> nop, 1 -> Even, 2 -> Odd +output [11:0] cfg_baud_16x ; // 16x Baud clock config + +input frm_error_o ; // framing error +input par_error_o ; // par error +input rx_fifo_full_err_o ; // rx fifo full error + +//--------------------------------- +// Reg Bus Interface Signal +//--------------------------------- +input reg_cs ; +input reg_wr ; +input [3:0] reg_addr ; +input [7:0] reg_wdata ; +input reg_be ; + +// Outputs +output [7:0] reg_rdata ; +output reg_ack ; + + + +//----------------------------------------------------------------------- +// Internal Wire Declarations +//----------------------------------------------------------------------- + +wire sw_rd_en; +wire sw_wr_en; +wire [3:0] sw_addr ; // addressing 16 registers +wire wr_be ; + +reg [7:0] reg_rdata ; +reg reg_ack ; + +wire [7:0] reg_0; // Software_Reg_0 +wire [7:0] reg_1; // Software-Reg_1 +wire [7:0] reg_2; // Software-Reg_2 +wire [7:0] reg_3; // Software-Reg_3 +wire [7:0] reg_4; // Software-Reg_4 +wire [7:0] reg_5; // Software-Reg_5 +wire [7:0] reg_6; // Software-Reg_6 +wire [7:0] reg_7; // Software-Reg_7 +wire [7:0] reg_8; // Software-Reg_8 +wire [7:0] reg_9; // Software-Reg_9 +wire [7:0] reg_10; // Software-Reg_10 +wire [7:0] reg_11; // Software-Reg_11 +wire [7:0] reg_12; // Software-Reg_12 +wire [7:0] reg_13; // Software-Reg_13 +wire [7:0] reg_14; // Software-Reg_14 +wire [7:0] reg_15; // Software-Reg_15 +reg [7:0] reg_out; + +//----------------------------------------------------------------------- +// Main code starts here +//----------------------------------------------------------------------- + +//----------------------------------------------------------------------- +// Internal Logic Starts here +//----------------------------------------------------------------------- + assign sw_addr = reg_addr [3:0]; + assign sw_rd_en = reg_cs & !reg_wr; + assign sw_wr_en = reg_cs & reg_wr; + assign wr_be = reg_be; + + +//----------------------------------------------------------------------- +// Read path mux +//----------------------------------------------------------------------- + +always @ (posedge mclk or negedge reset_n) +begin : preg_out_Seq + if (reset_n == 1'b0) + begin + reg_rdata [7:0] <= 8'h00; + reg_ack <= 1'b0; + end + else if (sw_rd_en && !reg_ack) + begin + reg_rdata [7:0] <= reg_out [7:0]; + reg_ack <= 1'b1; + end + else if (sw_wr_en && !reg_ack) + reg_ack <= 1'b1; + else + begin + reg_ack <= 1'b0; + end +end + + +//----------------------------------------------------------------------- +// register read enable and write enable decoding logic +//----------------------------------------------------------------------- +wire sw_wr_en_0 = sw_wr_en & (sw_addr == 4'h0); +wire sw_rd_en_0 = sw_rd_en & (sw_addr == 4'h0); +wire sw_wr_en_1 = sw_wr_en & (sw_addr == 4'h1); +wire sw_rd_en_1 = sw_rd_en & (sw_addr == 4'h1); +wire sw_wr_en_2 = sw_wr_en & (sw_addr == 4'h2); +wire sw_rd_en_2 = sw_rd_en & (sw_addr == 4'h2); +wire sw_wr_en_3 = sw_wr_en & (sw_addr == 4'h3); +wire sw_rd_en_3 = sw_rd_en & (sw_addr == 4'h3); +wire sw_wr_en_4 = sw_wr_en & (sw_addr == 4'h4); +wire sw_rd_en_4 = sw_rd_en & (sw_addr == 4'h4); +wire sw_wr_en_5 = sw_wr_en & (sw_addr == 4'h5); +wire sw_rd_en_5 = sw_rd_en & (sw_addr == 4'h5); +wire sw_wr_en_6 = sw_wr_en & (sw_addr == 4'h6); +wire sw_rd_en_6 = sw_rd_en & (sw_addr == 4'h6); +wire sw_wr_en_7 = sw_wr_en & (sw_addr == 4'h7); +wire sw_rd_en_7 = sw_rd_en & (sw_addr == 4'h7); +wire sw_wr_en_8 = sw_wr_en & (sw_addr == 4'h8); +wire sw_rd_en_8 = sw_rd_en & (sw_addr == 4'h8); +wire sw_wr_en_9 = sw_wr_en & (sw_addr == 4'h9); +wire sw_rd_en_9 = sw_rd_en & (sw_addr == 4'h9); +wire sw_wr_en_10 = sw_wr_en & (sw_addr == 4'hA); +wire sw_rd_en_10 = sw_rd_en & (sw_addr == 4'hA); +wire sw_wr_en_11 = sw_wr_en & (sw_addr == 4'hB); +wire sw_rd_en_11 = sw_rd_en & (sw_addr == 4'hB); +wire sw_wr_en_12 = sw_wr_en & (sw_addr == 4'hC); +wire sw_rd_en_12 = sw_rd_en & (sw_addr == 4'hC); +wire sw_wr_en_13 = sw_wr_en & (sw_addr == 4'hD); +wire sw_rd_en_13 = sw_rd_en & (sw_addr == 4'hD); +wire sw_wr_en_14 = sw_wr_en & (sw_addr == 4'hE); +wire sw_rd_en_14 = sw_rd_en & (sw_addr == 4'hE); +wire sw_wr_en_15 = sw_wr_en & (sw_addr == 4'hF); +wire sw_rd_en_15 = sw_rd_en & (sw_addr == 4'hF); + + +always @( *) +begin : preg_sel_Com + + reg_out [7:0] = 8'd0; + + case (sw_addr [3:0]) + 4'b0000 : reg_out [7:0] = reg_0 [7:0]; + 4'b0001 : reg_out [7:0] = reg_1 [7:0]; + 4'b0010 : reg_out [7:0] = reg_2 [7:0]; + 4'b0011 : reg_out [7:0] = reg_3 [7:0]; + 4'b0100 : reg_out [7:0] = reg_4 [7:0]; + 4'b0101 : reg_out [7:0] = reg_5 [7:0]; + 4'b0110 : reg_out [7:0] = reg_6 [7:0]; + 4'b0111 : reg_out [7:0] = reg_7 [7:0]; + 4'b1000 : reg_out [7:0] = reg_8 [7:0]; + 4'b1001 : reg_out [7:0] = reg_9 [7:0]; + 4'b1010 : reg_out [7:0] = reg_10 [7:0]; + 4'b1011 : reg_out [7:0] = reg_11 [7:0]; + 4'b1100 : reg_out [7:0] = reg_12 [7:0]; + 4'b1101 : reg_out [7:0] = reg_13 [7:0]; + 4'b1110 : reg_out [7:0] = reg_14 [7:0]; + 4'b1111 : reg_out [7:0] = reg_15 [7:0]; + endcase +end + + + +//----------------------------------------------------------------------- +// Individual register assignments +//----------------------------------------------------------------------- +// Logic for Register 0 : uart Control Register +//----------------------------------------------------------------------- +wire [1:0] cfg_pri_mod = reg_0[4:3]; // priority mode, 0 -> nop, 1 -> Even, 2 -> Odd +wire cfg_stop_bit = reg_0[2]; // 0 -> 1 Stop, 1 -> 2 Stop +wire cfg_rx_enable = reg_0[1]; // Rx Enable +wire cfg_tx_enable = reg_0[0]; // Tx Enable + +generic_register #(5,0 ) u_uart_ctrl_be0 ( + .we ({5{sw_wr_en_0 & + wr_be }} ), + .data_in (reg_wdata[4:0] ), + .reset_n (reset_n ), + .clk (mclk ), + + //List of Outs + .data_out (reg_0[4:0] ) + ); + + +assign reg_0[7:5] = 3'h0; + +//----------------------------------------------------------------------- +// Logic for Register 1 : uart interrupt status +//----------------------------------------------------------------------- +stat_register u_intr_bit0 ( + //inputs + . clk (mclk ), + . reset_n (reset_n ), + . cpu_we (sw_wr_en_1 & + wr_be ), + . cpu_ack (reg_wdata[0] ), + . hware_req (frm_error_o ), + + //outputs + . data_out (reg_1[0] ) + ); + +stat_register u_intr_bit1 ( + //inputs + . clk (mclk ), + . reset_n (reset_n ), + . cpu_we (sw_wr_en_1 & + wr_be ), + . cpu_ack (reg_wdata[1] ), + . hware_req (par_error_o ), + + //outputs + . data_out (reg_1[1] ) + ); + +stat_register u_intr_bit2 ( + //inputs + . clk (mclk ), + . reset_n (reset_n ), + . cpu_we (sw_wr_en_1 & + wr_be ), + . cpu_ack (reg_wdata[2] ), + . hware_req (rx_fifo_full_err_o ), + + //outputs + . data_out (reg_1[2] ) + ); + +assign reg_1[7:3] = 5'h0; + + +//----------------------------------------------------------------------- +// Logic for Register 2 : Baud Rate Control +//----------------------------------------------------------------------- +wire [11:0] cfg_baud_16x = {reg_3[3:0],reg_2[7:0]}; + +generic_register #(8,0 ) u_uart_ctrl_reg2 ( + .we ({8{sw_wr_en_2 & + wr_be }} ), + .data_in (reg_wdata[7:0] ), + .reset_n (reset_n ), + .clk (mclk ), + + //List of Outs + .data_out (reg_2[7:0] ) + ); + +generic_register #(4,0 ) u_uart_ctrl_reg3 ( + .we ({4{sw_wr_en_3 & + wr_be }} ), + .data_in (reg_wdata[3:0] ), + .reset_n (reset_n ), + .clk (mclk ), + + //List of Outs + .data_out (reg_3[3:0] ) + ); + +assign reg_3[7:4] = 4'h0; + + +// reg-4 status +// +assign reg_4[7:0] = {6'h0,rx_fifo_empty,tx_fifo_full}; + +// reg_5 is tx_fifo wr +assign tx_fifo_wr_en = sw_wr_en_5 & reg_ack & !tx_fifo_full; +assign tx_fifo_data = reg_wdata[7:0]; + +// reg_6 is rx_fifo read +// rx_fifo read data +assign reg_6[7:0] = {rx_fifo_data}; +assign rx_fifo_rd_en = sw_rd_en_6 & reg_ack & !rx_fifo_empty; + +assign reg_7[7:0] = {3'h0,tx_fifo_fspace}; // tx fifo free space +assign reg_8[7:0] = {3'h0,rx_fifo_dval}; // rx fifo data available + +endmodule
diff --git a/verilog/rtl/uart/src/uart_core.sv b/verilog/rtl/uart/src/uart_core.sv new file mode 100644 index 0000000..d318e3f --- /dev/null +++ b/verilog/rtl/uart/src/uart_core.sv
@@ -0,0 +1,320 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// UART CORE with TX/RX 16 Byte Buffer //// +//// //// +//// This file is part of the YIFive cores project //// +//// http://www.opencores.org/cores/yifive/ //// +//// //// +//// Description //// +//// //// +//// To Do: //// +//// nothing //// +//// //// +//// Author(s): //// +//// - Dinesh Annayya, dinesha@opencores.org //// +//// //// +//// Revision : //// +//// 0.1 - 20th June 2021, Dinesh A //// +//// 1. initial version picked from //// +//// http://www.opencores.org/cores/oms8051mini //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + +module uart_core + + ( + + arst_n , // async reset + app_clk , + + // Reg Bus Interface Signal + reg_cs, + reg_wr, + reg_addr, + reg_wdata, + reg_be, + + // Outputs + reg_rdata, + reg_ack, + + // Line Interface + si, + so + + ); + + + + +parameter W = 8'd8; +parameter DP = 8'd16; +parameter AW = (DP == 2) ? 1 : + (DP == 4) ? 2 : + (DP == 8) ? 3 : + (DP == 16) ? 4 : + (DP == 32) ? 5 : + (DP == 64) ? 6 : + (DP == 128) ? 7 : + (DP == 256) ? 8 : 0; + + + +input arst_n ; // async reset +input app_clk ; // application clock + +//--------------------------------- +// Reg Bus Interface Signal +//--------------------------------- +input reg_cs ; +input reg_wr ; +input [3:0] reg_addr ; +input [7:0] reg_wdata ; +input reg_be ; + +// Outputs +output [7:0] reg_rdata ; +output reg_ack ; + +// Line Interface +input si ; // uart si +output so ; // uart so + +// Wire Declaration +wire app_reset_n ; +wire line_reset_n ; + +wire [W-1: 0] tx_fifo_rd_data; +wire [W-1: 0] rx_fifo_wr_data; +wire [W-1: 0] app_rxfifo_data; +wire [W-1: 0] app_txfifo_data; +wire [1 : 0] error_ind; + +// Wire +wire cfg_tx_enable ; // Tx Enable +wire cfg_rx_enable ; // Rx Enable +wire cfg_stop_bit ; // 0 -> 1 Stop, 1 -> 2 Stop +wire [1:0] cfg_pri_mod ; // priority mode, 0 -> nop, 1 -> Even, 2 -> Odd + +wire frm_error_o ; // framing error +wire par_error_o ; // par error +wire rx_fifo_full_err_o ; // rx fifo full error + +wire [11:0] cfg_baud_16x ; // 16x Baud clock generation +wire rx_fifo_wr_full ; +wire app_rxfifo_empty ; + +wire [AW:0] tx_fifo_fspace ; // Total Tx fifo Free Space +wire [AW:0] rx_fifo_dval ; // Total Rx fifo Data Available + +uart_cfg u_cfg ( + + . mclk (app_clk), + . reset_n (app_reset_n), + + // Reg Bus Interface Signal + . reg_cs (reg_cs), + . reg_wr (reg_wr), + . reg_addr (reg_addr), + . reg_wdata (reg_wdata), + . reg_be (reg_be), + + // Outputs + . reg_rdata (reg_rdata), + . reg_ack (reg_ack), + + + // configuration + . cfg_tx_enable (cfg_tx_enable), + . cfg_rx_enable (cfg_rx_enable), + . cfg_stop_bit (cfg_stop_bit), + . cfg_pri_mod (cfg_pri_mod), + + . cfg_baud_16x (cfg_baud_16x), + + . tx_fifo_full (app_tx_fifo_full), + .tx_fifo_fspace (tx_fifo_fspace ), + . tx_fifo_wr_en (tx_fifo_wr_en), + . tx_fifo_data (app_txfifo_data), + + . rx_fifo_empty (app_rxfifo_empty), + .rd_fifo_dval (rx_fifo_dval ), + . rx_fifo_rd_en (app_rxfifo_rd_en), + . rx_fifo_data (app_rxfifo_data) , + + . frm_error_o (frm_error_o), + . par_error_o (par_error_o), + . rx_fifo_full_err_o (rx_fifo_full_err_o) + + ); + + +//############################################################## +// 16x Baud clock generation +// Example: to generate 19200 Baud clock from 50Mhz Link clock +// 50 * 1000 * 1000 / (2 + cfg_baud_16x) = 19200 * 16 +// cfg_baud_16x = 0xA0 (160) +//############################################################### + +wire line_clk_16x; + +clk_ctl #(11) u_clk_ctl ( + // Outputs + .clk_o (line_clk_16x), + + // Inputs + .mclk (app_clk), + .reset_n (app_reset_n), + .clk_div_ratio (cfg_baud_16x) + ); + +//################################### +// Application Reset Synchronization +//################################### +reset_sync u_app_rst ( + .scan_mode (1'b0 ), + .dclk (app_clk ), // Destination clock domain + .arst_n (arst_n ), // active low async reset + .srst_n (app_reset_n ) + ); + +//################################### +// Line Reset Synchronization +//################################### +reset_sync u_line_rst ( + .scan_mode (1'b0 ), + .dclk (line_clk_16x ), // Destination clock domain + .arst_n (arst_n ), // active low async reset + .srst_n (line_reset_n ) + ); + + +uart_txfsm u_txfsm ( + .reset_n ( line_reset_n ), + .baud_clk_16x ( line_clk_16x ), + + .cfg_tx_enable ( cfg_tx_enable ), + .cfg_stop_bit ( cfg_stop_bit ), + .cfg_pri_mod ( cfg_pri_mod ), + + // FIFO control signal + .fifo_empty ( tx_fifo_rd_empty ), + .fifo_rd ( tx_fifo_rd ), + .fifo_data ( tx_fifo_rd_data ), + + // Line Interface + .so ( so ) + ); + + +uart_rxfsm u_rxfsm ( + .reset_n ( line_reset_n ), + .baud_clk_16x ( line_clk_16x ) , + + .cfg_rx_enable ( cfg_rx_enable ), + .cfg_stop_bit ( cfg_stop_bit ), + .cfg_pri_mod ( cfg_pri_mod ), + + .error_ind ( error_ind ), + + // FIFO control signal + .fifo_aval ( !rx_fifo_wr_full ), + .fifo_wr ( rx_fifo_wr ), + .fifo_data ( rx_fifo_wr_data ), + + // Line Interface + .si (si_ss ) + ); + +async_fifo_th #(W,DP,0,0) u_rxfifo ( + .wr_clk (line_clk_16x ), + .wr_reset_n (line_reset_n ), + .wr_en (rx_fifo_wr ), + .wr_data (rx_fifo_wr_data ), + .full (rx_fifo_wr_full ), // sync'ed to wr_clk + .wr_total_free_space( ), + + .rd_clk (app_clk ), + .rd_reset_n (app_reset_n ), + .rd_en (app_rxfifo_rd_en ), + .empty (app_rxfifo_empty ), // sync'ed to rd_clk + .rd_total_aval (rx_fifo_dval ), + .rd_data (app_rxfifo_data ) + ); + +async_fifo_th #(W,DP,0,0) u_txfifo ( + .wr_clk (app_clk ), + .wr_reset_n (app_reset_n ), + .wr_en (tx_fifo_wr_en ), + .wr_data (app_txfifo_data ), + .full (app_tx_fifo_full ), // sync'ed to wr_clk + .wr_total_free_space(tx_fifo_fspace ), + + .rd_clk (line_clk_16x ), + .rd_reset_n (line_reset_n ), + .rd_en (tx_fifo_rd ), + .empty (tx_fifo_rd_empty ), // sync'ed to rd_clk + .rd_total_aval ( ), + .rd_data (tx_fifo_rd_data ) + ); + + +double_sync_low u_si_sync ( + .in_data ( si ), + .out_clk (line_clk_16x ), + .out_rst_n (line_reset_n ), + .out_data (si_ss ) + ); + +wire frm_error = (error_ind == 2'b01); +wire par_error = (error_ind == 2'b10); +wire rx_fifo_full_err = (error_ind == 2'b11); + +double_sync_low u_frm_err ( + .in_data ( frm_error ), + .out_clk ( app_clk ), + .out_rst_n ( app_reset_n ), + .out_data ( frm_error_o ) + ); + +double_sync_low u_par_err ( + .in_data ( par_error ), + .out_clk ( app_clk ), + .out_rst_n ( app_reset_n ), + .out_data ( par_error_o ) + ); + +double_sync_low u_rxfifo_err ( + .in_data ( rx_fifo_full_err ), + .out_clk ( app_clk ), + .out_rst_n ( app_reset_n ), + .out_data ( rx_fifo_full_err_o ) + ); + + +endmodule
diff --git a/verilog/rtl/uart/src/uart_rxfsm.sv b/verilog/rtl/uart/src/uart_rxfsm.sv new file mode 100644 index 0000000..e7dea59 --- /dev/null +++ b/verilog/rtl/uart/src/uart_rxfsm.sv
@@ -0,0 +1,203 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// UART RX FSM //// +//// //// +//// This file is part of the YIFive cores project //// +//// http://www.opencores.org/cores/yifive/ //// +//// //// +//// Description //// +//// //// +//// To Do: //// +//// nothing //// +//// //// +//// Author(s): //// +//// - Dinesh Annayya, dinesha@opencores.org //// +//// //// +//// Revision : //// +//// 0.1 - 20th June 2021, Dinesh A //// +//// 1. initial version picked from //// +//// http://www.opencores.org/cores/oms8051mini //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + +module uart_rxfsm ( + reset_n , + baud_clk_16x , + + cfg_rx_enable , + cfg_stop_bit , + cfg_pri_mod , + + error_ind , + + // FIFO control signal + fifo_aval , + fifo_wr , + fifo_data , + + // Line Interface + si + ); + + +input reset_n ; // active low reset signal +input baud_clk_16x ; // baud clock-16x + +input cfg_rx_enable ; // transmit interface enable +input cfg_stop_bit ; // stop bit + // 0 --> 1 stop, 1 --> 2 Stop +input [1:0] cfg_pri_mod ;// Priority Mode + // 2'b00 --> None + // 2'b10 --> Even priority + // 2'b11 --> Odd priority + +output [1:0] error_ind ; // 2'b00 --> Normal + // 2'b01 --> framing error + // 2'b10 --> parity error + // 2'b11 --> fifo full +//-------------------------------------- +// FIFO control signal +//-------------------------------------- +input fifo_aval ; // fifo empty +output fifo_wr ; // fifo write, assumed no back to back write +output [7:0] fifo_data ; // fifo write data + +// Line Interface +input si ; // rxd pin + + + +reg [7:0] fifo_data ; // fifo write data +reg fifo_wr ; // fifo write +reg [1:0] error_ind ; +reg [2:0] cnt ; +reg [3:0] offset ; // free-running counter from 0 - 15 +reg [3:0] rxpos ; // stable rx position +reg [2:0] rxstate ; + +parameter idle_st = 3'b000; +parameter xfr_start = 3'b001; +parameter xfr_data_st = 3'b010; +parameter xfr_pri_st = 3'b011; +parameter xfr_stop_st1 = 3'b100; +parameter xfr_stop_st2 = 3'b101; + + +always @(negedge reset_n or posedge baud_clk_16x) begin + if(reset_n == 0) begin + rxstate <= 3'b0; + offset <= 4'b0; + rxpos <= 4'b0; + cnt <= 3'b0; + error_ind <= 2'b0; + fifo_wr <= 1'b0; + fifo_data <= 8'h0; + end + else begin + offset <= offset + 1; + case(rxstate) + idle_st : begin + if(!si) begin // Start indication + if(fifo_aval && cfg_rx_enable) begin + rxstate <= xfr_start; + cnt <= 0; + rxpos <= offset + 8; // Assign center rxoffset + error_ind <= 2'b00; + end + else begin + error_ind <= 2'b11; // fifo full error indication + end + end else begin + error_ind <= 2'b00; // Reset Error + end + end + xfr_start : begin + // Make Sure that minimum 8 cycle low is detected + if(cnt < 7 && si) begin // Start indication + rxstate <= idle_st; + end + else if(cnt == 7 && !si) begin // Start indication + rxstate <= xfr_data_st; + cnt <= 0; + end else begin + cnt <= cnt +1; + end + end + xfr_data_st : begin + if(rxpos == offset) begin + fifo_data[cnt] <= si; + cnt <= cnt+1; + if(cnt == 7) begin + fifo_wr <= 1; + if(cfg_pri_mod == 2'b00) // No Priority + rxstate <= xfr_stop_st1; + else rxstate <= xfr_pri_st; + end + end + end + xfr_pri_st : begin + fifo_wr <= 0; + if(rxpos == offset) begin + if(cfg_pri_mod == 2'b10) // even priority + if( si != ^fifo_data) error_ind <= 2'b10; + else // Odd Priority + if( si != ~(^fifo_data)) error_ind <= 2'b10; + rxstate <= xfr_stop_st1; + end + end + xfr_stop_st1 : begin + fifo_wr <= 0; + if(rxpos == offset) begin + if(si) begin + if(cfg_stop_bit) // Two Stop bit + rxstate <= xfr_stop_st2; + else + rxstate <= idle_st; + end else begin // Framing error + error_ind <= 2'b01; + rxstate <= idle_st; + end + end + end + xfr_stop_st2 : begin + if(rxpos == offset) begin + if(si) begin + rxstate <= idle_st; + end else begin // Framing error + error_ind <= 2'b01; + rxstate <= idle_st; + end + end + end + default: rxstate <= idle_st; + endcase + end +end + + +endmodule
diff --git a/verilog/rtl/uart/src/uart_txfsm.sv b/verilog/rtl/uart/src/uart_txfsm.sv new file mode 100644 index 0000000..fd8f947 --- /dev/null +++ b/verilog/rtl/uart/src/uart_txfsm.sv
@@ -0,0 +1,172 @@ +////////////////////////////////////////////////////////////////////// +//// //// +//// UART TX FSM //// +//// //// +//// This file is part of the YIFive cores project //// +//// http://www.opencores.org/cores/yifive/ //// +//// //// +//// Description //// +//// //// +//// To Do: //// +//// nothing //// +//// //// +//// Author(s): //// +//// - Dinesh Annayya, dinesha@opencores.org //// +//// //// +//// Revision : //// +//// 0.1 - 20th June 2021, Dinesh A //// +//// 1. initial version picked from //// +//// http://www.opencores.org/cores/oms8051mini //// +//// //// +////////////////////////////////////////////////////////////////////// +//// //// +//// Copyright (C) 2000 Authors and OPENCORES.ORG //// +//// //// +//// This source file may be used and distributed without //// +//// restriction provided that this copyright statement is not //// +//// removed from the file and that any derivative work contains //// +//// the original copyright notice and the associated disclaimer. //// +//// //// +//// This source file is free software; you can redistribute it //// +//// and/or modify it under the terms of the GNU Lesser General //// +//// Public License as published by the Free Software Foundation; //// +//// either version 2.1 of the License, or (at your option) any //// +//// later version. //// +//// //// +//// This source is distributed in the hope that it will be //// +//// useful, but WITHOUT ANY WARRANTY; without even the implied //// +//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// +//// PURPOSE. See the GNU Lesser General Public License for more //// +//// details. //// +//// //// +//// You should have received a copy of the GNU Lesser General //// +//// Public License along with this source; if not, download it //// +//// from http://www.opencores.org/lgpl.shtml //// +//// //// +////////////////////////////////////////////////////////////////////// + + +module uart_txfsm ( + reset_n , + baud_clk_16x , + + cfg_tx_enable , + cfg_stop_bit , + cfg_pri_mod , + + // FIFO control signal + fifo_empty , + fifo_rd , + fifo_data , + + // Line Interface + so + ); + + +input reset_n ; // active low reset signal +input baud_clk_16x ; // baud clock-16x + +input cfg_tx_enable ; // transmit interface enable +input cfg_stop_bit ; // stop bit + // 0 --> 1 stop, 1 --> 2 Stop +input [1:0] cfg_pri_mod ;// Priority Mode + // 2'b00 --> None + // 2'b10 --> Even priority + // 2'b11 --> Odd priority + +//-------------------------------------- +// FIFO control signal +//-------------------------------------- +input fifo_empty ; // fifo empty +output fifo_rd ; // fifo read, assumed no back to back read +input [7:0] fifo_data ; // fifo read data + +// Line Interface +output so ; // txd pin + + +reg [2:0] txstate ; // tx state +reg so ; // txd pin +reg [7:0] txdata ; // local txdata +reg fifo_rd ; // Fifo read enable +reg [2:0] cnt ; // local data cont +reg [3:0] divcnt ; // clock div count + +parameter idle_st = 3'b000; +parameter xfr_data_st = 3'b001; +parameter xfr_pri_st = 3'b010; +parameter xfr_stop_st1 = 3'b011; +parameter xfr_stop_st2 = 3'b100; + + +always @(negedge reset_n or posedge baud_clk_16x) +begin + if(reset_n == 1'b0) begin + txstate <= idle_st; + so <= 1'b1; + cnt <= 3'b0; + txdata <= 8'h0; + fifo_rd <= 1'b0; + divcnt <= 4'b0; + end + else begin + divcnt <= divcnt+1; + if(divcnt == 4'b0000) begin // Do at once in 16 clock + case(txstate) + idle_st : begin + if(!fifo_empty && cfg_tx_enable) begin + so <= 1'b0 ; // Start bit + cnt <= 3'b0; + fifo_rd <= 1'b1; + txdata <= fifo_data; + txstate <= xfr_data_st; + end + end + + xfr_data_st : begin + fifo_rd <= 1'b0; + so <= txdata[cnt]; + cnt <= cnt+1; + if(cnt == 7) begin + if(cfg_pri_mod == 2'b00) begin // No Priority + txstate <= xfr_stop_st1; + end + else begin + txstate <= xfr_pri_st; + end + end + end + + xfr_pri_st : begin + if(cfg_pri_mod == 2'b10) // even priority + so <= ^txdata; + else begin // Odd Priority + so <= ~(^txdata); + end + txstate <= xfr_stop_st1; + end + + xfr_stop_st1 : begin // First Stop Bit + so <= 1; + if(cfg_stop_bit == 0) // 1 Stop Bit + txstate <= idle_st; + else // 2 Stop Bit + txstate <= xfr_stop_st2; + end + + xfr_stop_st2 : begin // Second Stop Bit + so <= 1; + txstate <= idle_st; + end + default: txstate <= idle_st; + endcase + end + else begin + fifo_rd <= 1'b0; + end + end +end + + +endmodule
diff --git a/verilog/rtl/uprj_netlists.v b/verilog/rtl/uprj_netlists.v index 689eca3..33f2c1f 100644 --- a/verilog/rtl/uprj_netlists.v +++ b/verilog/rtl/uprj_netlists.v
@@ -31,6 +31,13 @@ `include "spi_master/src/spim_rx.sv" `include "spi_master/src/spim_tx.sv" + `include "uart/src/uart_core.sv" + `include "uart/src/uart_cfg.sv" + `include "uart/src/uart_rxfsm.sv" + `include "uart/src/uart_txfsm.sv" + `include "lib/async_fifo_th.sv" + `include "lib/reset_sync.sv" + `include "sdram_ctrl/src/top/sdrc_top.v" `include "sdram_ctrl/src/wb2sdrc/wb2sdrc.v" `include "lib/async_fifo.sv" @@ -80,4 +87,5 @@ `include "syntacore/scr1/src/top/scr1_imem_wb.sv" `include "syntacore/scr1/src/top/scr1_top_wb.sv" `include "lib/sync_fifo.sv" + `endif
diff --git a/verilog/rtl/wb_interconnect/src/wb_interconnect.sv b/verilog/rtl/wb_interconnect/src/wb_interconnect.sv index 3eb688e..61f7f64 100644 --- a/verilog/rtl/wb_interconnect/src/wb_interconnect.sv +++ b/verilog/rtl/wb_interconnect/src/wb_interconnect.sv
@@ -20,6 +20,8 @@ //// 0.2 - 17th June 2021, Dinesh A //// //// Stagging FF added at Slave Interface to break //// //// path //// +//// 0.3 - 21th June 2021, Dinesh A //// +//// slave port 3 added for uart //// //// //// ////////////////////////////////////////////////////////////////////// //// //// @@ -120,6 +122,18 @@ output logic s2_wbd_we_o, output logic s2_wbd_cyc_o, output logic s2_wbd_stb_o + + // Slave 3 Interface + // Uart is 8bit interface + input logic [7:0] s3_wbd_dat_i, + input logic s3_wbd_ack_i, + input logic s3_wbd_err_i, + output logic [7:0] s3_wbd_dat_o, + output logic [7:0] s3_wbd_adr_o, + output logic s3_wbd_sel_o, + output logic s3_wbd_we_o, + output logic s3_wbd_cyc_o, + output logic s3_wbd_stb_o ); //////////////////////////////////////////////////////////////////// @@ -161,11 +175,13 @@ type_wb_wr_intf s0_wb_wr; type_wb_wr_intf s1_wb_wr; type_wb_wr_intf s2_wb_wr; +type_wb_wr_intf s3_wb_wr; // Slave Read Interface type_wb_rd_intf s0_wb_rd; type_wb_rd_intf s1_wb_rd; type_wb_rd_intf s2_wb_rd; +type_wb_rd_intf s3_wb_rd; type_wb_wr_intf m_bus_wr; // Multiplexed Master I/F @@ -179,22 +195,26 @@ // 0x1000_0000 to 0x1000_00FF - SPI REGISTER // 0x2000_0000 to 0x2FFF_FFFF - SDRAM // 0x3000_0000 to 0x3000_00FF - GLOBAL REGISTER +// 0x3000_0000 to 0x3001_00FF - UART Register //----------------------------- // -wire [3:0] m0_wbd_tid_i = (m0_wbd_adr_i[31:28] == 4'b0000 ) ? 4'b0000 : - (m0_wbd_adr_i[31:28] == 4'b0001 ) ? 4'b0000 : - (m0_wbd_adr_i[31:28] == 4'b0010 ) ? 4'b0001 : - (m0_wbd_adr_i[31:28] == 4'b0011 ) ? 4'b0010 : 4'b0000; +wire [3:0] m0_wbd_tid_i = (m0_wbd_adr_i[31:28] == 4'b0000 ) ? 4'b0000 : + (m0_wbd_adr_i[31:28] == 4'b0001 ) ? 4'b0000 : + (m0_wbd_adr_i[31:28] == 4'b0010 ) ? 4'b0001 : + (m0_wbd_adr_i[31:16] == 16'h3000 ) ? 4'b0010 : + (m0_wbd_adr_i[31:16] == 16'h3001 ) ? 4'b0011 : 4'b0000; -wire [3:0] m1_wbd_tid_i = (m1_wbd_adr_i[31:28] == 4'b0000 ) ? 4'b0000 : - (m1_wbd_adr_i[31:28] == 4'b0001 ) ? 4'b0000 : - (m1_wbd_adr_i[31:28] == 4'b0010 ) ? 4'b0001 : - (m1_wbd_adr_i[31:28] == 4'b0011 ) ? 4'b0010 : 4'b0000; +wire [3:0] m1_wbd_tid_i = (m1_wbd_adr_i[31:28] == 4'b0000 ) ? 4'b0000 : + (m1_wbd_adr_i[31:28] == 4'b0001 ) ? 4'b0000 : + (m1_wbd_adr_i[31:28] == 4'b0010 ) ? 4'b0001 : + (m1_wbd_adr_i[31:16] == 16'h3000 ) ? 4'b0010 : + (m1_wbd_adr_i[31:16] == 16'h3001 ) ? 4'b0011 : 4'b0000; //------------------------------------------------------------------- // EXTERNAL MEMORY MAP // 0x3000_0000 to 0x3000_00FF - GLOBAL REGISTER +// 0x3000_0000 to 0x3001_00FF - UART Register // 0x4000_0000 to 0x4FFF_FFFF - SPI FLASH MEMORY // 0x5000_0000 to 0x5000_00FF - SPI REGISTER // 0x6000_0000 to 0x6FFF_FFFF - SDRAM @@ -202,7 +222,8 @@ wire [3:0] m2_wbd_tid_i = (m2_wbd_adr_i[31:28] == 4'b0100 ) ? 4'b0000 : (m2_wbd_adr_i[31:28] == 4'b0101 ) ? 4'b0000 : (m2_wbd_adr_i[31:28] == 4'b0110 ) ? 4'b0001 : - (m2_wbd_adr_i[31:28] == 4'b0011 ) ? 4'b0010 : 4'b0000; + (m2_wbd_adr_i[31:16] == 16'h3000 ) ? 4'b0010 : + (m2_wbd_adr_i[31:16] == 16'h3001 ) ? 4'b0011 : 4'b0000; //---------------------------------------- // Master Mapping @@ -267,6 +288,13 @@ assign s2_wbd_we_o = s2_wb_wr.wbd_we ; assign s2_wbd_cyc_o = s2_wb_wr.wbd_cyc ; assign s2_wbd_stb_o = s2_wb_wr.wbd_stb ; + + assign s3_wbd_dat_o = s3_wb_wr.wbd_dat[7:0] ; + assign s3_wbd_adr_o = s3_wb_wr.wbd_adr[7:0] ; // Global Reg Need 8 bit + assign s3_wbd_sel_o = s3_wb_wr.wbd_sel[0] ; + assign s3_wbd_we_o = s3_wb_wr.wbd_we ; + assign s3_wbd_cyc_o = s3_wb_wr.wbd_cyc ; + assign s3_wbd_stb_o = s3_wb_wr.wbd_stb ; assign s0_wb_rd.wbd_dat = s0_wbd_dat_i ; assign s0_wb_rd.wbd_ack = s0_wbd_ack_i ; @@ -280,6 +308,9 @@ assign s2_wb_rd.wbd_ack = s2_wbd_ack_i ; assign s2_wb_rd.wbd_err = s2_wbd_err_i ; + assign s3_wb_rd.wbd_dat = {24'h0,s3_wbd_dat_i} ; + assign s3_wb_rd.wbd_ack = s3_wbd_ack_i ; + assign s3_wb_rd.wbd_err = s3_wbd_err_i ; // // arbitor @@ -314,6 +345,7 @@ 3'h0: s_bus_rd = s0_wb_rd; 3'h1: s_bus_rd = s1_wb_rd; 3'h2: s_bus_rd = s2_wb_rd; + 3'h3: s_bus_rd = s3_wb_rd; default: s_bus_rd = s0_wb_rd; endcase end @@ -323,6 +355,7 @@ assign s0_wb_wr = (s_wbd_tid == 2'b00) ? s_bus_wr : 'h0; assign s1_wb_wr = (s_wbd_tid == 2'b01) ? s_bus_wr : 'h0; assign s2_wb_wr = (s_wbd_tid == 2'b10) ? s_bus_wr : 'h0; +assign s3_wb_wr = (s_wbd_tid == 2'b11) ? s_bus_wr : 'h0; // Connect Slave to Master assign m0_wb_rd = (gnt == 2'b00) ? m_bus_rd : 'h0;