diff --git a/.github/scripts/check_sim.sh b/.github/scripts/check_sim.sh index eb7c19fa..707b4520 100755 --- a/.github/scripts/check_sim.sh +++ b/.github/scripts/check_sim.sh @@ -12,6 +12,7 @@ expected_lines=( "\[JTAG\] Halting hart 0" "\[JTAG\] Resumed hart 0" "\[UART\] Hello World!" + "\[UART\] Loopback received: internal msg" "\[UART\] Result: 0x8940, Cycles: 0xBD" "\[UART\] Tick" "\[UART\] Tock" diff --git a/Bender.local b/Bender.local index b6ddde3a..182efa6a 100644 --- a/Bender.local +++ b/Bender.local @@ -4,7 +4,7 @@ overrides: common_cells: { path: "rtl/common_cells" } apb: { path: "rtl/apb" } register_interface: { path: "rtl/register_interface" } - apb_uart: { path: "rtl/apb_uart" } + obi_peripherals: { path: "rtl/obi_uart" } ibex: { path: "rtl/ibex" } obi: { path: "rtl/obi" } riscv-dbg: { path: "rtl/riscv-dbg" } diff --git a/Bender.lock b/Bender.lock index 2fc0edce..2e4f4eae 100644 --- a/Bender.lock +++ b/Bender.lock @@ -6,14 +6,6 @@ packages: Path: rtl/apb dependencies: - common_cells - apb_uart: - revision: null - version: null - source: - Path: rtl/apb_uart - dependencies: - - apb - - register_interface common_cells: revision: null version: null @@ -42,6 +34,14 @@ packages: dependencies: - common_cells - common_verification + obi_peripherals: + revision: null + version: null + source: + Path: rtl/obi_uart + dependencies: + - common_cells + - obi register_interface: revision: null version: null diff --git a/Bender.yml b/Bender.yml index d312c3fe..97468f09 100644 --- a/Bender.yml +++ b/Bender.yml @@ -16,8 +16,8 @@ dependencies: register_interface: { git: "https://github.com/pulp-platform/register_interface.git", version: 0.4.1 } apb: { git: "https://github.com/pulp-platform/apb.git", version: 0.2.4 } timer_unit: { git: "https://github.com/pulp-platform/timer_unit.git", version: 1.0.3 } - obi: { git: "https://github.com/pulp-platform/obi.git", version: 0.1.3 } - apb_uart: { git: "https://github.com/pulp-platform/apb_uart.git", version: 0.2.1 } + obi: { git: "https://github.com/pulp-platform/obi.git", version: 0.1.7 } + obi_peripherals: { git: "https://github.com/pulp-platform/obi_peripherals.git", rev: 21ee04d } # UART cve2: { path: "rtl/cve2" } # a vendor package (no Bender.yml), see below @@ -166,15 +166,13 @@ vendor_package: - { from: 'Bender.yml', to: 'Bender.yml', patch_dir: '' } - { from: 'doc/timer_unit.pdf', to: 'timer_unit.pdf', patch_dir: 'doc/' } - - name: apb_uart - target_dir: rtl/apb_uart - upstream: { git: "https://github.com/pulp-platform/apb_uart.git", rev: "6c7dde3d749ac8274377745c105da8c8b8cd27c6" } # v0.2.1 - patch_dir: "rtl/patches/apb_uart" - exclude_from_upstream: - - "src/vhdl_orig" + - name: obi_peripherals + target_dir: rtl/obi_uart + upstream: { git: "https://github.com/pulp-platform/obi_peripherals.git", rev: "21ee04d267025f6ea3d2faa462272287ddcb9bbb" } # newest + patch_dir: "rtl/patches/obi_uart" mapping: - - { from: 'src/', to: '', patch_dir: 'src/' } - - { from: 'Bender.yml', to: 'Bender.yml', patch_dir: '' } + - { from: 'hw/obi_uart/', to: '', patch_dir: 'hw/' } + - { from: 'Bender.yml', to: 'Bender.yml', patch_dir: '' } ######### diff --git a/croc.flist b/croc.flist index 89c40cd9..84c57b52 100644 --- a/croc.flist +++ b/croc.flist @@ -1,20 +1,3 @@ -# Copyright (c) 2025 ETH Zurich and University of Bologna. -# Licensed under the Apache License, Version 2.0, see LICENSE for details. -# SPDX-License-Identifier: Apache-2.0 -# -# Authors: -# - Philippe Sauter - -# List of files to synthesize the design -# A file list given to the yosys-slang frontend to load the design -# In this flow we use 'read_slang -F croc.flist' to load this file -# All paths are relative to this file (use -f to make them relative to CWD) -# It contains: -# - include directores expected from SystemVerilog 'include' statements -# - defines used in some SystemVerilog files -# often used to guard non-synthesisable code or select some implementation -# - the paths to all source files - +incdir+rtl/apb/include +incdir+rtl/common_cells/include +incdir+rtl/cve2/include @@ -108,27 +91,16 @@ rtl/common_cells/stream_arbiter.sv rtl/common_cells/stream_omega_net.sv rtl/common_cells/mem_to_banks.sv rtl/apb/apb_pkg.sv -rtl/register_interface/reg_intf.sv -rtl/register_interface/lowrisc_opentitan/prim_subreg_arb.sv -rtl/register_interface/lowrisc_opentitan/prim_subreg_ext.sv -rtl/register_interface/periph_to_reg.sv -rtl/register_interface/reg_to_apb.sv -rtl/register_interface/lowrisc_opentitan/prim_subreg_shadow.sv -rtl/register_interface/lowrisc_opentitan/prim_subreg.sv -rtl/apb_uart/slib_clock_div.sv -rtl/apb_uart/slib_counter.sv -rtl/apb_uart/slib_edge_detect.sv -rtl/apb_uart/slib_fifo.sv -rtl/apb_uart/slib_input_filter.sv -rtl/apb_uart/slib_input_sync.sv -rtl/apb_uart/slib_mv_filter.sv -rtl/apb_uart/uart_baudgen.sv -rtl/apb_uart/uart_interrupt.sv -rtl/apb_uart/uart_receiver.sv -rtl/apb_uart/uart_transmitter.sv -rtl/apb_uart/apb_uart.sv -rtl/apb_uart/apb_uart_wrap.sv -rtl/apb_uart/reg_uart_wrap.sv +rtl/obi/obi_pkg.sv +rtl/obi/obi_intf.sv +rtl/obi/obi_rready_converter.sv +rtl/obi/obi_atop_resolver.sv +rtl/obi/obi_cut.sv +rtl/obi/obi_demux.sv +rtl/obi/obi_err_sbr.sv +rtl/obi/obi_mux.sv +rtl/obi/obi_sram_shim.sv +rtl/obi/obi_xbar.sv rtl/cve2/cve2_pkg.sv rtl/cve2/cve2_alu.sv rtl/cve2/cve2_compressed_decoder.sv @@ -149,15 +121,21 @@ rtl/cve2/cve2_id_stage.sv rtl/cve2/cve2_prefetch_buffer.sv rtl/cve2/cve2_if_stage.sv rtl/cve2/cve2_core.sv -rtl/obi/obi_pkg.sv -rtl/obi/obi_intf.sv -rtl/obi/obi_rready_converter.sv -rtl/obi/obi_atop_resolver.sv -rtl/obi/obi_demux.sv -rtl/obi/obi_err_sbr.sv -rtl/obi/obi_mux.sv -rtl/obi/obi_sram_shim.sv -rtl/obi/obi_xbar.sv +rtl/obi_uart/obi_uart_pkg.sv +rtl/obi_uart/obi_uart_baudgen.sv +rtl/obi_uart/obi_uart_interrupts.sv +rtl/obi_uart/obi_uart_modem.sv +rtl/obi_uart/obi_uart_rx.sv +rtl/obi_uart/obi_uart_tx.sv +rtl/obi_uart/obi_uart_register.sv +rtl/obi_uart/obi_uart.sv +rtl/register_interface/reg_intf.sv +rtl/register_interface/lowrisc_opentitan/prim_subreg_arb.sv +rtl/register_interface/lowrisc_opentitan/prim_subreg_ext.sv +rtl/register_interface/periph_to_reg.sv +rtl/register_interface/reg_to_apb.sv +rtl/register_interface/lowrisc_opentitan/prim_subreg_shadow.sv +rtl/register_interface/lowrisc_opentitan/prim_subreg.sv rtl/riscv-dbg/dm_pkg.sv rtl/riscv-dbg/debug_rom/debug_rom.sv rtl/riscv-dbg/debug_rom/debug_rom_one_scratch.sv diff --git a/rtl/apb_uart/Bender.yml b/rtl/apb_uart/Bender.yml deleted file mode 100644 index 60d59b6b..00000000 --- a/rtl/apb_uart/Bender.yml +++ /dev/null @@ -1,26 +0,0 @@ -package: - name: apb_uart - authors: [ - "Sebastian Witt", - "Jonathan Kimmitt" - ] - -dependencies: - apb: { git: "https://github.com/pulp-platform/apb", version: 0.2.1 } - register_interface: { git: "https://github.com/pulp-platform/register_interface", version: 0.3.6 } - -sources: - - slib_clock_div.sv - - slib_counter.sv - - slib_edge_detect.sv - - slib_fifo.sv - - slib_input_filter.sv - - slib_input_sync.sv - - slib_mv_filter.sv - - uart_baudgen.sv - - uart_interrupt.sv - - uart_receiver.sv - - uart_transmitter.sv - - apb_uart.sv - - apb_uart_wrap.sv - - reg_uart_wrap.sv diff --git a/rtl/apb_uart/apb_uart.sv b/rtl/apb_uart/apb_uart.sv deleted file mode 100644 index 0372a46d..00000000 --- a/rtl/apb_uart/apb_uart.sv +++ /dev/null @@ -1,947 +0,0 @@ -// -// UART 16750 -// -// Converted to System Verilog by Jonathan Kimmitt -// This version has been partially checked with formality but some bugs remain -// Original Author: Sebastian Witt -// Date: 14.03.2019 -// Version: 1.6 -// -// History: 1.0 - Initial version -// 1.1 - THR empty interrupt register connected to RST -// 1.2 - Registered outputs -// 1.3 - Automatic flow control -// 1.4 - De-assert IIR FIFO64 when FIFO is disabled -// 1.5 - Inverted low active outputs when RST is active -// 1.6 - Converted to System Verilog -// -// -// This code 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 code 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 library; if not, write to the -// Free Software Foundation, Inc., 59 Temple Place, Suite 330, -// Boston, MA 02111-1307 USA -// - -module apb_uart( - input wire CLK, - input wire RSTN, - input wire PSEL, - input wire PENABLE, - input wire PWRITE, - input wire [2:0] PADDR, - input wire [31:0] PWDATA, - output logic [31:0] PRDATA, - output logic PREADY, - output logic PSLVERR, - output logic INT, - output logic OUT1N, - output logic OUT2N, - output logic RTSN, - output logic DTRN, - input wire CTSN, - input wire DSRN, - input wire DCDN, - input wire RIN, - input wire SIN, - output logic SOUT); // 507 -/* design apb_uart */ -/* architecture rtl */ -typedef enum {FALSE,TRUE} bool_t; // 527 -// Declare component uart_transmitter; // 950 -// Declare component uart_receiver; // 950 -// Declare component uart_interrupt; // 950 -// Declare component uart_baudgen; // 950 -// Declare component slib_edge_detect; // 950 -// Declare component slib_input_sync; // 950 -reg iWrite; // 612 -reg iRead; // 612 -reg iRST; // 612 -reg iRBRRead; // 612 -reg iTHRWrite; // 612 -reg iDLLWrite; // 612 -reg iDLMWrite; // 612 -reg iIERWrite; // 612 -reg iIIRRead; // 612 -reg iFCRWrite; // 612 -reg iLCRWrite; // 612 -reg iMCRWrite; // 612 -reg iLSRRead; // 612 -reg iMSRRead; // 612 -reg iSCRWrite; // 612 -reg [7:0] iTSR; // 605 -reg [7:0] iRBR; // 605 -reg [7:0] iDLL; // 605 -reg [7:0] iDLM; // 605 -reg [7:0] iIER; // 605 -reg [7:0] iIIR; // 605 -reg [7:0] iFCR; // 605 -reg [7:0] iLCR; // 605 -reg [7:0] iMCR; // 605 -reg [7:0] iLSR; // 605 -reg [7:0] iMSR; // 605 -reg [7:0] iSCR; // 605 -reg iIER_ERBI; // 612 -reg iIER_ETBEI; // 612 -reg iIER_ELSI; // 612 -reg iIER_EDSSI; // 612 -reg iIIR_PI; // 612 -reg iIIR_ID0; // 612 -reg iIIR_ID1; // 612 -reg iIIR_ID2; // 612 -reg iIIR_FIFO64; // 612 -reg iFCR_FIFOEnable; // 612 -reg iFCR_RXFIFOReset; // 612 -reg iFCR_TXFIFOReset; // 612 -reg iFCR_DMAMode; // 612 -reg iFCR_FIFO64E; // 612 -reg [1:0] iFCR_RXTrigger; // 605 -reg [1:0] iLCR_WLS; // 605 -reg iLCR_STB; // 612 -reg iLCR_PEN; // 612 -reg iLCR_EPS; // 612 -reg iLCR_SP; // 612 -reg iLCR_BC; // 612 -reg iLCR_DLAB; // 612 -reg iMCR_DTR; // 612 -reg iMCR_RTS; // 612 -reg iMCR_OUT1; // 612 -reg iMCR_OUT2; // 612 -reg iMCR_LOOP; // 612 -reg iMCR_AFE; // 612 -reg iLSR_DR; // 612 -reg iLSR_OE; // 612 -reg iLSR_PE; // 612 -reg iLSR_FE; // 612 -reg iLSR_BI; // 612 -reg iLSR_THRE; // 612 -reg iLSR_TEMT; // 612 -reg iLSR_FIFOERR; // 612 -reg iMSR_dCTS; // 612 -reg iMSR_dDSR; // 612 -reg iMSR_TERI; // 612 -reg iMSR_dDCD; // 612 -reg iMSR_CTS; // 612 -reg iMSR_DSR; // 612 -reg iMSR_RI; // 612 -reg iMSR_DCD; // 612 -reg iCTSNs; // 612 -reg iDSRNs; // 612 -reg iDCDNs; // 612 -reg iRINs; // 612 -reg iCTSn; // 612 -reg iDSRn; // 612 -reg iDCDn; // 612 -reg iRIn; // 612 -reg iCTSnRE; // 612 -reg iCTSnFE; // 612 -reg iDSRnRE; // 612 -reg iDSRnFE; // 612 -reg iDCDnRE; // 612 -reg iDCDnFE; // 612 -reg iRInRE; // 612 -reg iRInFE; // 612 -reg [15:0] iBaudgenDiv; // 605 -reg iBaudtick16x; // 612 -reg iBaudtick2x; // 612 -reg iRCLK; // 612 -reg iBAUDOUTN; // 612 -reg iTXFIFOClear; // 612 -reg iTXFIFOWrite; // 612 -reg iTXFIFORead; // 612 -reg iTXFIFOEmpty; // 612 -reg iTXFIFOFull; // 612 -reg iTXFIFO16Full; // 612 -reg iTXFIFO64Full; // 612 -reg [5:0] iTXFIFOUsage; // 605 -reg [7:0] iTXFIFOQ; // 605 -reg iRXFIFOClear; // 612 -reg iRXFIFOWrite; // 612 -reg iRXFIFORead; // 612 -reg iRXFIFOEmpty; // 612 -reg iRXFIFOFull; // 612 -reg iRXFIFO16Full; // 612 -reg iRXFIFO64Full; // 612 -reg [10:0] iRXFIFOD; // 605 -reg [10:0] iRXFIFOQ; // 605 -reg [5:0] iRXFIFOUsage; // 605 -reg iRXFIFOTrigger; // 612 -reg iRXFIFO16Trigger; // 612 -reg iRXFIFO64Trigger; // 612 -reg iRXFIFOPE; // 612 -reg iRXFIFOFE; // 612 -reg iRXFIFOBI; // 612 -reg iSOUT; // 612 -reg iTXStart; // 612 -reg iTXClear; // 612 -reg iTXFinished; // 612 -reg iTXRunning; // 612 -reg iSINr; // 612 -reg iSIN; // 612 -reg iRXFinished; // 612 -reg iRXClear; // 612 -reg [7:0] iRXData; // 605 -reg iRXPE; // 612 -reg iRXFE; // 612 -reg iRXBI; // 612 -reg iFERE; // 612 -reg iPERE; // 612 -reg iBIRE; // 612 -reg [6:0] iFECounter; // 900 -reg iFEIncrement; // 612 -reg iFEDecrement; // 612 -reg iRDAInterrupt; // 612 -reg [5:0] iTimeoutCount; // 605 -reg iCharTimeout; // 612 -reg iLSR_THRERE; // 612 -reg iTHRInterrupt; // 612 -reg iTXEnable; // 612 -reg iRTS; // 612 -assign /*903*/ iWrite = (PSEL == 1'b1 && PENABLE == 1'b1) && PWRITE == 1'b1 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iRead = (PSEL == 1'b1 && PENABLE == 1'b1) && PWRITE == 1'b0 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iRST = RSTN == 1'b0 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iRBRRead = (iRead == 1'b1 && PADDR == 3'b000) && iLCR_DLAB == 1'b0 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iTHRWrite = (iWrite == 1'b1 && PADDR == 3'b000) && iLCR_DLAB == 1'b0 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iDLLWrite = (iWrite == 1'b1 && PADDR == 3'b000) && iLCR_DLAB == 1'b1 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iDLMWrite = (iWrite == 1'b1 && PADDR == 3'b001) && iLCR_DLAB == 1'b1 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iIERWrite = (iWrite == 1'b1 && PADDR == 3'b001) && iLCR_DLAB == 1'b0 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iIIRRead = iRead == 1'b1 && PADDR == 3'b010 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iFCRWrite = iWrite == 1'b1 && PADDR == 3'b010 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iLCRWrite = iWrite == 1'b1 && PADDR == 3'b011 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iMCRWrite = iWrite == 1'b1 && PADDR == 3'b100 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iLSRRead = iRead == 1'b1 && PADDR == 3'b101 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iMSRRead = iRead == 1'b1 && PADDR == 3'b110 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iSCRWrite = iWrite == 1'b1 && PADDR == 3'b111 ? 1'b1 : 1'b0; // 905 -slib_input_sync UART_IS_SIN (CLK,iRST,SIN,iSINr); // 879 -slib_input_sync UART_IS_CTS (CLK,iRST,CTSN,iCTSNs); // 879 -slib_input_sync UART_IS_DSR (CLK,iRST,DSRN,iDSRNs); // 879 -slib_input_sync UART_IS_DCD (CLK,iRST,DCDN,iDCDNs); // 879 -slib_input_sync UART_IS_RI (CLK,iRST,RIN,iRINs); // 879 -slib_input_filter #(.SIZE(2)) UART_IF_CTS (CLK,iRST,iBaudtick2x,iCTSNs,iCTSn); // 879 -slib_input_filter #(.SIZE(2)) UART_IF_DSR (CLK,iRST,iBaudtick2x,iDSRNs,iDSRn); // 879 -slib_input_filter #(.SIZE(2)) UART_IF_DCD (CLK,iRST,iBaudtick2x,iDCDNs,iDCDn); // 879 -slib_input_filter #(.SIZE(2)) UART_IF_RI (CLK,iRST,iBaudtick2x,iRINs,iRIn); // 879 - -always @(posedge CLK or posedge iRST) - if ((iRST == 1'b1)) - begin - /* block const 263 */ - iDLL <= (0<<7)|(0<<6)|(0<<5)|(0<<4)|(0<<3)|(0<<2)|(0<<1)|(1<<0); - /* block const 263 */ - iDLM <= (0<<7)|(0<<6)|(0<<5)|(0<<4)|(0<<3)|(0<<2)|(0<<1)|(0<<0); - end - else - begin - if ((iDLLWrite == 1'b1)) - begin - iDLL <= PWDATA[7:0] ; // 413 - end - if ((iDLMWrite == 1'b1)) - begin - iDLM <= PWDATA[7:0] ; // 413 - end - end - -always @(posedge CLK or posedge iRST) - if ((iRST == 1'b1)) - begin - iIER[7:0] <= 0; - end - else - begin - if ((iIERWrite == 1'b1)) - begin - iIER[3:0] <= PWDATA[3:0]; - end - iIER[7:4] <= '0; - end - -assign /*432*/ iIER_ERBI = iIER[0]; // 434 -assign /*432*/ iIER_ETBEI = iIER[1]; // 434 -assign /*432*/ iIER_ELSI = iIER[2]; // 434 -assign /*432*/ iIER_EDSSI = iIER[3]; // 434 - -uart_interrupt UART_IIC ( - .CLK(CLK), - .RST(iRST), - .IER(iIER[3:0] ), - .LSR(iLSR[4:0] ), - .THI(iTHRInterrupt), - .RDA(iRDAInterrupt), - .CTI(iCharTimeout), - .AFE(iMCR_AFE), - .MSR(iMSR[3:0] ), - .IIR(iIIR[3:0] ), - .INT(INT)); // 879 -slib_edge_detect UART_IIC_THRE_ED ( - .CLK(CLK), - .RST(iRST), - .D(iLSR_THRE), - .RE(iLSR_THRERE), - .FE()); // 879 - -always @(posedge CLK or posedge iRST) - if ((iRST == 1'b1)) - begin - iTHRInterrupt <= 1'b0; // 413 - end - else - begin - if (((iLSR_THRERE == 1'b1 | iFCR_TXFIFOReset == 1'b1) | ((iIERWrite == 1'b1 && PWDATA[1] == 1'b1) && iLSR_THRE == 1'b1))) - begin - iTHRInterrupt <= 1'b1; // 413 - end - else if (((iIIRRead == 1'b1 && iIIR[3:1] == 3'b001) | iTHRWrite == 1'b1)) - begin - iTHRInterrupt <= 1'b0; // 413 - end - end - -assign /*903*/ iRDAInterrupt = (iFCR_FIFOEnable == 1'b0 && iLSR_DR == 1'b1) | (iFCR_FIFOEnable == 1'b1 && iRXFIFOTrigger == 1'b1) ? 1'b1 : 1'b0; // 905 -assign /*432*/ iIIR_PI = iIIR[0]; // 434 -assign /*432*/ iIIR_ID0 = iIIR[1]; // 434 -assign /*432*/ iIIR_ID1 = iIIR[2]; // 434 -assign /*432*/ iIIR_ID2 = iIIR[3]; // 434 -assign /*432*/ iIIR_FIFO64 = iIIR[5]; // 434 -assign iIIR[4] = 0; -assign iIIR[5] = iFCR_FIFOEnable ? iFCR_FIFO64E : 1'b0; -assign iIIR[6] = iFCR_FIFOEnable; -assign iIIR[7] = iFCR_FIFOEnable; - -always @(posedge CLK or posedge iRST) - if ((iRST == 1'b1)) - begin - /* block const 263 */ - iTimeoutCount <= (0<<5)|(0<<4)|(0<<3)|(0<<2)|(0<<1)|(0<<0); - iCharTimeout <= 1'b0; // 413 - end - else - begin - if (((iRXFIFOEmpty == 1'b1 | iRBRRead == 1'b1) | iRXFIFOWrite == 1'b1)) - begin - /* block const 263 */ - iTimeoutCount <= (0<<5)|(0<<4)|(0<<3)|(0<<2)|(0<<1)|(0<<0); - end - else if (((iRXFIFOEmpty == 1'b0 && iBaudtick2x == 1'b1) && iTimeoutCount[5] == 1'b0)) - begin - iTimeoutCount <= iTimeoutCount + 1; // 413 - end - if ((iFCR_FIFOEnable == 1'b1)) - begin - if ((iRBRRead == 1'b1)) - begin - iCharTimeout <= 1'b0; // 413 - end - else if ((iTimeoutCount[5] == 1'b1)) - begin - iCharTimeout <= 1'b1; // 413 - end - end - else - begin - iCharTimeout <= 1'b0; // 413 - end - end - -always @(posedge CLK or posedge iRST) - if ((iRST == 1'b1)) - begin - iFCR_FIFOEnable <= 1'b0; // 413 - iFCR_RXFIFOReset <= 1'b0; // 413 - iFCR_TXFIFOReset <= 1'b0; // 413 - iFCR_DMAMode <= 1'b0; // 413 - iFCR_FIFO64E <= 1'b0; // 413 - /* block const 263 */ - iFCR_RXTrigger <= (0<<1)|(0<<0); - end - else - begin - iFCR_RXFIFOReset <= 1'b0; // 413 - iFCR_TXFIFOReset <= 1'b0; // 413 - if ((iFCRWrite == 1'b1)) - begin - iFCR_FIFOEnable <= PWDATA[0]; // 413 - iFCR_DMAMode <= PWDATA[3]; // 413 - iFCR_RXTrigger <= PWDATA[7:6] ; // 413 - if ((iLCR_DLAB == 1'b1)) - begin - iFCR_FIFO64E <= PWDATA[5]; // 413 - end - - if (((PWDATA[1] == 1'b1 | (iFCR_FIFOEnable == 1'b0 && PWDATA[0] == 1'b1)) | (iFCR_FIFOEnable == 1'b1 && PWDATA[0] == 1'b0))) - begin - iFCR_RXFIFOReset <= 1'b1; // 413 - end - - if (((PWDATA[2] == 1'b1 | (iFCR_FIFOEnable == 1'b0 && PWDATA[0] == 1'b1)) | (iFCR_FIFOEnable == 1'b1 && PWDATA[0] == 1'b0))) - begin - iFCR_TXFIFOReset <= 1'b1; // 413 - end - end - end - -assign iFCR[0] = iFCR_FIFOEnable; -assign iFCR[1] = iFCR_RXFIFOReset; -assign iFCR[2] = iFCR_TXFIFOReset; -assign iFCR[3] = iFCR_DMAMode; -assign iFCR[4] = 1'b0; -assign iFCR[5] = iFCR_FIFO64E; -assign iFCR[7:6] = iFCR_RXTrigger; - -always @(posedge CLK or posedge iRST) - if ((iRST == 1'b1)) - begin - /* block const 263 */ - iLCR <= (0<<7)|(0<<6)|(0<<5)|(0<<4)|(0<<3)|(0<<2)|(0<<1)|(0<<0); - end - else - begin - if ((iLCRWrite == 1'b1)) - begin - iLCR <= PWDATA[7:0] ; // 413 - end - end - -assign /*432*/ iLCR_WLS = iLCR[1:0] ; // 434 -assign /*432*/ iLCR_STB = iLCR[2]; // 434 -assign /*432*/ iLCR_PEN = iLCR[3]; // 434 -assign /*432*/ iLCR_EPS = iLCR[4]; // 434 -assign /*432*/ iLCR_SP = iLCR[5]; // 434 -assign /*432*/ iLCR_BC = iLCR[6]; // 434 -assign /*432*/ iLCR_DLAB = iLCR[7]; // 434 - -always @(posedge CLK or posedge iRST) - if ((iRST == 1'b1)) - begin - iMCR[7:0] <= 0; - end - else - begin - if ((iMCRWrite == 1'b1)) - begin - iMCR[5:0] <= PWDATA[5:0]; - end - iMCR[7:6] <= 0; - end - -assign /*432*/ iMCR_DTR = iMCR[0]; // 434 -assign /*432*/ iMCR_RTS = iMCR[1]; // 434 -assign /*432*/ iMCR_OUT1 = iMCR[2]; // 434 -assign /*432*/ iMCR_OUT2 = iMCR[3]; // 434 -assign /*432*/ iMCR_LOOP = iMCR[4]; // 434 -assign /*432*/ iMCR_AFE = iMCR[5]; // 434 - -always @(posedge CLK or posedge iRST) - if ((iRST == 1'b1)) - begin - iLSR_OE <= 1'b0; // 413 - iLSR_PE <= 1'b0; // 413 - iLSR_FE <= 1'b0; // 413 - iLSR_BI <= 1'b0; // 413 - iFECounter <= 0; // 413 - iLSR_FIFOERR <= 1'b0; // 413 - end - else - begin - if ((((iFCR_FIFOEnable == 1'b0 && iLSR_DR == 1'b1) && iRXFinished == 1'b1) | ((iFCR_FIFOEnable == 1'b1 && iRXFIFOFull == 1'b1) && iRXFinished == 1'b1))) - begin - iLSR_OE <= 1'b1; // 413 - end - else if ((iLSRRead == 1'b1)) - begin - iLSR_OE <= 1'b0; // 413 - end - if ((iPERE == 1'b1)) - begin - iLSR_PE <= 1'b1; // 413 - end - else if ((iLSRRead == 1'b1)) - begin - iLSR_PE <= 1'b0; // 413 - end - if ((iFERE == 1'b1)) - begin - iLSR_FE <= 1'b1; // 413 - end - else if ((iLSRRead == 1'b1)) - begin - iLSR_FE <= 1'b0; // 413 - end - if ((iBIRE == 1'b1)) - begin - iLSR_BI <= 1'b1; // 413 - end - else if ((iLSRRead == 1'b1)) - begin - iLSR_BI <= 1'b0; // 413 - end - if ((iFECounter != 0)) - begin - iLSR_FIFOERR <= 1'b1; // 413 - end - else if ((iRXFIFOEmpty == 1'b1 | iRXFIFOQ[10:8] == 3'b000)) - begin - iLSR_FIFOERR <= 1'b0; // 413 - end - if ((iRXFIFOClear == 1'b1)) - begin - iFECounter <= 0; // 413 - end - else - begin - if ((iFEIncrement == 1'b1 && iFEDecrement == 1'b0)) - begin - iFECounter <= iFECounter + 1; // 413 - end - else if ((iFEIncrement == 1'b0 && iFEDecrement == 1'b1)) - begin - iFECounter <= iFECounter - 1; // 413 - end - end - end - -assign /*903*/ iRXFIFOPE = iRXFIFOEmpty == 1'b0 && iRXFIFOQ[8] == 1'b1 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iRXFIFOFE = iRXFIFOEmpty == 1'b0 && iRXFIFOQ[9] == 1'b1 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iRXFIFOBI = iRXFIFOEmpty == 1'b0 && iRXFIFOQ[10] == 1'b1 ? 1'b1 : 1'b0; // 905 -slib_edge_detect UART_PEDET (.CLK,.RST(iRST),.D(iRXFIFOPE),.RE(iPERE),.FE()); // 879 -slib_edge_detect UART_FEDET (.CLK,.RST(iRST),.D(iRXFIFOFE),.RE(iFERE),.FE()); // 879 -slib_edge_detect UART_BIDET (.CLK,.RST(iRST),.D(iRXFIFOBI),.RE(iBIRE),.FE()); // 879 -assign /*903*/ iFEIncrement = iRXFIFOWrite == 1'b1 && iRXFIFOD[10:8] != 3'b000 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iFEDecrement = (iFECounter != 0 && iRXFIFOEmpty == 1'b0) && ((iPERE == 1'b1 | iFERE == 1'b1) | iBIRE == 1'b1) ? 1'b1 : 1'b0; // 905 -assign iLSR[0] = iLSR_DR; -assign iLSR[1] = iLSR_OE; -assign iLSR[2] = iLSR_PE; -assign iLSR[3] = iLSR_FE; -assign iLSR[4] = iLSR_BI; -assign iLSR[5] = iLSR_THRE; -assign iLSR[6] = iLSR_TEMT; -assign iLSR[7] = iFCR_FIFOEnable && iLSR_FIFOERR; - -assign /*903*/ iLSR_DR = iRXFIFOEmpty == 1'b0 | iRXFIFOWrite == 1'b1 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iLSR_THRE = iTXFIFOEmpty == 1'b1 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iLSR_TEMT = iTXRunning == 1'b0 && iLSR_THRE == 1'b1 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iMSR_CTS = (iMCR_LOOP == 1'b1 && iRTS == 1'b1) | (iMCR_LOOP == 1'b0 && iCTSn == 1'b0) ? 1'b1 : 1'b0; // 905 -assign /*903*/ iMSR_DSR = (iMCR_LOOP == 1'b1 && iMCR_DTR == 1'b1) | (iMCR_LOOP == 1'b0 && iDSRn == 1'b0) ? 1'b1 : 1'b0; // 905 -assign /*903*/ iMSR_RI = (iMCR_LOOP == 1'b1 && iMCR_OUT1 == 1'b1) | (iMCR_LOOP == 1'b0 && iRIn == 1'b0) ? 1'b1 : 1'b0; // 905 -assign /*903*/ iMSR_DCD = (iMCR_LOOP == 1'b1 && iMCR_OUT2 == 1'b1) | (iMCR_LOOP == 1'b0 && iDCDn == 1'b0) ? 1'b1 : 1'b0; // 905 -slib_edge_detect UART_ED_CTS ( - .CLK(CLK), - .RST(iRST), - .D(iMSR_CTS), - .RE(iCTSnRE), - .FE(iCTSnFE)); // 879 -slib_edge_detect UART_ED_DSR ( - .CLK(CLK), - .RST(iRST), - .D(iMSR_DSR), - .RE(iDSRnRE), - .FE(iDSRnFE)); // 879 -slib_edge_detect UART_ED_RI ( - .CLK(CLK), - .RST(iRST), - .D(iMSR_RI), - .RE(iRInRE), - .FE(iRInFE)); // 879 -slib_edge_detect UART_ED_DCD ( - .CLK(CLK), - .RST(iRST), - .D(iMSR_DCD), - .RE(iDCDnRE), - .FE(iDCDnFE)); // 879 - -always @(posedge CLK or posedge iRST) - if ((iRST == 1'b1)) - begin - iMSR_dCTS <= 1'b0; // 413 - iMSR_dDSR <= 1'b0; // 413 - iMSR_TERI <= 1'b0; // 413 - iMSR_dDCD <= 1'b0; // 413 - end - else - begin - if ((iCTSnRE == 1'b1 | iCTSnFE == 1'b1)) - begin - iMSR_dCTS <= 1'b1; // 413 - end - else if ((iMSRRead == 1'b1)) - begin - iMSR_dCTS <= 1'b0; // 413 - end - if ((iDSRnRE == 1'b1 | iDSRnFE == 1'b1)) - begin - iMSR_dDSR <= 1'b1; // 413 - end - else if ((iMSRRead == 1'b1)) - begin - iMSR_dDSR <= 1'b0; // 413 - end - if ((iRInFE == 1'b1)) - begin - iMSR_TERI <= 1'b1; // 413 - end - else if ((iMSRRead == 1'b1)) - begin - iMSR_TERI <= 1'b0; // 413 - end - if ((iDCDnRE == 1'b1 | iDCDnFE == 1'b1)) - begin - iMSR_dDCD <= 1'b1; // 413 - end - else if ((iMSRRead == 1'b1)) - begin - iMSR_dDCD <= 1'b0; // 413 - end - end - -assign iMSR[0] = iMSR_dCTS; -assign iMSR[1] = iMSR_dDSR; -assign iMSR[2] = iMSR_TERI; -assign iMSR[3] = iMSR_dDCD; -assign iMSR[4] = iMSR_CTS; -assign iMSR[5] = iMSR_DSR; -assign iMSR[6] = iMSR_RI; -assign iMSR[7] = iMSR_DCD; - -always @(posedge CLK or posedge iRST) - if ((iRST == 1'b1)) - begin - /* block const 263 */ - iSCR <= (0<<7)|(0<<6)|(0<<5)|(0<<4)|(0<<3)|(0<<2)|(0<<1)|(0<<0); - end - else - begin - if ((iSCRWrite == 1'b1)) - begin - iSCR <= PWDATA[7:0] ; // 413 - end - end - -assign /*432*/ iBaudgenDiv = {iDLM, iDLL} -; // 434 -uart_baudgen UART_BG16 ( - .CLK(CLK), - .RST(iRST), - .CE( 1'b1), - .CLEAR( 1'b0), - .DIVIDER(iBaudgenDiv), - .BAUDTICK(iBaudtick16x)); // 879 -slib_clock_div #(.RATIO(8)) UART_BG2 ( - .CLK(CLK), - .RST(iRST), - .CE(iBaudtick16x), - .Q(iBaudtick2x)); // 879 -slib_edge_detect UART_RCLK ( - .CLK(CLK), - .RST(iRST), - .D(iBAUDOUTN), - .RE(iRCLK), - .FE()); // 879 -slib_fifo #(.WIDTH(8), .SIZE_E(6)) UART_TXFF ( - .CLK(CLK), - .RST(iRST), - .CLEAR(iTXFIFOClear), - .WRITE(iTXFIFOWrite), - .READ(iTXFIFORead), - .D(PWDATA[7:0] ), - .Q(iTXFIFOQ), - .EMPTY(iTXFIFOEmpty), - .FULL(iTXFIFO64Full), - .USAGE(iTXFIFOUsage)); // 879 -assign /*432*/ iTXFIFO16Full = iTXFIFOUsage[4]; // 434 -assign /*903*/ iTXFIFOFull = iFCR_FIFO64E == 1'b0 ? iTXFIFO16Full : iTXFIFO64Full; // 905 -assign /*903*/ iTXFIFOWrite = ((iFCR_FIFOEnable == 1'b0 && iTXFIFOEmpty == 1'b1) | (iFCR_FIFOEnable == 1'b1 && iTXFIFOFull == 1'b0)) && iTHRWrite == 1'b1 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iTXFIFOClear = iFCR_TXFIFOReset == 1'b1 ? 1'b1 : 1'b0; // 905 -slib_fifo #(.WIDTH(11), .SIZE_E(6)) UART_RXFF ( - .CLK(CLK), - .RST(iRST), - .CLEAR(iRXFIFOClear), - .WRITE(iRXFIFOWrite), - .READ(iRXFIFORead), - .D(iRXFIFOD), - .Q(iRXFIFOQ), - .EMPTY(iRXFIFOEmpty), - .FULL(iRXFIFO64Full), - .USAGE(iRXFIFOUsage)); // 879 -assign /*903*/ iRXFIFORead = iRBRRead == 1'b1 ? 1'b1 : 1'b0; // 905 -assign /*432*/ iRXFIFO16Full = iRXFIFOUsage[4]; // 434 -assign /*903*/ iRXFIFOFull = iFCR_FIFO64E == 1'b0 ? iRXFIFO16Full : iRXFIFO64Full; // 905 -assign /*432*/ iRBR = iRXFIFOQ[7:0] ; // 434 -assign /*903*/ iRXFIFO16Trigger = ((((iFCR_RXTrigger == 2'b00 && iRXFIFOEmpty == 1'b0) | (iFCR_RXTrigger == 2'b01 && (iRXFIFOUsage[2] == 1'b1 | iRXFIFOUsage[3] == 1'b1))) | (iFCR_RXTrigger == 2'b10 && iRXFIFOUsage[3] == 1'b1)) | (((iFCR_RXTrigger == 2'b11 && iRXFIFOUsage[3] == 1'b1) && iRXFIFOUsage[2] == 1'b1) && iRXFIFOUsage[1] == 1'b1)) | iRXFIFO16Full == 1'b1 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iRXFIFO64Trigger = ((((iFCR_RXTrigger == 2'b00 && iRXFIFOEmpty == 1'b0) | (iFCR_RXTrigger == 2'b01 && (iRXFIFOUsage[4] == 1'b1 | iRXFIFOUsage[5] == 1'b1))) | (iFCR_RXTrigger == 2'b10 && iRXFIFOUsage[5] == 1'b1)) | (((iFCR_RXTrigger == 2'b11 && iRXFIFOUsage[5] == 1'b1) && iRXFIFOUsage[4] == 1'b1) && iRXFIFOUsage[3] == 1'b1)) | iRXFIFO64Full == 1'b1 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iRXFIFOTrigger = iFCR_FIFO64E == 1'b0 ? iRXFIFO16Trigger : iRXFIFO64Trigger; // 905 -uart_transmitter UART_TX ( - .CLK(CLK), - .RST(iRST), - .TXCLK(iBaudtick2x), - .TXSTART(iTXStart), - .CLEAR(iTXClear), - .WLS(iLCR_WLS), - .STB(iLCR_STB), - .PEN(iLCR_PEN), - .EPS(iLCR_EPS), - .SP(iLCR_SP), - .BC(iLCR_BC), - .DIN(iTSR), - .TXFINISHED(iTXFinished), - .SOUT(iSOUT)); // 879 -assign /*432*/ iTXClear = 1'b0; // 434 -uart_receiver UART_RX ( - .CLK(CLK), - .RST(iRST), - .RXCLK(iRCLK), - .RXCLEAR(iRXClear), - .WLS(iLCR_WLS), - .STB(iLCR_STB), - .PEN(iLCR_PEN), - .EPS(iLCR_EPS), - .SP(iLCR_SP), - .SIN(iSIN), - .PE(iRXPE), - .FE(iRXFE), - .BI(iRXBI), - .DOUT(iRXData), - .RXFINISHED(iRXFinished)); // 879 -assign /*432*/ iRXClear = 1'b0; // 434 -assign /*903*/ iSIN = iMCR_LOOP == 1'b0 ? iSINr : iSOUT; // 905 -assign /*903*/ iTXEnable = iTXFIFOEmpty == 1'b0 && (iMCR_AFE == 1'b0 | (iMCR_AFE == 1'b1 && iMSR_CTS == 1'b1)) ? 1'b1 : 1'b0; // 905 - - typedef enum logic [1:0] {TXIDLE, TXSTART, TXRUN, TXEND} tx_state_type; - typedef enum logic {RXIDLE, RXSAVE} rx_state_type; - - rx_state_type rx_State; - tx_state_type tx_State; - - // Transmitter process - always @ (posedge CLK or posedge iRST) - if (iRST == 1'b1) - begin - tx_State <= TXIDLE; - iTSR <= 0; - iTXStart <= 1'b0; - iTXFIFORead <= 1'b0; - iTXRunning <= 1'b0; - end - else - begin - // Defaults - iTXStart <= 1'b0; - iTXFIFORead <= 1'b0; - iTXRunning <= 1'b0; - - case(tx_State) - TXIDLE : - begin - if (iTXEnable == 1'b1) - begin - iTXStart <= 1'b1; // Start transmitter - tx_State <= TXSTART; - end - else - tx_State <= TXIDLE; - end - TXSTART : - begin - iTSR <= iTXFIFOQ; - iTXStart <= 1'b1; // Start transmitter - iTXFIFORead <= 1'b1; // Increment TX FIFO read counter - tx_State <= TXRUN; - end - TXRUN : - begin - if (iTXFinished == 1'b1) // TX finished - tx_State <= TXEND; - else - tx_State <= TXRUN; - iTXRunning <= 1'b1; - iTXStart <= 1'b1; - end - TXEND : tx_State <= TXIDLE; - default : tx_State <= TXIDLE; - endcase; - end - - // Receiver process - always @(posedge CLK or posedge iRST) - if (iRST == 1'b1) - begin - rx_State <= RXIDLE; - iRXFIFOWrite <= 1'b0; - iRXFIFOClear <= 1'b0; - iRXFIFOD <= 0; - end - else - begin - // Defaults - iRXFIFOWrite <= 1'b0; - iRXFIFOClear <= iFCR_RXFIFOReset; - - case (rx_State) - RXIDLE : - begin - if (iRXFinished == 1'b1) - begin // Receive finished - iRXFIFOD <= {iRXBI, iRXFE, iRXPE, iRXData}; - if (iFCR_FIFOEnable == 1'b0) - iRXFIFOClear <= 1'b1; // Non-FIFO mode - rx_State <= RXSAVE; - end - else - rx_State <= RXIDLE; - end - RXSAVE : - begin - if (iFCR_FIFOEnable == 1'b0) - iRXFIFOWrite <= 1'b1; // Non-FIFO mode: Overwrite - else if (iRXFIFOFull == 1'b0) - iRXFIFOWrite <= 1'b1; // FIFO mode - rx_State <= RXIDLE; - end - default : rx_State <= RXIDLE; - endcase; // case rx_State - end - -always @(posedge CLK or posedge iRST) - if ((iRST == 1'b1)) - begin - iRTS <= 1'b0; // 413 - end - else - begin - if ((iMCR_RTS == 1'b0 | (iMCR_AFE == 1'b1 && iRXFIFOTrigger == 1'b1))) - begin - iRTS <= 1'b0; // 413 - end - else if ((iMCR_RTS == 1'b1 && (iMCR_AFE == 1'b0 | (iMCR_AFE == 1'b1 && iRXFIFOEmpty == 1'b1)))) - begin - iRTS <= 1'b1; // 413 - end - end - -always @(posedge CLK or posedge iRST) - if ((iRST == 1'b1)) - begin - iBAUDOUTN <= 1'b1; // 413 - OUT1N <= 1'b1; // 413 - OUT2N <= 1'b1; // 413 - RTSN <= 1'b1; // 413 - DTRN <= 1'b1; // 413 - SOUT <= 1'b1; // 413 - end - else - begin - iBAUDOUTN <= 1'b0; // 413 - OUT1N <= 1'b0; // 413 - OUT2N <= 1'b0; // 413 - RTSN <= 1'b0; // 413 - DTRN <= 1'b0; // 413 - SOUT <= 1'b0; // 413 - if ((iBaudtick16x == 1'b0)) - begin - iBAUDOUTN <= 1'b1; // 413 - end - - if ((iMCR_LOOP == 1'b1 | iMCR_OUT1 == 1'b0)) - begin - OUT1N <= 1'b1; // 413 - end - - if ((iMCR_LOOP == 1'b1 | iMCR_OUT2 == 1'b0)) - begin - OUT2N <= 1'b1; // 413 - end - - if ((iMCR_LOOP == 1'b1 | iRTS == 1'b0)) - begin - RTSN <= 1'b1; // 413 - end - - if ((iMCR_LOOP == 1'b1 | iMCR_DTR == 1'b0)) - begin - DTRN <= 1'b1; // 413 - end - - if ((iMCR_LOOP == 1'b1 | iSOUT == 1'b1)) - begin - SOUT <= 1'b1; // 413 - end - end - -always @(PADDR or iLCR_DLAB or iRBR or iDLL or iDLM or iIER or iIIR or iLCR or iMCR or iLSR or iMSR or iSCR) - begin - case (PADDR) - 3'b000: - begin - if ((iLCR_DLAB == 1'b0)) - begin - PRDATA[7:0] <= iRBR; - end - else - begin - PRDATA[7:0] <= iDLL; - end - end - - 3'b001: - begin - if ((iLCR_DLAB == 1'b0)) - begin - PRDATA[7:0] <= iIER; - end - else - begin - PRDATA[7:0] <= iDLM; - end - end - - 3'b010: - begin - PRDATA[7:0] <= iIIR; - end - - 3'b011: - begin - PRDATA[7:0] <= iLCR; - end - - 3'b100: - begin - PRDATA[7:0] <= iMCR; - end - - 3'b101: - begin - PRDATA[7:0] <= iLSR; - end - - 3'b110: - begin - PRDATA[7:0] <= iMSR; - end - - 3'b111: - begin - PRDATA[7:0] <= iSCR; - end - - default: - begin - PRDATA[7:0] <= iRBR; - end - - endcase - PRDATA[31:8] <= '0; - end - -assign /*432*/ PREADY = 1'b1; // 434 -assign /*432*/ PSLVERR = 1'b0; // 434 - -endmodule // apb_uart diff --git a/rtl/apb_uart/apb_uart_wrap.sv b/rtl/apb_uart/apb_uart_wrap.sv deleted file mode 100644 index 2076d59a..00000000 --- a/rtl/apb_uart/apb_uart_wrap.sv +++ /dev/null @@ -1,76 +0,0 @@ -// -// UART 16750 -// -// Author: Paul Scheffler -// -// Description: This wrapper adapts the flat interface of apb_uart to -// an interface using passed structs for APB and port -// names aligned with our style guide. Note that your -// APB must have a datawidth of 32 to match the IP. -// -// This code 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 code 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 library; if not, write to the -// Free Software Foundation, Inc., 59 Temple Place, Suite 330, -// Boston, MA 02111-1307 USA -// - -module apb_uart_wrap #( - parameter type apb_req_t = logic, - parameter type apb_rsp_t = logic -) ( - input logic clk_i, - input logic rst_ni, - - // APB - input apb_req_t apb_req_i, - output apb_rsp_t apb_rsp_o, - - // Physical interface - output logic intr_o, - output logic out1_no, - output logic out2_no, - output logic rts_no, - output logic dtr_no, - input logic cts_ni, - input logic dsr_ni, - input logic dcd_ni, - input logic rin_ni, - input logic sin_i, // RX - output logic sout_o // TX -); - - apb_uart i_apb_uart ( - .CLK ( clk_i ), - .RSTN ( rst_ni ), - .PSEL ( apb_req_i.psel ), - .PENABLE ( apb_req_i.penable ), - .PWRITE ( apb_req_i.pwrite ), - .PADDR ( apb_req_i.paddr[4:2] ), - .PWDATA ( apb_req_i.pwdata ), - .PRDATA ( apb_rsp_o.prdata ), - .PREADY ( apb_rsp_o.pready ), - .PSLVERR ( apb_rsp_o.pslverr ), - .INT ( intr_o ), - .OUT1N ( out1_no ), - .OUT2N ( out2_no ), - .RTSN ( rts_no ), - .DTRN ( dtr_no ), - .CTSN ( cts_ni ), - .DSRN ( dsr_ni ), - .DCDN ( dcd_ni ), - .RIN ( rin_ni ), - .SIN ( sin_i ), - .SOUT ( sout_o ) - ); - -endmodule diff --git a/rtl/apb_uart/reg_uart_wrap.sv b/rtl/apb_uart/reg_uart_wrap.sv deleted file mode 100644 index 8b955310..00000000 --- a/rtl/apb_uart/reg_uart_wrap.sv +++ /dev/null @@ -1,100 +0,0 @@ -// -// UART 16750 -// -// Authors: -// Paul Scheffler -// Nicole Narr -// Christopher Reinwardt -// -// Description: This wrapper adapts the flat interface of apb_uart to -// the Regbus interface. Note that your Regbus must have -// a datawidth of 32 to match the IP. -// -// This code 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 code 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 library; if not, write to the -// Free Software Foundation, Inc., 59 Temple Place, Suite 330, -// Boston, MA 02111-1307 USA -// - -`include "apb/typedef.svh" - -module reg_uart_wrap #( - parameter int unsigned AddrWidth = -1, - parameter type reg_req_t = logic, - parameter type reg_rsp_t = logic -) ( - input logic clk_i, - input logic rst_ni, - - // Regbus - input reg_req_t reg_req_i, - output reg_rsp_t reg_rsp_o, - - // Physical interface - output logic intr_o, - output logic out1_no, - output logic out2_no, - output logic rts_no, - output logic dtr_no, - input logic cts_ni, - input logic dsr_ni, - input logic dcd_ni, - input logic rin_ni, - input logic sin_i, // RX - output logic sout_o // TX -); - `APB_TYPEDEF_REQ_T(reg_uart_apb_req_t, logic [AddrWidth-1:0], logic [31:0], logic [3:0]) - `APB_TYPEDEF_RESP_T(reg_uart_apb_rsp_t, logic [31:0]) - - reg_uart_apb_req_t uart_apb_req; - reg_uart_apb_rsp_t uart_apb_rsp; - - reg_to_apb #( - .reg_req_t ( reg_req_t ), - .reg_rsp_t ( reg_rsp_t ), - .apb_req_t ( reg_uart_apb_req_t ), - .apb_rsp_t ( reg_uart_apb_rsp_t ) - ) i_reg_uart_reg_to_apb ( - .clk_i, - .rst_ni, - .reg_req_i, - .reg_rsp_o, - .apb_req_o ( uart_apb_req ), - .apb_rsp_i ( uart_apb_rsp ) - ); - - apb_uart i_apb_uart ( - .CLK ( clk_i ), - .RSTN ( rst_ni ), - .PSEL ( uart_apb_req.psel ), - .PENABLE ( uart_apb_req.penable ), - .PWRITE ( uart_apb_req.pwrite ), - .PADDR ( uart_apb_req.paddr[4:2] ), - .PWDATA ( uart_apb_req.pwdata ), - .PRDATA ( uart_apb_rsp.prdata ), - .PREADY ( uart_apb_rsp.pready ), - .PSLVERR ( uart_apb_rsp.pslverr ), - .INT ( intr_o ), - .OUT1N ( out1_no ), - .OUT2N ( out2_no ), - .RTSN ( rts_no ), - .DTRN ( dtr_no ), - .CTSN ( cts_ni ), - .DSRN ( dsr_ni ), - .DCDN ( dcd_ni ), - .RIN ( rin_ni ), - .SIN ( sin_i ), - .SOUT ( sout_o ) - ); - -endmodule diff --git a/rtl/apb_uart/slib_clock_div.sv b/rtl/apb_uart/slib_clock_div.sv deleted file mode 100644 index c5222429..00000000 --- a/rtl/apb_uart/slib_clock_div.sv +++ /dev/null @@ -1,75 +0,0 @@ -// -// UART 16750 -// -// Converted to System Verilog by Jonathan Kimmitt -// This version has been partially checked with formality but some bugs remain -// Original Author: Sebastian Witt -// Date: 14.03.2019 -// Version: 1.6 -// -// History: 1.0 - Initial version -// 1.1 - THR empty interrupt register connected to RST -// 1.2 - Registered outputs -// 1.3 - Automatic flow control -// 1.4 - De-assert IIR FIFO64 when FIFO is disabled -// 1.5 - Inverted low active outputs when RST is active -// 1.6 - Converted to System Verilog -// -// -// This code 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 code 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 library; if not, write to the -// Free Software Foundation, Inc., 59 Temple Place, Suite 330, -// Boston, MA 02111-1307 USA -// - -module slib_clock_div #(parameter RATIO = 4) ( - input wire CLK, - input wire RST, - input wire CE, - output logic Q); // 507 -/* design slib_clock_div */ -/* architecture rtl */ -typedef enum {FALSE,TRUE} bool_t; // 527 -reg iQ; // 612 -reg [$clog2(RATIO-1)-1:0] iCounter; - -always @(posedge CLK or posedge RST) -begin -if ((RST == 1'b1)) - begin - iCounter <= 0; // 413 - iQ <= 1'b0; // 413 - end - else - begin - iQ <= 1'b0; // 413 - if ((CE == 1'b1)) - begin - if ((iCounter == (RATIO - 1))) - begin - iQ <= 1'b1; // 413 - iCounter <= 0; // 413 - end - else - begin - iCounter <= iCounter + 1; // 413 - end - end - - end - -end - -assign /*432*/ Q = iQ; // 434 - -endmodule // slib_clock_div diff --git a/rtl/apb_uart/slib_counter.sv b/rtl/apb_uart/slib_counter.sv deleted file mode 100644 index 59cdd5a6..00000000 --- a/rtl/apb_uart/slib_counter.sv +++ /dev/null @@ -1,88 +0,0 @@ -// -// UART 16750 -// -// Converted to System Verilog by Jonathan Kimmitt -// This version has been partially checked with formality but some bugs remain -// Original Author: Sebastian Witt -// Date: 14.03.2019 -// Version: 1.6 -// -// History: 1.0 - Initial version -// 1.1 - THR empty interrupt register connected to RST -// 1.2 - Registered outputs -// 1.3 - Automatic flow control -// 1.4 - De-assert IIR FIFO64 when FIFO is disabled -// 1.5 - Inverted low active outputs when RST is active -// 1.6 - Converted to System Verilog -// -// -// This code 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 code 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 library; if not, write to the -// Free Software Foundation, Inc., 59 Temple Place, Suite 330, -// Boston, MA 02111-1307 USA -// - -module slib_counter # (parameter WIDTH = 4) ( - input wire CLK, - input wire RST, - input wire CLEAR, - input wire LOAD, - input wire ENABLE, - input wire DOWN, - input wire [WIDTH - 1:0] D, - output logic [WIDTH - 1:0] Q, - output logic OVERFLOW); // 507 -/* design slib_counter */ -/* architecture rtl */ -typedef enum {FALSE,TRUE} bool_t; // 527 -reg [WIDTH:0] iCounter; // 605 - -always @(posedge CLK or posedge RST) -if (RST) - begin - /* block const 263 */ - iCounter <= 0; - end -else - begin - if ((CLEAR == 1'b1)) - begin - /* block const 263 */ - iCounter <= 0; - end - else if ((LOAD == 1'b1)) - begin - iCounter <= $unsigned({ 1'b0, D}); // 413 - end - - else if ((ENABLE == 1'b1)) - begin - if ((DOWN == 1'b0)) - begin - iCounter <= iCounter + 1; // 413 - end - else - begin - iCounter <= iCounter - 1; // 413 - end - end - - if ((iCounter[WIDTH] == 1'b1)) - begin - iCounter[WIDTH] <= 0; - end - end - -assign /*432*/ Q = iCounter[WIDTH - 1:0]; // 434 -assign /*432*/ OVERFLOW = iCounter[WIDTH]; // 434 -endmodule // slib_counter diff --git a/rtl/apb_uart/slib_edge_detect.sv b/rtl/apb_uart/slib_edge_detect.sv deleted file mode 100644 index 768b2a0e..00000000 --- a/rtl/apb_uart/slib_edge_detect.sv +++ /dev/null @@ -1,62 +0,0 @@ -// -// UART 16750 -// -// Converted to System Verilog by Jonathan Kimmitt -// This version has been partially checked with formality but some bugs remain -// Original Author: Sebastian Witt -// Date: 14.03.2019 -// Version: 1.6 -// -// History: 1.0 - Initial version -// 1.1 - THR empty interrupt register connected to RST -// 1.2 - Registered outputs -// 1.3 - Automatic flow control -// 1.4 - De-assert IIR FIFO64 when FIFO is disabled -// 1.5 - Inverted low active outputs when RST is active -// 1.6 - Converted to System Verilog -// -// -// This code 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 code 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 library; if not, write to the -// Free Software Foundation, Inc., 59 Temple Place, Suite 330, -// Boston, MA 02111-1307 USA -// - -module slib_edge_detect( - input wire CLK, - input wire RST, - input wire D, - output logic RE, - output logic FE); // 507 -/* design slib_edge_detect */ -/* architecture rtl */ -typedef enum {FALSE,TRUE} bool_t; // 527 -reg iDd; // 612 - -always @(posedge CLK or posedge RST) -begin -if ((RST == 1'b1)) - begin - iDd <= 1'b0; // 413 - end - else - begin - iDd <= D; // 413 - end - -end - -assign /*903*/ RE = iDd == 1'b0 && D == 1'b1 ? 1'b1 : 1'b0; // 905 -assign /*903*/ FE = iDd == 1'b1 && D == 1'b0 ? 1'b1 : 1'b0; // 905 - -endmodule // slib_edge_detect diff --git a/rtl/apb_uart/slib_fifo.sv b/rtl/apb_uart/slib_fifo.sv deleted file mode 100644 index 255b7a93..00000000 --- a/rtl/apb_uart/slib_fifo.sv +++ /dev/null @@ -1,159 +0,0 @@ -// -// UART 16750 -// -// Converted to System Verilog by Jonathan Kimmitt -// This version has been partially checked with formality but some bugs remain -// Original Author: Sebastian Witt -// Date: 14.03.2019 -// Version: 1.6 -// -// History: 1.0 - Initial version -// 1.1 - THR empty interrupt register connected to RST -// 1.2 - Registered outputs -// 1.3 - Automatic flow control -// 1.4 - De-assert IIR FIFO64 when FIFO is disabled -// 1.5 - Inverted low active outputs when RST is active -// 1.6 - Converted to System Verilog -// -// -// This code 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 code 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 library; if not, write to the -// Free Software Foundation, Inc., 59 Temple Place, Suite 330, -// Boston, MA 02111-1307 USA -// - -module slib_fifo # (parameter WIDTH = 8, parameter SIZE_E=6) ( - input wire CLK, - input wire RST, - input wire CLEAR, - input wire WRITE, - input wire READ, - input wire [WIDTH - 1:0] D, - output logic [WIDTH - 1:0] Q, - output logic EMPTY, - output logic FULL, - output logic [SIZE_E - 1:0] USAGE); // 507 -/* design slib_fifo */ -/* architecture rtl */ -typedef enum {FALSE,TRUE} bool_t; // 527 -reg iEMPTY; // 612 -reg iFULL; // 612 -reg [SIZE_E:0] iWRAddr; // 605 -reg [SIZE_E:0] iRDAddr; // 605 -reg [SIZE_E:0] init; // 605 -reg [SIZE_E - 1:0] iUSAGE; // 605 -reg [WIDTH-1:0] iFIFOMem [0:2**SIZE_E-1]; - -assign /*903*/ iFULL = (iRDAddr[SIZE_E - 1:0] == iWRAddr[SIZE_E - 1:0] ) && (iRDAddr[SIZE_E] != iWRAddr[SIZE_E]) ? 1'b1 : 1'b0; // 905 - -always @(posedge CLK or posedge RST) -begin -if ((RST == 1'b1)) - begin - /* block const 263 */ -iWRAddr <= 0; -/* block const 263 */ -iRDAddr <= 0; -iEMPTY <= 1'b1; // 413 - end - else - begin - if ((WRITE == 1'b1 && iFULL == 1'b0)) - begin - iWRAddr <= iWRAddr + 1; // 413 - end - -if ((READ == 1'b1 && iEMPTY == 1'b0)) - begin - iRDAddr <= iRDAddr + 1; // 413 - end - -if ((CLEAR == 1'b1)) - begin - /* block const 263 */ -iWRAddr <= 0; -/* block const 263 */ -iRDAddr <= 0; - end - -if ((iRDAddr == iWRAddr)) - begin - iEMPTY <= 1'b1; // 413 - end - else - begin - iEMPTY <= 1'b0; // 413 - end - end - -end - - -always @(posedge CLK or posedge RST) -begin -if ((RST == 1'b1)) - begin - /* block const 263 */ - for (init = 0; init < 2**SIZE_E; init++) - iFIFOMem[init[SIZE_E-1:0]] <= 0; - Q <= (0<<0); - end - else - begin - if ((WRITE == 1'b1 && iFULL == 1'b0)) - begin - iFIFOMem[iWRAddr[SIZE_E-1:0]] <= D; - end - -Q <= iFIFOMem[iRDAddr[SIZE_E - 1:0]]; // 413 - end - -end - - -always @(posedge CLK or posedge RST) -begin -if ((RST == 1'b1)) - begin - /* block const 263 */ -iUSAGE <= 0; - end - else - begin - if ((CLEAR == 1'b1)) - begin - /* block const 263 */ -iUSAGE <= 0; - end - else - begin - if (((READ == 1'b0 && WRITE == 1'b1) && iFULL == 1'b0)) - begin - iUSAGE <= iUSAGE + 1; // 413 - end - -if (((WRITE == 1'b0 && READ == 1'b1) && iEMPTY == 1'b0)) - begin - iUSAGE <= iUSAGE - 1; // 413 - end - - end - end - -end - -assign /*432*/ EMPTY = iEMPTY; // 434 -assign /*432*/ FULL = iFULL; // 434 -assign /*432*/ USAGE = iUSAGE; // 434 - -endmodule // slib_fifo diff --git a/rtl/apb_uart/slib_input_filter.sv b/rtl/apb_uart/slib_input_filter.sv deleted file mode 100644 index 3ddab477..00000000 --- a/rtl/apb_uart/slib_input_filter.sv +++ /dev/null @@ -1,81 +0,0 @@ -// -// UART 16750 -// -// Converted to System Verilog by Jonathan Kimmitt -// This version has been partially checked with formality but some bugs remain -// Original Author: Sebastian Witt -// Date: 14.03.2019 -// Version: 1.6 -// -// History: 1.0 - Initial version -// 1.1 - THR empty interrupt register connected to RST -// 1.2 - Registered outputs -// 1.3 - Automatic flow control -// 1.4 - De-assert IIR FIFO64 when FIFO is disabled -// 1.5 - Inverted low active outputs when RST is active -// 1.6 - Converted to System Verilog -// -// -// This code 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 code 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 library; if not, write to the -// Free Software Foundation, Inc., 59 Temple Place, Suite 330, -// Boston, MA 02111-1307 USA -// - -module slib_input_filter #(parameter SIZE = 4) ( - input wire CLK, - input wire RST, - input wire CE, - input wire D, - output logic Q); // 507 -/* design slib_input_filter */ -/* architecture rtl */ -typedef enum {FALSE,TRUE} bool_t; // 527 - -reg [$clog2(SIZE+1)-1:0] iCount; - -always @(posedge CLK or posedge RST) - begin - if ((RST == 1'b1)) - begin - iCount <= 0; // 413 - Q <= 1'b0; // 413 - end - else - begin - if ((CE == 1'b1)) - begin - if ((D == 1'b1) && (iCount != SIZE)) - begin - iCount <= iCount + 1; // 413 - end - else if ((D == 1'b0) && (iCount != 0)) - begin - iCount <= iCount - 1; // 413 - end - end - - if ((iCount == SIZE)) - begin - Q <= 1'b1; // 413 - end - else if ((iCount == 0)) - begin - Q <= 1'b0; // 413 - end - end - - end - - -endmodule diff --git a/rtl/apb_uart/slib_input_sync.sv b/rtl/apb_uart/slib_input_sync.sv deleted file mode 100644 index e2eb76f0..00000000 --- a/rtl/apb_uart/slib_input_sync.sv +++ /dev/null @@ -1,60 +0,0 @@ -// -// UART 16750 -// -// Converted to System Verilog by Jonathan Kimmitt -// This version has been partially checked with formality but some bugs remain -// Original Author: Sebastian Witt -// Date: 14.03.2019 -// Version: 1.6 -// -// History: 1.0 - Initial version -// 1.1 - THR empty interrupt register connected to RST -// 1.2 - Registered outputs -// 1.3 - Automatic flow control -// 1.4 - De-assert IIR FIFO64 when FIFO is disabled -// 1.5 - Inverted low active outputs when RST is active -// 1.6 - Converted to System Verilog -// -// -// This code 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 code 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 library; if not, write to the -// Free Software Foundation, Inc., 59 Temple Place, Suite 330, -// Boston, MA 02111-1307 USA -// - -module slib_input_sync( - input wire CLK, - input wire RST, - input wire D, - output logic Q); // 507 -/* design slib_input_sync */ -/* architecture rtl */ -typedef enum {FALSE,TRUE} bool_t; // 527 -reg [1:0] iD; // 605 - -always @(posedge CLK or posedge RST) - begin - if ((RST == 1'b1)) - begin - /* block const 263 */ - iD <= (0<<1)|(0<<0); - end - else - begin - iD[0] <= D; - iD[1] <= iD[0]; - end - end - -assign /*432*/ Q = iD[1]; // 434 -endmodule // slib_input_sync diff --git a/rtl/apb_uart/slib_mv_filter.sv b/rtl/apb_uart/slib_mv_filter.sv deleted file mode 100644 index 363b89e1..00000000 --- a/rtl/apb_uart/slib_mv_filter.sv +++ /dev/null @@ -1,78 +0,0 @@ -// -// UART 16750 -// -// Converted to System Verilog by Jonathan Kimmitt -// This version has been partially checked with formality but some bugs remain -// Original Author: Sebastian Witt -// Date: 14.03.2019 -// Version: 1.6 -// -// History: 1.0 - Initial version -// 1.1 - THR empty interrupt register connected to RST -// 1.2 - Registered outputs -// 1.3 - Automatic flow control -// 1.4 - De-assert IIR FIFO64 when FIFO is disabled -// 1.5 - Inverted low active outputs when RST is active -// 1.6 - Converted to System Verilog -// -// -// This code 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 code 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 library; if not, write to the -// Free Software Foundation, Inc., 59 Temple Place, Suite 330, -// Boston, MA 02111-1307 USA -// - -module slib_mv_filter #(parameter WIDTH = 4, parameter THRESHOLD = 10) ( - input wire CLK, - input wire RST, - input wire SAMPLE, - input wire CLEAR, - input wire D, - output logic Q); // 507 -/* design slib_mv_filter */ -/* architecture rtl */ -typedef enum {FALSE,TRUE} bool_t; // 527 -reg [WIDTH:0] iCounter; // 605 -reg iQ; // 612 - -always @(posedge CLK or posedge RST) - if (RST) - begin - /* block const 263 */ - iCounter <= 0; - iQ <= 1'b0; // 413 - end - else - begin - if (iCounter >= THRESHOLD) - begin - iQ <= 1'b1; // 413 - end - else - begin - if ((SAMPLE == 1'b1 && D == 1'b1)) - begin - iCounter <= iCounter + 1; // 413 - end - end - if ((CLEAR == 1'b1)) - begin - /* block const 263 */ - iCounter <= 0; - iQ <= 1'b0; // 413 - end - end - -assign /*432*/ Q = iQ; // 434 - -endmodule // slib_mv_filter diff --git a/rtl/apb_uart/uart_baudgen.sv b/rtl/apb_uart/uart_baudgen.sv deleted file mode 100644 index 47904acc..00000000 --- a/rtl/apb_uart/uart_baudgen.sv +++ /dev/null @@ -1,78 +0,0 @@ -// -// UART 16750 -// -// Converted to System Verilog by Jonathan Kimmitt -// This version has been partially checked with formality but some bugs remain -// Original Author: Sebastian Witt -// Date: 14.03.2019 -// Version: 1.6 -// -// History: 1.0 - Initial version -// 1.1 - THR empty interrupt register connected to RST -// 1.2 - Registered outputs -// 1.3 - Automatic flow control -// 1.4 - De-assert IIR FIFO64 when FIFO is disabled -// 1.5 - Inverted low active outputs when RST is active -// 1.6 - Converted to System Verilog -// -// -// This code 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 code 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 library; if not, write to the -// Free Software Foundation, Inc., 59 Temple Place, Suite 330, -// Boston, MA 02111-1307 USA -// - -module uart_baudgen( - input wire CLK, - input wire RST, - input wire CE, - input wire CLEAR, - input wire [15:0] DIVIDER, - output logic BAUDTICK); // 507 -/* design uart_baudgen */ -/* architecture rtl */ -typedef enum {FALSE,TRUE} bool_t; // 527 -reg [15:0] iCounter; // 605 - -always @(posedge CLK or posedge RST) -begin -if ((RST == 1'b1)) - begin - /* block const 263 */ -iCounter <= (0<<15)|(0<<14)|(0<<13)|(0<<12)|(0<<11)|(0<<10)|(0<<9)|(0<<8)|(0<<7)|(0<<6)|(0<<5)|(0<<4)|(0<<3)|(0<<2)|(0<<1)|(0<<0); -BAUDTICK <= 1'b0; // 413 - end - else - begin - if ((CLEAR == 1'b1)) - begin - /* block const 263 */ -iCounter <= (0<<15)|(0<<14)|(0<<13)|(0<<12)|(0<<11)|(0<<10)|(0<<9)|(0<<8)|(0<<7)|(0<<6)|(0<<5)|(0<<4)|(0<<3)|(0<<2)|(0<<1)|(0<<0); - end - else if ((CE == 1'b1)) - begin - iCounter <= iCounter - 1; // 413 - end - BAUDTICK <= 1'b0; // 413 - if (iCounter == '0) - begin - /* block const 263 */ -iCounter <= $unsigned(DIVIDER) - 1; -BAUDTICK <= 1'b1; // 413 - end - - end - -end - -endmodule // uart_baudgen diff --git a/rtl/apb_uart/uart_interrupt.sv b/rtl/apb_uart/uart_interrupt.sv deleted file mode 100644 index 98b33247..00000000 --- a/rtl/apb_uart/uart_interrupt.sv +++ /dev/null @@ -1,98 +0,0 @@ -// -// UART 16750 -// -// Converted to System Verilog by Jonathan Kimmitt -// This version has been partially checked with formality but some bugs remain -// Original Author: Sebastian Witt -// Date: 14.03.2019 -// Version: 1.6 -// -// History: 1.0 - Initial version -// 1.1 - THR empty interrupt register connected to RST -// 1.2 - Registered outputs -// 1.3 - Automatic flow control -// 1.4 - De-assert IIR FIFO64 when FIFO is disabled -// 1.5 - Inverted low active outputs when RST is active -// 1.6 - Converted to System Verilog -// -// -// This code 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 code 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 library; if not, write to the -// Free Software Foundation, Inc., 59 Temple Place, Suite 330, -// Boston, MA 02111-1307 USA -// - -module uart_interrupt( - input wire CLK, - input wire RST, - input wire [3:0] IER, - input wire [4:0] LSR, - input wire THI, - input wire RDA, - input wire CTI, - input wire AFE, - input wire [3:0] MSR, - output logic [3:0] IIR, - output logic INT); // 507 -/* design uart_interrupt */ -/* architecture rtl */ -typedef enum {FALSE,TRUE} bool_t; // 527 -reg iRLSInterrupt; // 612 -reg iRDAInterrupt; // 612 -reg iCTIInterrupt; // 612 -reg iTHRInterrupt; // 612 -reg iMSRInterrupt; // 612 -reg [3:0] iIIR; // 605 -assign /*432*/ iRLSInterrupt = IER[2] && (((LSR[1] | LSR[2]) | LSR[3]) | LSR[4]); // 434 -assign /*432*/ iRDAInterrupt = IER[0] && RDA; // 434 -assign /*432*/ iCTIInterrupt = IER[0] && CTI; // 434 -assign /*432*/ iTHRInterrupt = IER[1] && THI; // 434 -assign /*432*/ iMSRInterrupt = IER[3] && ((((MSR[0] && ~ AFE) | MSR[1]) | MSR[2]) | MSR[3]); // 434 - -always @(posedge CLK or posedge RST) - if ((RST == 1'b1)) - begin - iIIR <= 4'b0001; // 413 - end - else - begin - if ((iRLSInterrupt == 1'b1)) - begin - iIIR <= 4'b0110; // 413 - end - else if ((iCTIInterrupt == 1'b1)) - begin - iIIR <= 4'b1100; // 413 - end - else if ((iRDAInterrupt == 1'b1)) - begin - iIIR <= 4'b0100; // 413 - end - else if ((iTHRInterrupt == 1'b1)) - begin - iIIR <= 4'b0010; // 413 - end - else if ((iMSRInterrupt == 1'b1)) - begin - iIIR <= 4'b0000; // 413 - end - else - begin - iIIR <= 4'b0001; // 413 - end - end - -assign /*432*/ IIR = iIIR; // 434 -assign /*432*/ INT = ~ iIIR[0]; // 434 - -endmodule // uart_interrupt diff --git a/rtl/apb_uart/uart_receiver.sv b/rtl/apb_uart/uart_receiver.sv deleted file mode 100644 index 0cf79596..00000000 --- a/rtl/apb_uart/uart_receiver.sv +++ /dev/null @@ -1,315 +0,0 @@ -// -// UART 16750 -// -// Converted to System Verilog by Jonathan Kimmitt -// This version has been partially checked with formality but some bugs remain -// Original Author: Sebastian Witt -// Date: 14.03.2019 -// Version: 1.6 -// -// History: 1.0 - Initial version -// 1.1 - THR empty interrupt register connected to RST -// 1.2 - Registered outputs -// 1.3 - Automatic flow control -// 1.4 - De-assert IIR FIFO64 when FIFO is disabled -// 1.5 - Inverted low active outputs when RST is active -// 1.6 - Converted to System Verilog -// -// -// This code 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 code 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 library; if not, write to the -// Free Software Foundation, Inc., 59 Temple Place, Suite 330, -// Boston, MA 02111-1307 USA -// - -module uart_receiver( - input wire CLK, - input wire RST, - input wire RXCLK, - input wire RXCLEAR, - input wire [1:0] WLS, - input wire STB, - input wire PEN, - input wire EPS, - input wire SP, - input wire SIN, - output logic PE, - output logic FE, - output logic BI, - output logic [7:0] DOUT, - output logic RXFINISHED); // 507 -/* design uart_receiver */ -/* architecture rtl */ -typedef enum {FALSE,TRUE} bool_t; // 527 -typedef enum logic [2:0] {IDLE, -START, -DATA, -PAR, -STOP, -MWAIT} state_type; // 674 -state_type CState, NState; // 908 -reg [3:0] iBaudCount; // 605 -reg iBaudCountClear; // 612 -reg iBaudStep; // 612 -reg iBaudStepD; // 612 -reg iFilterClear; // 612 -reg iFSIN; // 612 -reg iFStopBit; // 612 -reg iParity; // 612 -reg iParityReceived; // 612 -reg [3:0] iDataCount; // 900 -reg iDataCountInit; // 612 -reg iDataCountFinish; // 612 -reg iRXFinished; // 612 -reg iFE; // 612 -reg iBI; // 612 -reg iNoStopReceived; // 612 -reg [7:0] iDOUT; // 605 -slib_counter #(.WIDTH(4)) RX_BRC ( - .CLK(CLK), - .RST(RST), - .CLEAR(iBaudCountClear), - .LOAD( 1'b0), - .ENABLE(RXCLK), - .DOWN( 1'b0), - .D(4'b0000), - .Q(iBaudCount), - .OVERFLOW(iBaudStep)); // 879 -slib_mv_filter #(.WIDTH(4),.THRESHOLD(10)) RX_MVF ( - .CLK(CLK), - .RST(RST), - .SAMPLE(RXCLK), - .CLEAR(iFilterClear), - .D(SIN), - .Q(iFSIN)); // 879 -slib_input_filter #(.SIZE(4)) RX_IFSB ( - .CLK(CLK), - .RST(RST), - .CE(RXCLK), - .D(SIN), - .Q(iFStopBit)); // 879 - -always @(posedge CLK or posedge RST) - begin - if ((RST == 1'b1)) - begin - iBaudStepD <= 1'b0; // 413 - end - else - begin - iBaudStepD <= iBaudStep; // 413 - end - end - -assign /*432*/ iFilterClear = iBaudStepD | iBaudCountClear; // 434 - -always @(iDOUT or EPS) -begin -iParity <= (((((((iDOUT[7] ^ iDOUT[6]) ^ iDOUT[5]) ^ iDOUT[4]) ^ iDOUT[3]) ^ iDOUT[2]) ^ iDOUT[1]) ^ iDOUT[0]) ^ ~ EPS; // 413 - -end - - -always @(posedge CLK or posedge RST) - if ((RST == 1'b1)) - begin - iDataCount <= 0; // 413 - /* block const 263 */ - iDOUT <= (0<<7)|(0<<6)|(0<<5)|(0<<4)|(0<<3)|(0<<2)|(0<<1)|(0<<0); - end - else - begin - if ((iDataCountInit == 1'b1)) - begin - iDataCount <= 0; // 413 - /* block const 263 */ - iDOUT <= (0<<7)|(0<<6)|(0<<5)|(0<<4)|(0<<3)|(0<<2)|(0<<1)|(0<<0); - end - else - begin - if ((iBaudStep == 1'b1 && iDataCountFinish == 1'b0)) - begin - iDOUT[iDataCount] <= iFSIN; - iDataCount <= iDataCount + 1; // 413 - end - end - end - -assign /*903*/ iDataCountFinish = (((WLS == 2'b00 && iDataCount == 5) | (WLS == 2'b01 && iDataCount == 6)) | (WLS == 2'b10 && iDataCount == 7)) | (WLS == 2'b11 && iDataCount == 8) ? 1'b1 : 1'b0; // 905 - -always @(posedge CLK or posedge RST) - if ((RST == 1'b1)) - begin - CState <= IDLE; // 413 - end - else - begin - CState <= NState; // 413 - end - -always @(CState or SIN or iFSIN or iFStopBit or iBaudStep or iBaudCount or iDataCountFinish or PEN or WLS or STB) -begin -NState <= IDLE; // 413 -iBaudCountClear <= 1'b0; // 413 -iDataCountInit <= 1'b0; // 413 -iRXFinished <= 1'b0; // 413 -case (CState) - IDLE: - begin - if ((SIN == 1'b0)) - begin - NState <= START; // 413 - end - -iBaudCountClear <= 1'b1; // 413 - iDataCountInit <= 1'b1; // 413 - end - - START: - begin - iDataCountInit <= 1'b1; // 413 - if ((iBaudStep == 1'b1)) - begin - if ((iFSIN == 1'b0)) - begin - NState <= DATA; // 413 - end - - end - else - begin - NState <= START; // 413 - end - end - - DATA: - begin - if ((iDataCountFinish == 1'b1)) - begin - if ((PEN == 1'b1)) - begin - NState <= PAR; // 413 - end - else - begin - NState <= STOP; // 413 - end - end - else - begin - NState <= DATA; // 413 - end - end - - PAR: - begin - if ((iBaudStep == 1'b1)) - begin - NState <= STOP; // 413 - end - else - begin - NState <= PAR; // 413 - end - end - - STOP: - begin - if ((iBaudCount[3] == 1'b1)) - begin - if ((iFStopBit == 1'b0)) - begin - iRXFinished <= 1'b1; // 413 - NState <= MWAIT; // 413 - end - else - begin - iRXFinished <= 1'b1; // 413 - NState <= IDLE; // 413 - end - end - else - begin - NState <= STOP; // 413 - end - end - - MWAIT: - begin - if ((SIN == 1'b0)) - begin - NState <= MWAIT; // 413 - end - - end - - default: - begin - begin end end - -endcase - -end - - -always @(posedge CLK or posedge RST) -begin -if ((RST == 1'b1)) - begin - PE <= 1'b0; // 413 - iParityReceived <= 1'b0; // 413 - end - else - begin - if ((CState == PAR && iBaudStep == 1'b1)) - begin - iParityReceived <= iFSIN; // 413 - end - -if ((PEN == 1'b1)) - begin - PE <= 1'b0; // 413 - if ((SP == 1'b1)) - begin - if (((EPS ^ iParityReceived) == 1'b0)) - begin - PE <= 1'b1; // 413 - end - - end - else - begin - if ((iParity != iParityReceived)) - begin - PE <= 1'b1; // 413 - end - - end - end - else - begin - PE <= 1'b0; // 413 - iParityReceived <= 1'b0; // 413 - end - end - -end - -assign /*903*/ iNoStopReceived = iFStopBit == 1'b0 && (CState == STOP) ? 1'b1 : 1'b0; // 905 -assign /*903*/ iBI = (iDOUT == 8'b00000000 && iParityReceived == 1'b0) && iNoStopReceived == 1'b1 ? 1'b1 : 1'b0; // 905 -assign /*903*/ iFE = iNoStopReceived == 1'b1 ? 1'b1 : 1'b0; // 905 -assign /*432*/ DOUT = iDOUT; // 434 -assign /*432*/ BI = iBI; // 434 -assign /*432*/ FE = iFE; // 434 -assign /*432*/ RXFINISHED = iRXFinished; // 434 -endmodule diff --git a/rtl/apb_uart/uart_transmitter.sv b/rtl/apb_uart/uart_transmitter.sv deleted file mode 100644 index 8d57a6b7..00000000 --- a/rtl/apb_uart/uart_transmitter.sv +++ /dev/null @@ -1,320 +0,0 @@ -// -// UART 16750 -// -// Converted to System Verilog by Jonathan Kimmitt -// This version has been partially checked with formality but some bugs remain -// Original Author: Sebastian Witt -// Date: 14.03.2019 -// Version: 1.6 -// -// History: 1.0 - Initial version -// 1.1 - THR empty interrupt register connected to RST -// 1.2 - Registered outputs -// 1.3 - Automatic flow control -// 1.4 - De-assert IIR FIFO64 when FIFO is disabled -// 1.5 - Inverted low active outputs when RST is active -// 1.6 - Converted to System Verilog -// -// -// This code 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 code 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 library; if not, write to the -// Free Software Foundation, Inc., 59 Temple Place, Suite 330, -// Boston, MA 02111-1307 USA -// - -module uart_transmitter( - input wire CLK, - input wire RST, - input wire TXCLK, - input wire TXSTART, - input wire CLEAR, - input wire [1:0] WLS, - input wire STB, - input wire PEN, - input wire EPS, - input wire SP, - input wire BC, - input wire [7:0] DIN, - output logic TXFINISHED, - output logic SOUT); // 507 -/* design uart_transmitter */ -/* architecture rtl */ -typedef enum {FALSE,TRUE} bool_t; // 527 -typedef enum logic [3:0] {IDLE, -START, -BIT0, -BIT1, -BIT2, -BIT3, -BIT4, -BIT5, -BIT6, -BIT7, -PAR, -STOP, -STOP2} state_type; // 674 -state_type CState, NState; // 908 -reg iTx2; // 612 -reg iSout; // 612 -reg iParity; // 612 -reg iFinished; // 612 - -always @(posedge CLK or posedge RST) - if ((RST == 1'b1)) - begin - CState <= IDLE; // 413 - iTx2 <= 1'b0; // 413 - end - else - begin - if ((TXCLK == 1'b1)) - begin - if ((iTx2 == 1'b0)) - begin - CState <= NState; // 413 - iTx2 <= 1'b1; // 413 - end - else - begin - if ((((WLS == 2'b00) && (STB == 1'b1)) && CState == STOP2)) - begin - CState <= NState; // 413 - iTx2 <= 1'b1; // 413 - end - else - begin - CState <= CState; // 413 - iTx2 <= 1'b0; // 413 - end - end - end - end - -always @(CState or TXSTART or DIN or WLS or PEN or SP or EPS or STB or iParity) - begin - NState <= IDLE; // 413 - iSout <= 1'b1; // 413 - case (CState) - IDLE: - begin - if ((TXSTART == 1'b1)) - begin - NState <= START; // 413 - end - - end - - START: - begin - iSout <= 1'b0; // 413 - NState <= BIT0; // 413 - end - - BIT0: - begin - iSout <= DIN[0]; // 413 - NState <= BIT1; // 413 - end - - BIT1: - begin - iSout <= DIN[1]; // 413 - NState <= BIT2; // 413 - end - - BIT2: - begin - iSout <= DIN[2]; // 413 - NState <= BIT3; // 413 - end - - BIT3: - begin - iSout <= DIN[3]; // 413 - NState <= BIT4; // 413 - end - - BIT4: - begin - iSout <= DIN[4]; // 413 - if ((WLS == 2'b00)) - begin - if ((PEN == 1'b1)) - begin - NState <= PAR; // 413 - end - else - begin - NState <= STOP; // 413 - end - end - else - begin - NState <= BIT5; // 413 - end - end - - BIT5: - begin - iSout <= DIN[5]; // 413 - if ((WLS == 2'b01)) - begin - if ((PEN == 1'b1)) - begin - NState <= PAR; // 413 - end - else - begin - NState <= STOP; // 413 - end - end - else - begin - NState <= BIT6; // 413 - end - end - - BIT6: - begin - iSout <= DIN[6]; // 413 - if ((WLS == 2'b10)) - begin - if ((PEN == 1'b1)) - begin - NState <= PAR; // 413 - end - else - begin - NState <= STOP; // 413 - end - end - else - begin - NState <= BIT7; // 413 - end - end - - BIT7: - begin - iSout <= DIN[7]; // 413 - if ((PEN == 1'b1)) - begin - NState <= PAR; // 413 - end - else - begin - NState <= STOP; // 413 - end - end - - PAR: - begin - if ((SP == 1'b1)) - begin - if ((EPS == 1'b1)) - begin - iSout <= 1'b0; // 413 - end - else - begin - iSout <= 1'b1; // 413 - end - end - else - begin - if ((EPS == 1'b1)) - begin - iSout <= iParity; // 413 - end - else - begin - iSout <= ~ iParity; // 413 - end - end - NState <= STOP; // 413 - end - - STOP: - begin - if ((STB == 1'b1)) - begin - NState <= STOP2; // 413 - end - else - begin - if ((TXSTART == 1'b1)) - begin - NState <= START; // 413 - end - - end - end - - STOP2: - begin - if ((TXSTART == 1'b1)) - begin - NState <= START; // 413 - end - - end - - default: - begin - begin end end - - endcase - - end - - // Parity generation - always @ (DIN or WLS) - begin:TX_PAR - logic iP40, iP50, iP60, iP70; - iP40 = DIN[4] ^ DIN[3] ^ DIN[2] ^ DIN[1] ^ DIN[0]; - iP50 = DIN[5] ^ iP40; - iP60 = DIN[6] ^ iP50; - iP70 = DIN[7] ^ iP60; - - case(WLS) - 2'b00: iParity <= iP40; - 2'b01: iParity <= iP50; - 2'b10: iParity <= iP60; - default: iParity <= iP70; - endcase; - end - - reg iLast; - always @(posedge CLK or posedge RST) - begin:TX_FIN - if (RST) - begin - iFinished <= 1'b0; - iLast <= 1'b0; - end - else - begin - iFinished <= 1'b0; - if (iLast == 1'b0 && CState == STOP) - iFinished <= 1'b1; - if (CState == STOP) - iLast <= 1'b1; - else - iLast <= 1'b0; - end - end - -assign /*903*/ SOUT = BC == 1'b0 ? iSout : 1'b0; // 905 -assign /*432*/ TXFINISHED = iFinished; // 434 - -endmodule // uart_transmitter diff --git a/rtl/croc_domain.sv b/rtl/croc_domain.sv index 91fa956b..18c15947 100644 --- a/rtl/croc_domain.sv +++ b/rtl/croc_domain.sv @@ -521,59 +521,32 @@ module croc_domain import croc_pkg::*; #( ); // UART - reg_req_t uart_reg_req; - reg_rsp_t uart_reg_rsp; - - periph_to_reg #( - .AW ( SbrObiCfg.AddrWidth ), - .DW ( SbrObiCfg.DataWidth ), - .BW ( 8 ), - .IW ( SbrObiCfg.IdWidth ), - .req_t ( reg_req_t ), - .rsp_t ( reg_rsp_t ) - ) i_uart_translate ( - .clk_i, - .rst_ni, - - .req_i ( uart_obi_req.req ), - .add_i ( uart_obi_req.a.addr ), - .wen_i ( ~uart_obi_req.a.we ), - .wdata_i ( uart_obi_req.a.wdata ), - .be_i ( uart_obi_req.a.be ), - .id_i ( uart_obi_req.a.aid ), - - .gnt_o ( uart_obi_rsp.gnt ), - .r_rdata_o ( uart_obi_rsp.r.rdata ), - .r_opc_o ( uart_obi_rsp.r.err ), - .r_id_o ( uart_obi_rsp.r.rid ), - .r_valid_o ( uart_obi_rsp.rvalid ), - - .reg_req_o ( uart_reg_req ), - .reg_rsp_i ( uart_reg_rsp ) - ); - - reg_uart_wrap #( - .AddrWidth ( 32 ), - .reg_req_t ( reg_req_t ), - .reg_rsp_t ( reg_rsp_t ) + obi_uart #( + .ObiCfg ( SbrObiCfg ), + .obi_req_t ( sbr_obi_req_t ), + .obi_rsp_t ( sbr_obi_rsp_t ) ) i_uart ( .clk_i, .rst_ni, - .reg_req_i ( uart_reg_req ), - .reg_rsp_o ( uart_reg_rsp ), - .intr_o ( uart_irq ), - .out2_no ( ), - .out1_no ( ), - .rts_no ( ), - .dtr_no ( ), - .cts_ni ( 1'b0 ), - .dsr_ni ( 1'b0 ), - .dcd_ni ( 1'b0 ), - .rin_ni ( 1'b0 ), - .sin_i ( uart_rx_i ), - .sout_o ( uart_tx_o ) - ); - assign uart_obi_rsp.r.r_optional = '0; + + .obi_req_i ( uart_obi_req ), + .obi_rsp_o ( uart_obi_rsp ), + .irq_o ( uart_irq ), + .irq_no ( ), + + .rxd_i ( uart_rx_i ), + .txd_o ( uart_tx_o ), + + // Modem control pins are optional + .cts_ni ( 1'b1 ), + .dsr_ni ( 1'b1 ), + .ri_ni ( 1'b1 ), + .cd_ni ( 1'b1 ), + .rts_no ( ), + .dtr_no ( ), + .out1_no ( ), + .out2_no ( ) +); // GPIO gpio #( diff --git a/rtl/obi_uart/Bender.yml b/rtl/obi_uart/Bender.yml new file mode 100644 index 00000000..e49903df --- /dev/null +++ b/rtl/obi_uart/Bender.yml @@ -0,0 +1,24 @@ +# Copyright 2025 ETH Zurich and University of Bologna. +# Solderpad Hardware License, Version 0.51, see LICENSE for details. +# SPDX-License-Identifier: SHL-0.51 + +package: + name: obi_peripherals + authors: + - "Philippe Sauter " + - "Hannah Pochert " + +dependencies: + common_cells: { git: "https://github.com/pulp-platform/common_cells.git", version: 1.37.0 } + obi: { git: "https://github.com/pulp-platform/obi.git", version: 0.1.3 } + +sources: + # obi_uart + - obi_uart_pkg.sv + - obi_uart_baudgen.sv + - obi_uart_interrupts.sv + - obi_uart_modem.sv + - obi_uart_rx.sv + - obi_uart_tx.sv + - obi_uart_register.sv + - obi_uart.sv diff --git a/rtl/obi_uart/obi_uart.sv b/rtl/obi_uart/obi_uart.sv new file mode 100644 index 00000000..8696f47e --- /dev/null +++ b/rtl/obi_uart/obi_uart.sv @@ -0,0 +1,182 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Authors: +// - Hannah Pochert +// - Philippe Sauter + +`include "common_cells/registers.svh" + +module obi_uart #( + /// The OBI configuration connected to this peripheral. + parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig, // SbrObiCfg + /// OBI request type + parameter type obi_req_t = logic, + /// OBI response type + parameter type obi_rsp_t = logic +) ( + input logic clk_i, // Primary input clock + input logic rst_ni, // Asynchronous active-low reset + + // OBI request interface + input obi_req_t obi_req_i, // a.addr, a.we, a.be, a.wdata, a.aid, a.a_optional | rready, req + // OBI response interface + output obi_rsp_t obi_rsp_o, // r.rdata, r.rid, r.err, r.r_optional | gnt, rvalid + + output logic irq_o, // Interrupt line + output logic irq_no, // Negated Interrupt line + + input logic rxd_i, // Serial Input + output logic txd_o, // Serial Output + + // Modem control pins are optional + input logic cts_ni, // Modem Inp Clear To Send + input logic dsr_ni, // Modem Inp Data Send Request + input logic ri_ni, // Modem Inp Ring Indicator + input logic cd_ni, // Modem Inp Carrier Detect + output logic rts_no, // Modem Oup Ready To Send + output logic dtr_no, // Modem Oup DaTa Ready + output logic out1_no, // Modem Oup DaTa Ready, optional outputs + output logic out2_no // Modem Oup DaTa Ready, optional outputs +); + // Import the UART package for definitions and parameters + import obi_uart_pkg::*; + + //--Receiver-and-Transmitter-Interface---------------------------------------------------------- + logic rxd; + logic txd; + + //--Receiver-Interrupt-Interface---------------------------------------------------------------- + logic rx_fifo_trigger; + logic rx_timeout; + + //--Register-Interface-Signals------------------------------------------------------------------ + reg_read_t reg_read; // signals read from the registers + reg_write_t reg_write; // new values being written to registers + + //--Baudenable-Interface-Signals---------------------------------------------------------------- + logic oversample_rate_edge; + logic double_rate_edge; + logic baud_rate_edge; + + //////////////////////////////////////////////////////////////////////////////////////////////// + // REGISTER INTERFACE // + //////////////////////////////////////////////////////////////////////////////////////////////// + + obi_uart_register #( + .obi_req_t (obi_req_t), + .obi_rsp_t (obi_rsp_t) + ) i_uart_register ( + .clk_i, + .rst_ni, + + .obi_req_i, + .obi_rsp_o, + + .reg_read_o (reg_read), + .reg_write_i (reg_write) + ); + + //////////////////////////////////////////////////////////////////////////////////////////////// + // MODEM CONTROL // + //////////////////////////////////////////////////////////////////////////////////////////////// + + obi_uart_modem #( + ) i_uart_modem ( + .clk_i, + .rst_ni, + + .cts_ni, + .dsr_ni, + .ri_ni, + .cd_ni, + .rts_no, + .dtr_no, + .out1_no, + .out2_no, + + .reg_read_i (reg_read), + .reg_write_o (reg_write.modem) + ); + + //--Loopback-Mode------------------------------------------------------------------------------- + assign txd_o = (reg_read.mcr.loopback == 1'b1) ? 1'b1 : txd; + assign rxd = (reg_read.mcr.loopback == 1'b1) ? txd : rxd_i; + + //////////////////////////////////////////////////////////////////////////////////////////////// + // BAUDRATE GENERATION // + //////////////////////////////////////////////////////////////////////////////////////////////// + + obi_uart_baudgen #( + ) i_uart_baudgen ( + .clk_i, + .rst_ni, + + .oversample_rate_edge_o(oversample_rate_edge), + .double_rate_edge_o (double_rate_edge), + .baud_rate_edge_o (baud_rate_edge), + + .reg_read_i (reg_read) + ); + + //////////////////////////////////////////////////////////////////////////////////////////////// + // RECEIVE // + //////////////////////////////////////////////////////////////////////////////////////////////// + + obi_uart_rx # ( + ) i_uart_rx ( + .clk_i, + .rst_ni, + + .oversample_rate_edge_i (oversample_rate_edge), + .baud_rate_edge_i (baud_rate_edge), + + .rxd_i (rxd), + + .trigger_o (rx_fifo_trigger), + .timeout_o (rx_timeout), + + .reg_read_i (reg_read), + .reg_write_o (reg_write.rx) + ); + + //////////////////////////////////////////////////////////////////////////////////////////////// + // TRANSMIT // + //////////////////////////////////////////////////////////////////////////////////////////////// + + obi_uart_tx # ( + ) i_uart_tx ( + .clk_i, + .rst_ni, + + .baud_rate_edge_i (baud_rate_edge), + .double_rate_edge_i (double_rate_edge), + + .txd_o (txd), + + .reg_read_i (reg_read), + .reg_write_o (reg_write.tx) + ); + + //////////////////////////////////////////////////////////////////////////////////////////////// + // INTERRUPT CONTROL // + //////////////////////////////////////////////////////////////////////////////////////////////// + + obi_uart_interrupts #( + ) i_uart_interrupts ( + .clk_i, + .rst_ni, + + .rx_fifo_trigger, + .rx_timeout, + + .irq_o, + .irq_no, + + .reg_read_i (reg_read), + .reg_write_i (reg_write), + .reg_isr_o (reg_write.isr) + ); + +endmodule diff --git a/rtl/obi_uart/obi_uart_baudgen.sv b/rtl/obi_uart/obi_uart_baudgen.sv new file mode 100644 index 00000000..89a74dd6 --- /dev/null +++ b/rtl/obi_uart/obi_uart_baudgen.sv @@ -0,0 +1,114 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Authors: +// - Hannah Pochert +// - Philippe Sauter + +`include "common_cells/registers.svh" + +/// Generates clock enable signals for the required baud multiples +module obi_uart_baudgen import obi_uart_pkg::*; #() +( + input logic clk_i, + input logic rst_ni, + + output logic oversample_rate_edge_o, // oversample clock enable signal + output logic double_rate_edge_o, // doubled baud clock enable signal + output logic baud_rate_edge_o, // baud clock enable signal + + input reg_read_t reg_read_i +); + + // Import the UART package for definitions and parameters + + //-- Configuration Signals --------------------------------------------------------------------- + logic [15:0] divisor; + logic divisor_valid; + + //-- Oversample Signals ------------------------------------------------------------------------ + logic oversample_is_divisor; + logic oversample_clear; + logic [15:0] oversample_count; + + //-- Double Baud Signals ----------------------------------------------------------------------- + logic clear_double_d, clear_double_q; + logic count_is_double; + + //-- Baud Signals ------------------------------------------------------------------------------ + logic baud_clear; + logic [3:0] baud_count; + logic baud_count_overflow; + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Clock Division // + //////////////////////////////////////////////////////////////////////////////////////////////// + + //---------------------------------------------------------------------------------------------- + // Oversample 16x + //---------------------------------------------------------------------------------------------- + + // Concatenate most significant byte and least significant byte of Divisor + // -1 since we clear to zero when reaching divisor, takes one cycle + assign divisor = {reg_read_i.dlm, reg_read_i.dll} - 16'd1; + // divisor reset value is 0 and per the 16550A formula it has no meaning -> invalid + assign divisor_valid = ~(divisor == 0); + assign oversample_is_divisor = (oversample_count == divisor) & divisor_valid; + // clear on reaching the divisor or when configuration changes + assign oversample_clear = oversample_is_divisor | reg_read_i.obi_write_dllm; + + counter #( + .WIDTH (16), + .STICKY_OVERFLOW (0) + ) i_oversample_counter ( + .clk_i, + .rst_ni, + .clear_i ( oversample_clear ), // Synchronous clear: Sets Counter 0 in the next cycle + .en_i ( divisor_valid ), // Count only if configuration is high + .load_i ( 1'b0 ), + .down_i ( 1'b0 ), // Count upwards + .d_i ( '0 ), + .q_o ( oversample_count ), + .overflow_o( ) // Set when counter overflows from '1 to '0 + ); + + // high for one clock cycle + assign oversample_rate_edge_o = (oversample_count == '0) & divisor_valid; + + //---------------------------------------------------------------------------------------------- + // Baudrate + //---------------------------------------------------------------------------------------------- + // Counts when oversample hits target, counter has the new value in the next cycle + // the same cycle when oversample_rate_edge_o goes high + + assign baud_clear = baud_count_overflow | reg_read_i.obi_write_dllm; + + counter #( + .WIDTH (4), + .STICKY_OVERFLOW(0) + ) i_baudrate_counter ( + .clk_i, + .rst_ni, + .clear_i ( baud_clear ), // Synchronous clear: Sets Counter 0 in the next cycle + .en_i ( oversample_is_divisor ), // Count every time oversample counter hits its target + .load_i ( 1'b0 ), + .down_i ( 1'b0 ), // Count upwards + .d_i ( '0 ), + .q_o ( baud_count ), + .overflow_o( baud_count_overflow ) + ); + + // oversample hits target, counter overflows on the next clock cycle and then clears itself + // therefore baud_rate_edge_o is high in the same cycle as oversample_rate_edge_o + assign baud_rate_edge_o = baud_count_overflow; + + // Double baud rate directly generated from baudrate counter + assign count_is_double = (baud_count[2:0] == '0); // last three bits zero + // clear_double turns the pulse off after one clock cycle + assign clear_double_d = count_is_double; + assign double_rate_edge_o = count_is_double & ~clear_double_q; + + `FF(clear_double_q, clear_double_d, '0, clk_i, rst_ni) + +endmodule diff --git a/rtl/obi_uart/obi_uart_interrupts.sv b/rtl/obi_uart/obi_uart_interrupts.sv new file mode 100644 index 00000000..9f3b4bba --- /dev/null +++ b/rtl/obi_uart/obi_uart_interrupts.sv @@ -0,0 +1,135 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Authors: +// - Hannah Pochert +// - Philippe Sauter + +`include "common_cells/registers.svh" + +/// Calculated interrupts and stores them until reset by hardware or by reading the ISR register +module obi_uart_interrupts import obi_uart_pkg::*; #() +( + input logic clk_i, + input logic rst_ni, + + input logic rx_fifo_trigger, + input logic rx_timeout, + + output logic irq_o, + output logic irq_no, + + input reg_read_t reg_read_i, + input reg_write_t reg_write_i, + output isr_bits_t reg_isr_o +); + + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Instantiations // + //////////////////////////////////////////////////////////////////////////////////////////////// + //--Interrupt-Control-Signals------------------------------------------------------------------- + typedef struct packed { + logic rls; // Receive Line Status Interrupt - Error notification + logic rxdr; // Receiver Data Ready + logic timeout; // Reception Timeout + logic thr_empty; // THR Empty Interrupt - Data can't be written + logic mstat; // Modem Status Interrupt - Changes in Modem Line + } reg_intrpt_t; + + reg_intrpt_t intrpt_reg_d, intrpt_reg_q; + + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Generare Interrupt Signals // + //////////////////////////////////////////////////////////////////////////////////////////////// + always_comb begin + //--Receive-Line-Status-Interrupt------------------------------------------------------------- + intrpt_reg_d.rls = reg_read_i.ier.rlstat & (reg_write_i.rx.overrun | reg_write_i.rx.par_err | + reg_write_i.rx.frame_err | reg_write_i.rx.break_ind); + + //--Receive-Data-Ready-Interrupt-------------------------------------------------------------- + if (reg_read_i.fcr.fifo_en) begin + intrpt_reg_d.rxdr = reg_read_i.ier.dtr & rx_fifo_trigger; // data ready in FIFO mode + end else begin + intrpt_reg_d.rxdr = reg_read_i.ier.dtr & reg_write_i.rx.data_ready; // in THR mode + end + + //--Character-Timeout-Interrupt--------------------------------------------------------------- + intrpt_reg_d.timeout = reg_read_i.fcr.fifo_en & reg_read_i.ier.dtr & rx_timeout; + + //--THR-Empty-Interrupt----------------------------------------------------------------------- + intrpt_reg_d.thr_empty = reg_read_i.ier.thr_empty & reg_write_i.tx.thr_empty; + + //--Modem-Status-Interrupt-------------------------------------------------------------------- + intrpt_reg_d.mstat = reg_read_i.ier.mstat & (reg_write_i.modem.d_cts | + reg_write_i.modem.d_dsr | reg_write_i.modem.te_ri | reg_write_i.modem.d_cd); + + ////////////////////////////////////////////////////////////////////////////////////////////// + // Interrupt Reset Condition // + ////////////////////////////////////////////////////////////////////////////////////////////// + if(reg_read_i.obi_read_lsr) begin + intrpt_reg_d.rls = 1'b0; + end + + if(reg_read_i.obi_read_rhr) begin + intrpt_reg_d.timeout = 1'b0; + if(~reg_read_i.fcr.fifo_en) begin + intrpt_reg_d.rxdr = 1'b0; + end + end + + if(reg_read_i.obi_write_thr) begin + intrpt_reg_d.thr_empty = 1'b0; + end + + if (reg_read_i.obi_read_msr) begin + intrpt_reg_d.mstat = 1'b0; + end + end + + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Setting ID & Status Bits // + //////////////////////////////////////////////////////////////////////////////////////////////// + always_comb begin + //--Defaults---------------------------------------------------------------------------------- + reg_isr_o.id = 3'b000; + reg_isr_o.fifos_en = 2'b11; // Indicate 16550A FIFO support + reg_isr_o.unused4 = 1'b0; + reg_isr_o.unused5 = 1'b0; + + reg_isr_o.status = ~( |intrpt_reg_q ); // 0: interrupt present; 1: no interrupt + + //--Priority-Encoder-------------------------------------------------------------------------- + // 1. Priority Level + if (intrpt_reg_q.rls) begin + reg_isr_o.id = 3'b011; + // 2. Priority Level + end else if (intrpt_reg_q.rxdr) begin + reg_isr_o.id = 3'b010; + // 2. Priority Level + end else if (intrpt_reg_q.timeout) begin + reg_isr_o.id = 3'b110; + // 3. Priority Level + end else if (intrpt_reg_q.thr_empty) begin + reg_isr_o.id = 3'b001; + // 4. Priority Level + end else if (intrpt_reg_q.mstat) begin + reg_isr_o.id = 3'b000; + end + + end + + ////////////////////////////////////////////////////////////////////////////////////////////// + // Direct Output Interrupt - Alert the CPU // + ////////////////////////////////////////////////////////////////////////////////////////////// + + // Once high stays high until interrupt condition is removed + assign irq_o = ~reg_isr_o.status; + assign irq_no = reg_isr_o.status; + + `FF(intrpt_reg_q, intrpt_reg_d, '0, clk_i, rst_ni) + +endmodule diff --git a/rtl/obi_uart/obi_uart_modem.sv b/rtl/obi_uart/obi_uart_modem.sv new file mode 100644 index 00000000..a85dd98f --- /dev/null +++ b/rtl/obi_uart/obi_uart_modem.sv @@ -0,0 +1,132 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Authors: +// - Hannah Pochert +// - Philippe Sauter + +`include "common_cells/registers.svh" + +/// Synchronizes incoming modem signals, outputs modem signals and handles loopback +module obi_uart_modem import obi_uart_pkg::*; #() +( + input logic clk_i, + input logic rst_ni, + + input logic cts_ni, // Modem Inp Clear To Send + input logic dsr_ni, // Modem Inp Data Send Request + input logic ri_ni, // Modem Inp Ring Indicator + input logic cd_ni, // Modem Inp Carrier Detect + output logic rts_no, // Modem Oup Ready To Send + output logic dtr_no, // Modem Oup DaTa Ready + output logic out1_no, // Modem Output 1 + output logic out2_no, // Modem Output 2 + + input reg_read_t reg_read_i, + output msr_bits_t reg_write_o +); + // Flow control is left to SW. UART Modem Control only writes modem inputs to + // register and sets modem outputs from the register. + + // Modem inputs and outputs are active low. Values seen in the signals are the opposite of + // the ones read from or written to the modem status/control registers ! + + //--Modem-Control-Signals----------------------------------------------------------------------- + logic sync_cts_n, sync_cts_n_d, sync_cts_n_q; + logic sync_dsr_n, sync_dsr_n_d, sync_dsr_n_q; + logic sync_ri_n, sync_ri_n_d, sync_ri_n_q; + logic sync_cd_n, sync_cd_n_d, sync_cd_n_q; + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Modem Input Synchronisation // + //////////////////////////////////////////////////////////////////////////////////////////////// + + sync #( + .STAGES (NrSyncStages) + ) i_sync_cts ( + .clk_i, + .rst_ni, + .serial_i(cts_ni), + .serial_o(sync_cts_n) + + ); + sync #( + .STAGES (NrSyncStages) + ) i_sync_dsr ( + .clk_i, + .rst_ni, + .serial_i(dsr_ni), + .serial_o(sync_dsr_n) + ); + + sync #( + .STAGES (NrSyncStages) + ) i_sync_ri ( + .clk_i, + .rst_ni, + .serial_i(ri_ni), + .serial_o(sync_ri_n) + ); + + sync #( + .STAGES (NrSyncStages) + ) i_sync_cd ( + .clk_i, + .rst_ni, + .serial_i(cd_ni), + .serial_o(sync_cd_n) + ); + + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Modem Input/Output and Loopback // + //////////////////////////////////////////////////////////////////////////////////////////////// + + always_comb begin + if(reg_read_i.mcr.loopback == 1'b1) begin + rts_no = 1'b1; + dtr_no = 1'b1; + out1_no = 1'b1; + out2_no = 1'b1; + + sync_cts_n_d = ~reg_read_i.mcr.rts; + sync_dsr_n_d = ~reg_read_i.mcr.dtr; + sync_ri_n_d = ~reg_read_i.mcr.out1; + sync_cd_n_d = ~reg_read_i.mcr.out2; + end else begin + rts_no = ~reg_read_i.mcr.rts; + dtr_no = ~reg_read_i.mcr.dtr; + out1_no = ~reg_read_i.mcr.out1; + out2_no = ~reg_read_i.mcr.out2; + + sync_cts_n_d = sync_cts_n; + sync_dsr_n_d = sync_dsr_n; + sync_ri_n_d = sync_ri_n; + sync_cd_n_d = sync_cd_n; + end + end + + `FF(sync_cts_n_q, sync_cts_n_d, '1, clk_i, rst_ni) + `FF(sync_dsr_n_q, sync_dsr_n_d, '1, clk_i, rst_ni) + `FF(sync_ri_n_q, sync_ri_n_d, '1, clk_i, rst_ni) + `FF(sync_cd_n_q, sync_cd_n_d, '1, clk_i, rst_ni) + + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Modem to MSR // + //////////////////////////////////////////////////////////////////////////////////////////////// + + // Modem Inputs are negated + assign reg_write_o.cts = ~sync_cts_n_d; + assign reg_write_o.dsr = ~sync_dsr_n_d; + assign reg_write_o.ri = ~sync_ri_n_d; + assign reg_write_o.cd = ~sync_cd_n_d; + + // Change status bits + assign reg_write_o.d_cts = sync_cts_n_d ^ sync_cts_n_q; // Delta: 1 if _d different from _q + assign reg_write_o.d_dsr = sync_dsr_n_d ^ sync_dsr_n_q; // Delta: 1 if _d different from _q + assign reg_write_o.te_ri = sync_ri_n_d & ~sync_ri_n_q; // Trailing Edge: 1 on negedge + assign reg_write_o.d_cd = sync_cd_n_d ^ sync_cd_n_q; // Delta: 1 if _d different from _q + +endmodule diff --git a/rtl/obi_uart/obi_uart_pkg.sv b/rtl/obi_uart/obi_uart_pkg.sv new file mode 100644 index 00000000..c2f89bc2 --- /dev/null +++ b/rtl/obi_uart/obi_uart_pkg.sv @@ -0,0 +1,269 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Authors: +// - Hannah Pochert +// - Philippe Sauter + +package obi_uart_pkg; + + //-- Configurable values ----------------------------------------------------------------------- + localparam int RegAlignBytes = 4; // regs aligned to this many bytes (4 -> 32-bit aligned) + + // Number of input synchronization stages + localparam int NrSyncStages = 2; + + //////////////////////////////////////////////////////////////////////////////////////////////// + // RX and TX Statemachine typedefs // + //////////////////////////////////////////////////////////////////////////////////////////////// + + // RX FSM states + typedef enum bit [2:0] { + RXIDLE, + RXSTART, + RXDATA, + RXPAR, + RXSTOP, + RXRESYNCHRONIZE + } state_type_rx_e; + + // TX FSM states + typedef enum bit [2:0] { + TXIDLE, + TXSTART, + TXDATA, + TXPAR, + TXSTOP1, + TXSTOP2, + TXWAIT + } state_type_tx_e; + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Address Offsets // + //////////////////////////////////////////////////////////////////////////////////////////////// + localparam int RegWidth = 8; + // Address widths used for decoding + localparam int AddressBits = 3; + localparam int AddressOffset = $clog2(RegAlignBytes); + + // Register Address Offsets + localparam bit [AddressBits-1:0] RegAddrRHR = 3'b000; + localparam bit [AddressBits-1:0] RegAddrTHR = 3'b000; + localparam bit [AddressBits-1:0] RegAddrIER = 3'b001; + localparam bit [AddressBits-1:0] RegAddrISR = 3'b010; + localparam bit [AddressBits-1:0] RegAddrFCR = 3'b010; + localparam bit [AddressBits-1:0] RegAddrLCR = 3'b011; + localparam bit [AddressBits-1:0] RegAddrMCR = 3'b100; + localparam bit [AddressBits-1:0] RegAddrLSR = 3'b101; + localparam bit [AddressBits-1:0] RegAddrMSR = 3'b110; + localparam bit [AddressBits-1:0] RegAddrSPR = 3'b111; + localparam bit [AddressBits-1:0] RegAddrDLL = 3'b000; + localparam bit [AddressBits-1:0] RegAddrDLM = 3'b001; + //localparam bit [AddressBits-1:0] RegAddrPSD = 3'b101; + + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Single Register Unions for Register Interface// + //////////////////////////////////////////////////////////////////////////////////////////////// + + //---------------------------------------------------------------------------------------------- + // Single Register Structs with Bit Definitions + //---------------------------------------------------------------------------------------------- + + typedef struct packed { + logic [7:0] char_rx; // Character received + } rhr_bits_t; + + typedef struct packed { + logic [7:0] char_tx; // Character transmitted + } thr_bits_t; + + typedef struct packed { + logic unused7; // Optional: DMA + logic unused6; // Optional: DMA + logic unused5; // 0 + logic unused4; // 0 + logic mstat; // Modem Status + logic rlstat; // Receive Line Status + logic thr_empty; // THR Empty + logic dtr; // Data Ready or Reception Timeout + } ier_bits_t; + + typedef struct packed { + logic [1:0] fifos_en; // Standard: 2'b00: 8250; 2'b01: 16550; 2'b10: 16750; 2'b11: 16550A + logic unused5; // Optional: DMA + logic unused4; // Optional: DMA + logic [2:0] id; // Intrpt Code ID + logic status; // Intrpt Status + } isr_bits_t; + + typedef struct packed { + logic [1:0] rx_fifo_tl; // Rx FIFO Trigger Level + logic unused5; // 0 + logic unused4; // Optional: DMA + logic unused3; // Optional: DMA + logic tx_fifo_rst; // Tx FIFO reset + logic rx_fifo_rst; // Rx FIFO reset + logic fifo_en; // FIFO Enable + } fcr_bits_t; + + typedef struct packed { + logic dlab; // DLAB Address multiplexing + logic set_break; // Set Break + logic force_par; // Force Parity + logic even_par; // Even Parity + logic par_en; // Parity Enable + logic stop_bits; // Stop Bits + logic [1:0] word_len; // Word Length 2'b00: 5 | 2'b01: 6 | 2'b10: 7 | 2'b11: 8 + } lcr_bits_t; + + typedef struct packed { + logic unused7; // 0 + logic unused6; // 0 + logic unused5; // 0 + logic loopback; // Loop Back + logic out2; // Optional: Gpio Output + logic out1; // Optional: Gpio Output + logic rts; // Request to Send + logic dtr; // DaTa Ready + } mcr_bits_t; + + typedef struct packed { + logic fifo_err; // FIFO Data Error + logic tx_empty; // Transmitter Empty (no bits to send) + logic thr_empty; // THR (and FIFO) Empty + logic break_ind; // Break Indicator + logic frame_err; // Framing Error + logic par_err; // Parity Error + logic overrun; // Overrun Error + logic data_ready; // Data Ready + } lsr_bits_t; + + typedef struct packed { + logic cd; // Carrier Detect + logic ri; // Ring Indicator + logic dsr; // Data Set Ready + logic cts; // Clear to Send + logic d_cd; // Delta CD: Indicates change + logic te_ri; // Trailing Edge RI: Detects trailing Edge (Transition high to low) + logic d_dsr; // Delta + logic d_cts; // Delta Clear to Send + } msr_bits_t; + + typedef struct packed { + logic [7:0] lsb; // Baudrate's Divisor Constant LSByte + } dll_bits_t; + + typedef struct packed { + logic [7:0] msb; // Baudrate's Divisor Constant MSByte + } dlm_bits_t; + + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Registers // + //////////////////////////////////////////////////////////////////////////////////////////////// + + typedef struct packed { + rhr_bits_t RHR; // Read Hold Register + thr_bits_t THR; // Transmit Hold Register + ier_bits_t IER; // Interrupt Enable Register + //isr_bits_t ISR; // Interrupt Status Register, stored seperately in interrupts module + fcr_bits_t FCR; // Fifo Control Register + lcr_bits_t LCR; // Line Control Register + mcr_bits_t MCR; // Modem Control Register + lsr_bits_t LSR; // Line Status Register + msr_bits_t MSR; // Modem Status Register + //logic [7:0] SPR; // Scratch Pad Register, Not Implemented + dll_bits_t DLL; // Divisor Latch Least signf. byte + dlm_bits_t DLM; // Divisor Latch Most sign. byte + //logic [7:0] PSD; // Pre Scaler Division, Optional + } uart_reg_fields_t; + + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Default/Reset Register Values // + //////////////////////////////////////////////////////////////////////////////////////////////// + + // Default values for the Registers from UART 16550A Standard + localparam uart_reg_fields_t RegResetVal = '{ + RHR: 8'h00, + THR: 8'h00, + IER: 8'h00, + // ISR: 8'hC1, // -> 11000001; bit 6 and 7 high -> 16550A (implemented in interrupt module) + FCR: 8'h00, + LCR: 8'h00, + MCR: 8'h00, + LSR: 8'h60, + MSR: 8'h00, + // SPR: 8'h00, // scratch reg not implemented, always return zero + DLL: 8'h01, + DLM: 8'h00 + // PSD: PSD_DEFAULT // PSD not implemented + }; + + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Interface between UART INTERNAL LOGIC and Register // + //////////////////////////////////////////////////////////////////////////////////////////////// + + typedef struct packed { + // current register values + thr_bits_t thr; + ier_bits_t ier; + isr_bits_t isr; + fcr_bits_t fcr; + lcr_bits_t lcr; + mcr_bits_t mcr; + dll_bits_t dll; + dlm_bits_t dlm; + // read/write indicators + logic obi_read_rhr; + logic obi_read_isr; + logic obi_read_lsr; + logic obi_read_msr; + logic obi_write_thr; + logic obi_write_dllm; + } reg_read_t; + + // new values from rx module + typedef struct packed { + rhr_bits_t rhr; + logic fifo_rst; + logic fifo_err; + logic data_ready; + logic overrun; + logic par_err; + logic frame_err; + logic break_ind; + + logic rhr_valid; + logic fifo_rst_valid; + logic fifo_err_valid; + logic dr_valid; + logic overrun_valid; + logic par_valid; + logic frame_valid; + logic break_valid; + } rx_reg_write_t; + + // new values from tx module + typedef struct packed { + logic fifo_rst; + logic tx_empty; + logic thr_empty; + + logic fifo_rst_valid; + logic empty_valid; + logic thr_valid; + } tx_reg_write_t; + + typedef struct packed { + rx_reg_write_t rx; + tx_reg_write_t tx; + isr_bits_t isr; + msr_bits_t modem; + } reg_write_t; + + +endpackage diff --git a/rtl/obi_uart/obi_uart_register.sv b/rtl/obi_uart/obi_uart_register.sv new file mode 100644 index 00000000..5731e3b8 --- /dev/null +++ b/rtl/obi_uart/obi_uart_register.sv @@ -0,0 +1,301 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Authors: +// - Hannah Pochert +// - Philippe Sauter + +`include "common_cells/registers.svh" + +module obi_uart_register import obi_uart_pkg::*; #( + /// The OBI configuration connected to this peripheral. + parameter obi_pkg::obi_cfg_t ObiCfg = obi_pkg::ObiDefaultConfig, // SbrObiCfg + /// OBI request type + parameter type obi_req_t = logic, + /// OBI response type + parameter type obi_rsp_t = logic +) ( + input logic clk_i, + input logic rst_ni, + + // OBI request interface + input obi_req_t obi_req_i, // a.addr, a.we, a.be, a.wdata, a.aid, a.a_optional | rready, req + // OBI response interface + output obi_rsp_t obi_rsp_o, // r.rdata, r.rid, r.err, r.r_optional | gnt, rvalid + + output reg_read_t reg_read_o, // Current register values + input reg_write_t reg_write_i // Internal updates to register values +); + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Obi Preparations // + //////////////////////////////////////////////////////////////////////////////////////////////// + + // Signals for the OBI response + logic [ObiCfg.DataWidth-1:0] rsp_data; + logic valid_d, valid_q; // delayed for the response phase + logic err; + logic w_err_d, w_err_q; + logic [AddressBits-1:0] word_addr_d, word_addr_q; // delayed for the response phase + logic [ObiCfg.IdWidth-1:0] id_d, id_q; // delayed for the response phase + logic we_d, we_q; + logic req_d, req_q; + + // OBI rsp Assignment + always_comb begin + obi_rsp_o = '0; + obi_rsp_o.r.rdata = rsp_data; + obi_rsp_o.r.rid = id_q; + obi_rsp_o.r.err = err; + obi_rsp_o.gnt = obi_req_i.req; + obi_rsp_o.rvalid = valid_q; + end + + // id, valid and address handling + assign id_d = obi_req_i.a.aid; + assign valid_d = obi_req_i.req; + assign word_addr_d = obi_req_i.a.addr[AddressOffset+:AddressBits]; + assign we_d = obi_req_i.a.we; + assign req_d = obi_req_i.req; + + // FF for the obi rsp signals (id and valid) + `FF(id_q, id_d, '0, clk_i, rst_ni) // 5 Bits + `FF(valid_q, valid_d, '0, clk_i, rst_ni) // 1 Bit + `FF(word_addr_q, word_addr_d, '0, clk_i, rst_ni) // #AddressBits Bits + `FF(we_q, we_d, '0, clk_i, rst_ni) // 1 Bit + `FF(w_err_q, w_err_d, '0, clk_i, rst_ni) // 1 Bit + `FF(req_q, req_d, '0, clk_i, rst_ni) // 1 Bit + + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Registers // + //////////////////////////////////////////////////////////////////////////////////////////////// + uart_reg_fields_t reg_d, reg_q; + uart_reg_fields_t new_reg; // next value of the registers if no read/write occurs (hw update) + + + //////////////////////////////////////////////////////////////////////////////////////////////// + // COMB LOGIC // + //////////////////////////////////////////////////////////////////////////////////////////////// + rx_reg_write_t write_rx; + tx_reg_write_t write_tx; + + assign write_tx = reg_write_i.tx; + assign write_rx = reg_write_i.rx; + + // output current register values + assign reg_read_o.thr = reg_q.THR; + assign reg_read_o.ier = reg_q.IER; + assign reg_read_o.isr = reg_write_i.isr; + assign reg_read_o.fcr = reg_q.FCR; + assign reg_read_o.lcr = reg_q.LCR; + assign reg_read_o.mcr = reg_q.MCR; + assign reg_read_o.dll = reg_q.DLL; + assign reg_read_o.dlm = reg_q.DLM; + + //-- Internal updates to registers ------------------------------------------------------------- + always_comb begin : hw_update + // default + new_reg = reg_q; + + // Flow Control Register + new_reg.FCR.rx_fifo_rst = write_rx.fifo_rst_valid ? write_rx.fifo_rst : reg_q.FCR.rx_fifo_rst; + new_reg.FCR.tx_fifo_rst = write_tx.fifo_rst_valid ? write_tx.fifo_rst : reg_q.FCR.tx_fifo_rst; + + new_reg.RHR = write_rx.rhr_valid ? write_rx.rhr : reg_q.RHR; + + // Line Status Register + new_reg.LSR.fifo_err = write_rx.fifo_err_valid ? write_rx.fifo_err : reg_q.LSR.fifo_err; + new_reg.LSR.tx_empty = write_tx.empty_valid ? write_tx.tx_empty : reg_q.LSR.tx_empty; + new_reg.LSR.thr_empty = write_tx.thr_valid ? write_tx.thr_empty : reg_q.LSR.thr_empty; + new_reg.LSR.break_ind = write_rx.break_valid ? write_rx.break_ind : reg_q.LSR.break_ind; + new_reg.LSR.frame_err = write_rx.frame_valid ? write_rx.frame_err : reg_q.LSR.frame_err; + new_reg.LSR.par_err = write_rx.par_valid ? write_rx.par_err : reg_q.LSR.par_err; + new_reg.LSR.data_ready = write_rx.dr_valid ? write_rx.data_ready : reg_q.LSR.data_ready; + new_reg.LSR.overrun = write_rx.overrun_valid ? write_rx.overrun : reg_q.LSR.overrun; + + // Modem Status Register + new_reg.MSR.cd = reg_write_i.modem.cd; + new_reg.MSR.ri = reg_write_i.modem.ri; + new_reg.MSR.dsr = reg_write_i.modem.dsr; + new_reg.MSR.cts = reg_write_i.modem.cts; + // remains high once set until cleared by read + new_reg.MSR.d_cd = reg_q.MSR.d_cd | reg_write_i.modem.d_cd; + new_reg.MSR.te_ri = reg_q.MSR.te_ri | reg_write_i.modem.te_ri; + new_reg.MSR.d_dsr = reg_q.MSR.d_dsr | reg_write_i.modem.d_dsr; + new_reg.MSR.d_cts = reg_q.MSR.d_cts | reg_write_i.modem.d_cts; + end + + //-- Software updates to registers ------------------------------------------------------------- + always_comb begin + // default + err = w_err_q; + w_err_d = 1'b0; + + // read/write indicators + reg_read_o.obi_read_rhr = 1'b0; + reg_read_o.obi_read_isr = 1'b0; + reg_read_o.obi_read_lsr = 1'b0; + reg_read_o.obi_read_msr = 1'b0; + reg_read_o.obi_write_thr = 1'b0; + reg_read_o.obi_write_dllm = 1'b0; + + rsp_data = 32'h0; + + reg_d = new_reg; + + //-- OBI-Writes ------------------------------------------------------------------------------ + if (obi_req_i.req & obi_req_i.a.we & obi_req_i.a.be[0]) begin + + w_err_d = 1'b0; + + if (~reg_q.LCR[7]) begin // DLAB = 0 Address Decode + + case (word_addr_d) + RegAddrTHR: begin + reg_d.THR = obi_req_i.a.wdata[RegWidth-1:0]; + reg_read_o.obi_write_thr = 1'b1; + end + + RegAddrIER: begin + reg_d.IER = obi_req_i.a.wdata[RegWidth-1:0]; + end + + RegAddrFCR: begin + reg_d.FCR = obi_req_i.a.wdata[RegWidth-1:0]; + end + + RegAddrLCR: begin + reg_d.LCR = obi_req_i.a.wdata[RegWidth-1:0]; + end + + RegAddrMCR: begin + reg_d.MCR = obi_req_i.a.wdata[RegWidth-1:0]; + end + + RegAddrSPR: begin + // no error but ignored (SPR always returns 0) + end + + default: begin + w_err_d = 1'b1; // unmapped register access + end + endcase + + end else begin // DLAB = 1 Address Decode + + case (word_addr_d) + RegAddrDLL: begin + reg_d.DLL = obi_req_i.a.wdata[RegWidth-1:0]; + reg_read_o.obi_write_dllm = 1'b1; + end + + RegAddrDLM: begin + reg_d.DLM = obi_req_i.a.wdata[RegWidth-1:0]; + reg_read_o.obi_write_dllm = 1'b1; + end + + RegAddrFCR: begin + reg_d.FCR = obi_req_i.a.wdata[RegWidth-1:0]; + end + + RegAddrLCR: begin + reg_d.LCR = obi_req_i.a.wdata[RegWidth-1:0]; + end + + RegAddrMCR: begin + reg_d.MCR = obi_req_i.a.wdata[RegWidth-1:0]; + end + + RegAddrSPR: begin + // no error but ignored (SPR always returns 0) + end + + default: begin + w_err_d = 1'b1; // unmapped register access + end + endcase + + end + + end + + //-- OBI-Read -------------------------------------------------------------------------------- + if (req_q & ~we_q) begin + + err = 1'b0; + + if (~reg_q.LCR[7]) begin // DLAB = 0 Address Decode + + case (word_addr_q) + RegAddrRHR: begin + rsp_data[RegWidth-1:0] = reg_q.RHR; + reg_read_o.obi_read_rhr = 1'b1; + end + + RegAddrIER: begin + rsp_data[RegWidth-1:0] = reg_q.IER; + end + + RegAddrISR: begin + rsp_data[RegWidth-1:0] = reg_write_i.isr; + reg_read_o.obi_read_isr = 1'b1; + end + + RegAddrLCR: begin + rsp_data[RegWidth-1:0] = reg_q.LCR; + end + + RegAddrMCR: begin + rsp_data[RegWidth-1:0] = reg_q.MCR; + end + + RegAddrLSR: begin + rsp_data[RegWidth-1:0] = reg_q.LSR; + reg_read_o.obi_read_lsr = 1'b1; + end + + RegAddrMSR: begin + rsp_data[RegWidth-1:0] = reg_q.MSR; + reg_d.MSR = reg_write_i.modem; // sticky bits cleared + end + + RegAddrSPR: begin + rsp_data[RegWidth-1:0] = '0; // not implemented + end + + default: begin + err = 1'b1; + end + endcase + + end else begin // DLAB = 1 Address Decode + + case (word_addr_q) + RegAddrDLL: begin + rsp_data[RegWidth-1:0] = reg_q.DLL; + end + + RegAddrDLM: begin + rsp_data[RegWidth-1:0] = reg_q.DLM; + end + + default: begin + err = 1'b1; + end + endcase + + end + + end + + end + + //////////////////////////////////////////////////////////////////////////////////////////////// + // SEQUENTIAL LOGIC // + //////////////////////////////////////////////////////////////////////////////////////////////// + + `FF(reg_q, reg_d, obi_uart_pkg::RegResetVal, clk_i, rst_ni) + +endmodule diff --git a/rtl/obi_uart/obi_uart_rx.sv b/rtl/obi_uart/obi_uart_rx.sv new file mode 100644 index 00000000..2ef497fb --- /dev/null +++ b/rtl/obi_uart/obi_uart_rx.sv @@ -0,0 +1,574 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Authors: +// - Hannah Pochert +// - Philippe Sauter + +`include "common_cells/registers.svh" + +module obi_uart_rx import obi_uart_pkg::*; #() +( + input logic clk_i, + input logic rst_ni, + + input logic oversample_rate_edge_i, + input logic baud_rate_edge_i, + + input logic rxd_i, + + output logic trigger_o, + output logic timeout_o, + + input reg_read_t reg_read_i, + output rx_reg_write_t reg_write_o +); + + //--Timing-------------------------------------------------------------------------------------- + logic timing_bit_center_q, timing_bit_center_d; + logic timing_bit_center_edge; + logic timing_clear; + logic timing_init_clear; + logic timing_load; + logic [4:0] timing_offset; + logic [4:0] timing_count; + + //--Synchronization-Signals--------------------------------------------------------------------- + logic sync_rxd; + + //--Majority-Filter-Signals--------------------------------------------------------------------- + logic [1:0] high_count_q, high_count_d; + logic filtered_rxd_q, filtered_rxd_d; + + //--FIFO-signals-------------------------------------------------------------------------------- + logic fifo_clear; + logic fifo_full; + logic fifo_empty; + logic [3:0] fifo_usage; + logic [10:0] fifo_data_i; + logic [10:0] fifo_data_o; + logic fifo_push; + logic fifo_pop; + // FIFO Write + logic break_interrupt; + logic [3:0] fifo_error_index_q, fifo_error_index_d; + // FIFO trigger + logic [3:0] tl_characters; + // FIFO timeout + // longest character: 1 start, 8 data, 1 parity, 2 stop -> 12bit + // timeout occurs after 4 characters -> 48bit -> $clog2(48) = 6 + logic [3:0] character_length; + logic [5:0] timeout_level; + logic [5:0] timeout_count_q, timeout_count_d; + + //--Write-Read-FIFO-or-Write-RHR---------------------------------------------------------------- + logic rhr_full_q, rhr_full_d; + + //--Statemachine-Transition-Signals------------------------------------------------------------- + state_type_rx_e state_q, state_d; + logic rsr_finish; + logic par_finish; + logic stop_finish; + logic write_init; + + //--Statemachine-RSR-Signals-------------------------------------------------------------------- + logic [7:0] rsr_q, rsr_d; + logic [2:0] bitcount_q, bitcount_d; // Count up to character_len + logic [2:0] word_len_bits; // 5-8 Bits + + //--Statemachine-Error-Signals------------------------------------------------------------------ + // Parity Check + logic parity_err_q, parity_err_d; + logic data_parity; + // Stop Bit Check + logic framing_err_q, framing_err_d; + logic break_q, break_d; + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Timing // + //////////////////////////////////////////////////////////////////////////////////////////////// + + //---------------------------------------------------------------------------------------------- + // Counter Instantiation + //---------------------------------------------------------------------------------------------- + + //--Clear-Counter------------------------------------------------------------------------------- + assign timing_clear = ((timing_count == 5'b01111) && oversample_rate_edge_i) + | (timing_init_clear) ? 1'b1 : 1'b0; + + counter #( + .WIDTH (5), + .STICKY_OVERFLOW(0) + ) i_counter ( + .clk_i, + .rst_ni, + .clear_i (timing_clear), // Synchronous clear: Sets Counter 0 in the next cycle + .en_i (oversample_rate_edge_i), + .load_i (timing_load), + .down_i (1'b0), // Always count upwards + .d_i (timing_offset), + .q_o (timing_count), + .overflow_o() + ); + + //---------------------------------------------------------------------------------------------- + // Timing Bit Center + //---------------------------------------------------------------------------------------------- + // Is high for one oversample_rate cycle + assign timing_bit_center_d = (timing_count == 5'b01000) ? 1'b1 : 1'b0; + // Edge is high for one clk_i cycle + assign timing_bit_center_edge = (timing_bit_center_d & ~timing_bit_center_q) ? 1'b1 : 1'b0; + + `FF(timing_bit_center_q, timing_bit_center_d, '0, clk_i, rst_ni) + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Input Stages // + //////////////////////////////////////////////////////////////////////////////////////////////// + + //---------------------------------------------------------------------------------------------- + // 2-Stage Input Synchronization + //---------------------------------------------------------------------------------------------- + sync #( + .STAGES (NrSyncStages) + ) i_sync ( + .clk_i, + .rst_ni, + .serial_i(rxd_i), + .serial_o(sync_rxd) + ); + + //---------------------------------------------------------------------------------------------- + // 3-Sample Majority Filter + //---------------------------------------------------------------------------------------------- + // The Majority Filter takes 3 samples and sets filtered_rxd high if at least 2 of them are high + + always_comb begin + + high_count_d = high_count_q; + filtered_rxd_d = filtered_rxd_q; + + // no timing lock yet, use as last sync_rxd value + if( (state_q == RXIDLE) || (state_q == RXRESYNCHRONIZE) ) begin + filtered_rxd_d = sync_rxd; + end + + if (timing_count == 5'b00100) begin // Start reset in cycle 5: "Majority Init" + high_count_d = 2'b00; + end else if (oversample_rate_edge_i) begin + if (sync_rxd & (timing_count < 5'b00111)) begin // Take samples in Cycle 6, 7, 8 + high_count_d = high_count_q + 1; + end else if (timing_count == 5'b00111) begin // filtered_rxd is set for Oversample Cycle 8 + if ((high_count_q == 2'b10) | (high_count_q == 2'b11) ) begin + filtered_rxd_d = 1'b1; + end else begin + filtered_rxd_d = 1'b0; + end + end + end + + end + + `FF(high_count_q, high_count_d, '0, clk_i, rst_ni) + `FF(filtered_rxd_q, filtered_rxd_d, 1'b1, clk_i, rst_ni) + + //////////////////////////////////////////////////////////////////////////////////////////////// + // FIFO Instantiation// + //////////////////////////////////////////////////////////////////////////////////////////////// + + fifo_v3 # ( + .FALL_THROUGH(), + .DATA_WIDTH (11), + .DEPTH (16), + .dtype (), + .ADDR_DEPTH () // DO NOT OVERWRITE THIS PARAMETER + ) i_fifo_v3 ( + .clk_i, // Clock + .rst_ni, // Asynchronous reset active low + .flush_i (fifo_clear), // flush the queue + .testmode_i(1'b0), + // status flags + .full_o (fifo_full), // queue is full + .empty_o (fifo_empty), // queue is empty + .usage_o (fifo_usage), // fill pointer + // as long as the queue is not full we can push new data + .data_i (fifo_data_i), // data to push into the queue + .push_i (fifo_push), // data is valid and can be pushed to the queue + // as long as the queue is not empty we can pop new elements + .data_o (fifo_data_o), // output data + .pop_i (fifo_pop) // pop head from queue + ); + + //////////////////////////////////////////////////////////////////////////////////////////////// + // General Logic // + //////////////////////////////////////////////////////////////////////////////////////////////// + always_comb begin + + //-------------------------------------------------------------------------------------------- + // Defaults + //-------------------------------------------------------------------------------------------- + // Character is all zeros, parity and stop indicate break, current line is still 0 -> break + break_interrupt = (rsr_q == '0) & (break_q | break_d) & (~filtered_rxd_q); + + //--FIFO Combinational------------------------------------------------------------------------ + fifo_clear = 1'b1; // Reset + + trigger_o = 1'b0; // trigger_o + tl_characters = 4'b0001; // trigger_o + + fifo_push = 1'b0; // Write + fifo_data_i = '0; // Write + + timeout_count_d = timeout_count_q; + timeout_o = 1'b0; // timeout_o + // timeout_level = (character_length * 4) +1 + character_length = (6'd02 +word_len_bits +reg_read_i.lcr.par_en +reg_read_i.lcr.stop_bits); + timeout_level = (character_length << 2) + 6'd01; + + fifo_error_index_d = fifo_error_index_q; // FIFO Error + + //--Register Interface------------------------------------------------------------------------ + reg_write_o = '0; + + //--Statemachine Combinational---------------------------------------------------------------- + state_d = state_q; // Pass along state + rsr_d = rsr_q; + bitcount_d = bitcount_q; + parity_err_d = parity_err_q; + framing_err_d = framing_err_q; + break_d = break_q; // Break Interrupt information for Parity and Stop Bits + + rsr_finish = 1'b0; + par_finish = 1'b0; + stop_finish = 1'b0; + write_init = 1'b0; + + data_parity = 1'b0; + + timing_init_clear = 1'b0; + timing_load = 1'b0; + timing_offset = 5'b00000; + + //--RHR-Combinational------------------------------------------------------------------------- + fifo_clear = 1'b1; + fifo_pop = 1'b0; + rhr_full_d = rhr_full_q; + + //-------------------------------------------------------------------------------------------- + // Word Length + //-------------------------------------------------------------------------------------------- + case (reg_read_i.lcr.word_len) + 2'b00: word_len_bits = 3'b100; // 5 Bits (4th index in rsr) + 2'b01: word_len_bits = 3'b101; // 6 Bits (5th index in rsr) + 2'b10: word_len_bits = 3'b110; // 7 Bits (6th index in rsr) + 2'b11: word_len_bits = 3'b111; // 8 Bits (7th index in rsr) + default: word_len_bits = 3'b111; + endcase + + //-------------------------------------------------------------------------------------------- + // Clear RHR & LSR after OBI read + //-------------------------------------------------------------------------------------------- + + //-Clear-RHR-and-Reset-Data-Ready-Bit--------------------------------------------------------- + if (reg_read_i.obi_read_rhr) begin + reg_write_o.rhr = '0; + reg_write_o.rhr_valid = 1'b1; + + rhr_full_d = 1'b0; + + reg_write_o.data_ready = 1'b0; + reg_write_o.dr_valid = 1'b1; + end + + if (reg_read_i.obi_read_lsr) begin // Clear LSR + reg_write_o.overrun = 1'b0; + reg_write_o.par_err = 1'b0; + reg_write_o.frame_err = 1'b0; + reg_write_o.break_ind = 1'b0; + reg_write_o.overrun_valid = 1'b0; + reg_write_o.par_valid = 1'b0; + reg_write_o.frame_valid = 1'b0; + reg_write_o.break_valid = 1'b0; + if (fifo_error_index_q == 4'b0000) begin + reg_write_o.fifo_err = 1'b0; + reg_write_o.fifo_err_valid = 1'b1; + end + end + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Statemachine Combinational // + //////////////////////////////////////////////////////////////////////////////////////////////// + + //-------------------------------------------------------------------------------------------- + // RSR - Receiver Shift Register (serial to parallel) + //-------------------------------------------------------------------------------------------- + // After rsr_finish, rsr_q is stored until the next time we are in START state + if (state_q == RXDATA) begin + if (timing_bit_center_edge & (bitcount_q <= word_len_bits)) begin + rsr_d[bitcount_q] = filtered_rxd_q; + bitcount_d = bitcount_q + 1; + if (bitcount_q == word_len_bits) begin + rsr_finish = 1'b1; + end + end + end + + //-------------------------------------------------------------------------------------------- + // Parity Check + //-------------------------------------------------------------------------------------------- + if (state_q == RXPAR) begin + parity_err_d = 1'b0; + data_parity = ^rsr_q; // XOR to compute parity of data bits + + if (timing_bit_center_edge) begin + case (reg_read_i.lcr[5:4]) // Read Parity Configuration + 2'b00: parity_err_d = (data_parity == filtered_rxd_q); // Odd Parity + 2'b01: parity_err_d = (data_parity != filtered_rxd_q); // Even Parity + 2'b10: parity_err_d = (~filtered_rxd_q); // Forced 1 + 2'b11: parity_err_d = filtered_rxd_q; // Forced 0 + default: parity_err_d = 1'b0; + endcase + break_d = ~filtered_rxd_q; + par_finish = 1'b1; + end + end + + //-------------------------------------------------------------------------------------------- + // Stop Bit Check + //-------------------------------------------------------------------------------------------- + if (state_q == RXSTOP) begin + framing_err_d = 1'b0; + if (timing_bit_center_edge) begin + break_d = ~filtered_rxd_q & (break_q | ~reg_read_i.lcr.par_en); + write_init = 1'b1; + stop_finish = 1'b1; + if (!filtered_rxd_q) begin + framing_err_d = 1'b1; + end else begin + framing_err_d = 1'b0; + end + end + end + + //-------------------------------------------------------------------------------------------- + // State Transformation + //-------------------------------------------------------------------------------------------- + case(state_q) + RXIDLE: begin + if (filtered_rxd_q & ~sync_rxd) begin // falling edge + state_d = RXSTART; + timing_init_clear = 1'b0; + if (oversample_rate_edge_i) begin + timing_load = 1'b1; + timing_offset = 5'b00010; // If first cycle not detected: Set Timing Counter to 2 + end + end + timing_init_clear = 1'b1; + end + + RXSTART: begin + if (timing_bit_center_edge) begin + if (~filtered_rxd_q) begin + bitcount_d = 3'b000; + rsr_d = '0; + state_d = RXDATA; + end else begin + state_d = RXIDLE; + end + end + end + + RXDATA: begin // Stays in this state for "word_len_bits" baud_cycles + if (rsr_finish) begin + if (reg_read_i.lcr.par_en) begin + state_d = RXPAR; + end else begin + state_d = RXSTOP; + end + end + end + + RXPAR: begin + if (par_finish) begin + state_d = RXSTOP; + end + end + + RXSTOP: begin + if (stop_finish) begin + if (framing_err_q) begin + state_d = RXRESYNCHRONIZE; + end else begin + state_d = RXIDLE; + end + end + end + + RXRESYNCHRONIZE: begin + if (filtered_rxd_q & ~sync_rxd) begin // falling edge + state_d = RXSTART; + end else begin + state_d = RXIDLE; + end + end + + default: state_d = RXIDLE; + endcase + + //////////////////////////////////////////////////////////////////////////////////////////////// + // WRITE RHR Combinational // + //////////////////////////////////////////////////////////////////////////////////////////////// + + //-------------------------------------------------------------------------------------------- + // Write RHR + //-------------------------------------------------------------------------------------------- + if (reg_read_i.fcr.fifo_en) begin // FIFO enabled + + // data ready when a character is moved from rsr or fifo to rhr or rhr already has data + reg_write_o.dr_valid = 1'b1; + reg_write_o.data_ready = write_init | ~fifo_empty | rhr_full_q; + + //--Write-FIFO-to-RHR----------------------------------------------------------------------- + if ((~rhr_full_q) & (~fifo_empty)) begin + reg_write_o.rhr = fifo_data_o[7:0]; + reg_write_o.rhr_valid = 1'b1; + reg_write_o.data_ready = 1'b1; + rhr_full_d = 1'b1; + + // If Fifo Enabled, always set LSR bits with the Data on top of the FIFO + reg_write_o.break_ind = fifo_data_o[8]; + reg_write_o.frame_err = fifo_data_o[9]; + reg_write_o.par_err = fifo_data_o[10]; + reg_write_o.break_valid = 1'b1; + reg_write_o.frame_valid = 1'b1; + reg_write_o.par_valid = 1'b1; + fifo_pop = 1'b1; + + if (4'b0000 != fifo_error_index_q) begin + fifo_error_index_d = fifo_error_index_q - 'b0001; + end + end + + end else begin // FIFO disabled : RHR acts as 1-Byte Holding Register + + //--Write-RSR-to-RHR------------------------------------------------------------------------ + if (write_init) begin + if (rhr_full_q) begin + reg_write_o.overrun = 1'b1; + reg_write_o.overrun_valid = 1'b1; + end + reg_write_o.rhr = rsr_q; // If full, RHR just gets overwritten + reg_write_o.rhr_valid = 1'b1; + rhr_full_d = 1'b1; + + reg_write_o.data_ready = 1'b1; // Set Data Ready Bit + reg_write_o.dr_valid = 1'b1; + reg_write_o.par_err = parity_err_q; + reg_write_o.frame_err = framing_err_q; + reg_write_o.break_ind = break_interrupt; + reg_write_o.break_ind = 1'b1; + reg_write_o.break_valid = 1'b1; + reg_write_o.par_valid = 1'b1; + reg_write_o.frame_valid = 1'b1; + end + + end + + //////////////////////////////////////////////////////////////////////////////////////////////// + // FIFO Combinational // + //////////////////////////////////////////////////////////////////////////////////////////////// + + if (reg_read_i.fcr.fifo_en) begin + //------------------------------------------------------------------------------------------ + // FIFO Reset + //------------------------------------------------------------------------------------------ + fifo_clear = 1'b0; + + if (reg_read_i.fcr.rx_fifo_rst) begin + fifo_clear = 1'b1; + reg_write_o.fifo_rst = 1'b0; + reg_write_o.fifo_rst_valid = 1'b1; + end + //------------------------------------------------------------------------------------------ + // FIFO trigger_o Output + //------------------------------------------------------------------------------------------ + case (reg_read_i.fcr.rx_fifo_tl) + 2'b00: tl_characters = 4'b0001; // 1 Character + 2'b01: tl_characters = 4'b0100; // 4 Characters + 2'b10: tl_characters = 4'b1000; // 8 Characters + 2'b11: tl_characters = 4'b1110; // 14 Characters + default: tl_characters = 4'b0001; + endcase + + if (tl_characters <= fifo_usage) begin + trigger_o = 1'b1; + end + //------------------------------------------------------------------------------------------ + // FIFO Write from RSR + //------------------------------------------------------------------------------------------ + if (write_init) begin + if (fifo_full) begin + reg_write_o.overrun = 1'b1; + reg_write_o.overrun_valid = 1'b1; + end else begin + fifo_push = 1'b1; + fifo_data_i = {parity_err_q, framing_err_q, break_interrupt, rsr_q}; // 11 Bits + + if (parity_err_q | framing_err_q | break_interrupt) begin + fifo_error_index_d = fifo_usage; + reg_write_o.fifo_err = 1'b1; + reg_write_o.fifo_err_valid = 1'b1; + end + end + end + //------------------------------------------------------------------------------------------ + // FIFO timeout + //------------------------------------------------------------------------------------------ + if (reg_read_i.obi_read_rhr | write_init) begin + timeout_count_d = '0; + end else if (~fifo_empty | rhr_full_q) begin + if (baud_rate_edge_i) begin + timeout_count_d = timeout_count_q + 1; + end + if (timeout_count_q == timeout_level) begin + timeout_o = 1'b1; + timeout_count_d = timeout_count_q; + end + end + + end // fifo enabled + + end // always_comb + + //////////////////////////////////////////////////////////////////////////////////////////////// + // FIFO & WRITE RHR Sequential // + //////////////////////////////////////////////////////////////////////////////////////////////// + + //--FIFO---------------------------------------------------------------------------------------- + `FF(fifo_error_index_q, fifo_error_index_d, '0, clk_i, rst_ni) + `FF(timeout_count_q, timeout_count_d, '0, clk_i, rst_ni) + + //--Write-RHR----------------------------------------------------------------------------------- + `FF(rhr_full_q, rhr_full_d, '0, clk_i, rst_ni) + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Statemachine Sequential// + //////////////////////////////////////////////////////////////////////////////////////////////// + + //--Statelogic---------------------------------------------------------------------------------- + `FF(state_q, state_d, RXIDLE, clk_i, rst_ni) + + //--RSR----------------------------------------------------------------------------------------- + `FF(rsr_q, rsr_d, '0, clk_i, rst_ni) + `FF(bitcount_q, bitcount_d, '0, clk_i, rst_ni) + + //--Parity-------------------------------------------------------------------------------------- + `FF(parity_err_q, parity_err_d, '0, clk_i, rst_ni) + + //--Stop---------------------------------------------------------------------------------------- + `FF(framing_err_q, framing_err_d, '0, clk_i, rst_ni) + + //--Break-Interrupt----------------------------------------------------------------------------- + `FF(break_q, break_d, '0, clk_i, rst_ni) + +endmodule diff --git a/rtl/obi_uart/obi_uart_tx.sv b/rtl/obi_uart/obi_uart_tx.sv new file mode 100644 index 00000000..920879de --- /dev/null +++ b/rtl/obi_uart/obi_uart_tx.sv @@ -0,0 +1,310 @@ +// Copyright 2024 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Authors: +// - Hannah Pochert +// - Philippe Sauter + +`include "common_cells/registers.svh" + +module obi_uart_tx #() +( + input logic clk_i, + input logic rst_ni, + + input logic baud_rate_edge_i, + input logic double_rate_edge_i, + + output logic txd_o, + + input obi_uart_pkg::reg_read_t reg_read_i, + output obi_uart_pkg::tx_reg_write_t reg_write_o +); + + // Import the UART package for definitions and parameters + import obi_uart_pkg::*; + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Instantiations // + //////////////////////////////////////////////////////////////////////////////////////////////// + + //--FIFO---------------------------------------------------------------------------------------- + logic fifo_clear; + logic fifo_full; + logic fifo_empty; + logic [7:0] fifo_data_i; + logic [7:0] fifo_data_o; + logic fifo_push; + logic fifo_pop; + logic [3:0] fifo_usage; + + //--THR-Full------------------------------------------------------------------------------------ + logic thr_full_q, thr_full_d; + + //--Statemachine-Transition-Signals------------------------------------------------------------- + state_type_tx_e state_q, state_d; + + logic [2:0] word_len_bits; + logic [7:0] word_len_mask; + + //--Statemachine-TSR-Signals-------------------------------------------------------------------- + logic tsr_empty; + logic tsr_finish; + logic [7:0] tsr_q, tsr_d; + logic [2:0] tsr_count_q, tsr_count_d; + + logic txd_q, txd_d; + + //////////////////////////////////////////////////////////////////////////////////////////////// + // FIFO Instantiation // + //////////////////////////////////////////////////////////////////////////////////////////////// + + fifo_v3 # ( + .FALL_THROUGH(1'b0), + .DATA_WIDTH (8), + .DEPTH (16) + ) i_fifo_v3 ( + .clk_i, + .rst_ni, + .flush_i (fifo_clear), // flush the queue + .testmode_i(1'b0 ), + // status flags + .full_o (fifo_full), // queue is full + .empty_o (fifo_empty), // queue is empty + .usage_o (fifo_usage), // fill pointer + // as long as the queue is not full we can push new data + .data_i (fifo_data_i), // data to push into the queue + .push_i (fifo_push ), // data is valid and can be pushed to the queue + // as long as the queue is not empty we can pop new elements + .data_o (fifo_data_o), // output data + .pop_i (fifo_pop ) // pop head from queue + ); + + //////////////////////////////////////////////////////////////////////////////////////////////// + // General Logic // + //////////////////////////////////////////////////////////////////////////////////////////////// + always_comb begin + //-------------------------------------------------------------------------------------------- + // Defaults + //-------------------------------------------------------------------------------------------- + thr_full_d = thr_full_q; + word_len_mask = '0; + + //--FIFO Combinational------------------------------------------------------------------------ + fifo_clear = 1'b0; + fifo_push = 1'b0; + fifo_data_i = '0; + + //--Register Interface------------------------------------------------------------------------ + reg_write_o = '0; + + //--Statemachine Combinational---------------------------------------------------------------- + state_d = state_q; // Pass along state + + txd_o = txd_q & ~reg_read_i.lcr.set_break; // UART Output Assignment + txd_d = txd_q; // UART Output store for one bit time + + fifo_pop = 1'b0; // Read and Remove Byte From FIFO + + tsr_d = tsr_q; //TSR + tsr_count_d = tsr_count_q; //TSR + tsr_finish = 1'b0; //TSR + tsr_empty = 1'b0; //TSR + + //-------------------------------------------------------------------------------------------- + // Word Length + //-------------------------------------------------------------------------------------------- + case (reg_read_i.lcr.word_len) + 2'b00: word_len_bits = 3'b100; // 5 Bits (4th index in tsr) + 2'b01: word_len_bits = 3'b101; // 6 Bits (5th index in tsr) + 2'b10: word_len_bits = 3'b110; // 7 Bits (6th index in tsr) + 2'b11: word_len_bits = 3'b111; // 8 Bits (7th index in tsr) + default: word_len_bits = 3'b111; + endcase + + for (int i = 0; i <= word_len_bits; i = i + 1) begin + word_len_mask[i] = 1'b1; + end + + //-------------------------------------------------------------------------------------------- + // THR Full Flag + //-------------------------------------------------------------------------------------------- + if (reg_read_i.obi_write_thr) begin + thr_full_d = 1'b1; + end + + //-------------------------------------------------------------------------------------------- + // Reset LSR + //-------------------------------------------------------------------------------------------- + if (reg_read_i.obi_write_thr) begin + reg_write_o.thr_empty = 1'b0; + reg_write_o.tx_empty = 1'b0; + reg_write_o.thr_valid = 1'b1; + reg_write_o.empty_valid = 1'b1; + end + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Statemachine Combinational // + //////////////////////////////////////////////////////////////////////////////////////////////// + + //-------------------------------------------------------------------------------------------- + // TSR - Transmitter Shift Register (parallel to serial) + //-------------------------------------------------------------------------------------------- + if (state_q == TXDATA & (tsr_count_q <= word_len_bits)) begin + txd_d = tsr_q[tsr_count_q]; + if (baud_rate_edge_i) begin + tsr_count_d = tsr_count_q + 1; + tsr_finish = (tsr_count_q == word_len_bits)? 1'b1 : 1'b0; + end + end + + //-------------------------------------------------------------------------------------------- + // State Transition + //-------------------------------------------------------------------------------------------- + case(state_q) + TXIDLE: begin + txd_d = 1'b1; // Inactive High + tsr_d = '0; + tsr_count_d = 1'b0; + tsr_empty = 1'b1; + + if (reg_read_i.fcr.fifo_en) begin + if (~fifo_empty & baud_rate_edge_i) begin // Read FIFO into TSR + tsr_d = fifo_data_o; + fifo_pop = 1'b1; + state_d = TXSTART; + end + end else begin + if (thr_full_q & baud_rate_edge_i) begin // Read THR into TSR + tsr_d = reg_read_i.thr.char_tx & word_len_mask; + thr_full_d = 1'b0; + state_d = TXSTART; + end + end + end + + TXSTART: begin + txd_d = 1'b0; + if (baud_rate_edge_i) begin + state_d = TXDATA; + end + end + + TXDATA: begin + if (tsr_finish) begin + if (reg_read_i.lcr.par_en) begin + state_d = TXPAR; + end else begin + state_d = TXSTOP1; + end + end + end + + TXPAR: begin + case (reg_read_i.lcr[5:4])// Read Parity Configuration + 2'b00: txd_d = ~(^tsr_q); // Odd Parity + 2'b01: txd_d = ^tsr_q; // Even Parity + 2'b10: txd_d = 1'b1; // Forced 1 + 2'b11: txd_d = 1'b0; // Forced 0 + default: txd_d = 1'b0; + endcase + if (baud_rate_edge_i) begin + state_d = TXSTOP1; + end + end + + TXSTOP1: begin + txd_d = 1'b1; + if (reg_read_i.lcr.stop_bits) begin + // next transaction starts on next baud_rate_edge_i + state_d = TXIDLE; + end else if (baud_rate_edge_i) begin + state_d = TXSTOP2; + end + end + + TXSTOP2: begin + txd_d = 1'b1; + if (word_len_bits == 3'b100) begin + // 1.5 stop bits + if(double_rate_edge_i) begin + state_d = TXIDLE; + // TODO: Change active edge to the other double_rate edge to have true 1.5b stop bit + // Since RX is a bit flexible this still works but degreades performance minimally + // only for a config with 1.5b stop bits. + end + end else begin + state_d = TXIDLE; + end + end + + default: state_d = TXIDLE; + endcase + + //////////////////////////////////////////////////////////////////////////////////////////////// + // FIFO Combinational // + //////////////////////////////////////////////////////////////////////////////////////////////// + + if (reg_read_i.fcr.fifo_en) begin + //--Reset-FIFO------------------------------------------------------------------------------ + fifo_clear = 1'b0; + + if (reg_read_i.fcr.tx_fifo_rst) begin + fifo_clear = 1'b1; + reg_write_o.fifo_rst = 1'b0; + reg_write_o.fifo_rst_valid = 1'b1; + end + + //--Set-LSR--------------------------------------------------------------------------------- + if (fifo_empty) begin + reg_write_o.thr_empty = 1'b1; + reg_write_o.thr_valid = 1'b1; + if (tsr_empty) begin + reg_write_o.tx_empty = 1'b1; + reg_write_o.empty_valid = 1'b1; + end + end + + //--Write-FIFO-from-THR--------------------------------------------------------------------- + if (thr_full_q & (~fifo_full)) begin + fifo_push = 1'b1; + fifo_data_i = reg_read_i.thr.char_tx & word_len_mask; + thr_full_d = 1'b0; + end + end + + //////////////////////////////////////////////////////////////////////////////////////////////// + // THR Combinational // + //////////////////////////////////////////////////////////////////////////////////////////////// + + if (~reg_read_i.fcr.fifo_en) begin + //--Keep-FIFO-cleared----------------------------------------------------------------------- + fifo_clear = 1'b1; + //--Set-LSR--------------------------------------------------------------------------------- + if (~thr_full_q) begin + reg_write_o.thr_empty = 1'b1; + reg_write_o.thr_valid = 1'b1; + if (tsr_empty) begin + reg_write_o.tx_empty = 1'b1; + reg_write_o.empty_valid = 1'b1; + end + end + end + + end + + //////////////////////////////////////////////////////////////////////////////////////////////// + // Sequential // + //////////////////////////////////////////////////////////////////////////////////////////////// + + `FF(thr_full_q, thr_full_d, '0, clk_i, rst_ni) + + `FF(tsr_q, tsr_d, '0, clk_i, rst_ni) + `FF(tsr_count_q, tsr_count_d, '0, clk_i, rst_ni) + + `FF(txd_q, txd_d, '1, clk_i, rst_ni) + + `FF(state_q, state_d, TXIDLE, clk_i, rst_ni) + +endmodule diff --git a/rtl/patches/apb_uart/0001-adjust-Bender-source-paths.patch b/rtl/patches/apb_uart/0001-adjust-Bender-source-paths.patch deleted file mode 100644 index 70d601be..00000000 --- a/rtl/patches/apb_uart/0001-adjust-Bender-source-paths.patch +++ /dev/null @@ -1,48 +0,0 @@ -From f753ef201beb917408327d3cafc28b6228af3fb1 Mon Sep 17 00:00:00 2001 -From: Philippe Sauter -Date: Wed, 21 Aug 2024 11:56:27 +0200 -Subject: [PATCH] adjust Bender source paths - ---- - Bender.yml | 28 ++++++++++++++-------------- - 1 file changed, 14 insertions(+), 14 deletions(-) - -diff --git a/Bender.yml b/Bender.yml -index 40ec53d..60d59b6 100644 ---- a/Bender.yml -+++ b/Bender.yml -@@ -10,17 +10,17 @@ dependencies: - register_interface: { git: "https://github.com/pulp-platform/register_interface", version: 0.3.6 } - - sources: -- - src/slib_clock_div.sv -- - src/slib_counter.sv -- - src/slib_edge_detect.sv -- - src/slib_fifo.sv -- - src/slib_input_filter.sv -- - src/slib_input_sync.sv -- - src/slib_mv_filter.sv -- - src/uart_baudgen.sv -- - src/uart_interrupt.sv -- - src/uart_receiver.sv -- - src/uart_transmitter.sv -- - src/apb_uart.sv -- - src/apb_uart_wrap.sv -- - src/reg_uart_wrap.sv -+ - slib_clock_div.sv -+ - slib_counter.sv -+ - slib_edge_detect.sv -+ - slib_fifo.sv -+ - slib_input_filter.sv -+ - slib_input_sync.sv -+ - slib_mv_filter.sv -+ - uart_baudgen.sv -+ - uart_interrupt.sv -+ - uart_receiver.sv -+ - uart_transmitter.sv -+ - apb_uart.sv -+ - apb_uart_wrap.sv -+ - reg_uart_wrap.sv --- -2.25.1 - diff --git a/rtl/patches/apb_uart/src/0001-Add-missing-parameter-keyword.patch b/rtl/patches/apb_uart/src/0001-Add-missing-parameter-keyword.patch deleted file mode 100644 index 3ec231b1..00000000 --- a/rtl/patches/apb_uart/src/0001-Add-missing-parameter-keyword.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 342fbd22d648915c80fff8551aa72e470139572b Mon Sep 17 00:00:00 2001 -From: Philippe Sauter -Date: Wed, 21 Aug 2024 11:54:22 +0200 -Subject: [PATCH] Add missing parameter keyword - ---- - slib_mv_filter.sv | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/slib_mv_filter.sv b/slib_mv_filter.sv -index d5b50a9..363b89e 100644 ---- a/slib_mv_filter.sv -+++ b/slib_mv_filter.sv -@@ -32,7 +32,7 @@ - // Boston, MA 02111-1307 USA - // - --module slib_mv_filter #(parameter WIDTH = 4, THRESHOLD = 10) ( -+module slib_mv_filter #(parameter WIDTH = 4, parameter THRESHOLD = 10) ( - input wire CLK, - input wire RST, - input wire SAMPLE, --- -2.25.1 - diff --git a/rtl/patches/apb_uart/src/0002-Assign-missing-vector-bits.patch b/rtl/patches/apb_uart/src/0002-Assign-missing-vector-bits.patch deleted file mode 100644 index 7046ba83..00000000 --- a/rtl/patches/apb_uart/src/0002-Assign-missing-vector-bits.patch +++ /dev/null @@ -1,91 +0,0 @@ -From c264e0b71fc240a31fab080164ad41e6c24314f9 Mon Sep 17 00:00:00 2001 -From: Philippe Sauter -Date: Wed, 21 Aug 2024 11:55:22 +0200 -Subject: [PATCH] Assign missing vector bits - ---- - apb_uart.sv | 21 ++++++++++----------- - 1 file changed, 10 insertions(+), 11 deletions(-) - -diff --git a/apb_uart.sv b/apb_uart.sv -index 6e7d2b9..0372a46 100644 ---- a/apb_uart.sv -+++ b/apb_uart.sv -@@ -254,7 +254,7 @@ always @(posedge CLK or posedge iRST) - always @(posedge CLK or posedge iRST) - if ((iRST == 1'b1)) - begin -- iIER[3:0] <= 0; -+ iIER[7:0] <= 0; - end - else - begin -@@ -262,13 +262,13 @@ always @(posedge CLK or posedge iRST) - begin - iIER[3:0] <= PWDATA[3:0]; - end -+ iIER[7:4] <= '0; - end - - assign /*432*/ iIER_ERBI = iIER[0]; // 434 - assign /*432*/ iIER_ETBEI = iIER[1]; // 434 - assign /*432*/ iIER_ELSI = iIER[2]; // 434 - assign /*432*/ iIER_EDSSI = iIER[3]; // 434 --assign iIER[7:4] = 0; - - uart_interrupt UART_IIC ( - .CLK(CLK), -@@ -422,14 +422,15 @@ assign /*432*/ iLCR_DLAB = iLCR[7]; // 434 - always @(posedge CLK or posedge iRST) - if ((iRST == 1'b1)) - begin -- iMCR[5:0] <= 0; -+ iMCR[7:0] <= 0; - end - else - begin - if ((iMCRWrite == 1'b1)) -- begin -- iMCR[5:0] <= PWDATA[5:0]; -- end -+ begin -+ iMCR[5:0] <= PWDATA[5:0]; -+ end -+ iMCR[7:6] <= 0; - end - - assign /*432*/ iMCR_DTR = iMCR[0]; // 434 -@@ -438,7 +439,6 @@ assign /*432*/ iMCR_OUT1 = iMCR[2]; // 434 - assign /*432*/ iMCR_OUT2 = iMCR[3]; // 434 - assign /*432*/ iMCR_LOOP = iMCR[4]; // 434 - assign /*432*/ iMCR_AFE = iMCR[5]; // 434 --assign iMCR[7:6] = 0; - - always @(posedge CLK or posedge iRST) - if ((iRST == 1'b1)) -@@ -877,7 +877,7 @@ always @(posedge CLK or posedge iRST) - - always @(PADDR or iLCR_DLAB or iRBR or iDLL or iDLM or iIER or iIIR or iLCR or iMCR or iLSR or iMSR or iSCR) - begin -- case (PADDR) -+ case (PADDR) - 3'b000: - begin - if ((iLCR_DLAB == 1'b0)) -@@ -937,11 +937,10 @@ always @(PADDR or iLCR_DLAB or iRBR or iDLL or iDLM or iIER or iIIR or iLCR or i - PRDATA[7:0] <= iRBR; - end - -- endcase -- -+ endcase -+ PRDATA[31:8] <= '0; - end - --assign PRDATA[31:8] = 24'b0; - assign /*432*/ PREADY = 1'b1; // 434 - assign /*432*/ PSLVERR = 1'b0; // 434 - --- -2.25.1 - diff --git a/rtl/patches/obi_uart/0001-adjust-Bender-source-paths.patch b/rtl/patches/obi_uart/0001-adjust-Bender-source-paths.patch new file mode 100644 index 00000000..32a8faf9 --- /dev/null +++ b/rtl/patches/obi_uart/0001-adjust-Bender-source-paths.patch @@ -0,0 +1,36 @@ +From e765f951952915890d475fcd703090d9bbc5ed29 Mon Sep 17 00:00:00 2001 +From: Philippe Sauter +Date: Fri, 20 Jun 2025 13:04:20 +0200 +Subject: [PATCH] adjust Bender source paths + +--- + Bender.yml | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/Bender.yml b/Bender.yml +index 516ea3d..e49903d 100644 +--- a/Bender.yml ++++ b/Bender.yml +@@ -14,11 +14,11 @@ dependencies: + + sources: + # obi_uart +- - hw/obi_uart/obi_uart_pkg.sv +- - hw/obi_uart/obi_uart_baudgen.sv +- - hw/obi_uart/obi_uart_interrupts.sv +- - hw/obi_uart/obi_uart_modem.sv +- - hw/obi_uart/obi_uart_rx.sv +- - hw/obi_uart/obi_uart_tx.sv +- - hw/obi_uart/obi_uart_register.sv +- - hw/obi_uart/obi_uart.sv ++ - obi_uart_pkg.sv ++ - obi_uart_baudgen.sv ++ - obi_uart_interrupts.sv ++ - obi_uart_modem.sv ++ - obi_uart_rx.sv ++ - obi_uart_tx.sv ++ - obi_uart_register.sv ++ - obi_uart.sv +-- +2.49.0 + diff --git a/rtl/tb_croc_soc.sv b/rtl/tb_croc_soc.sv index b87f6646..e00080c4 100644 --- a/rtl/tb_croc_soc.sv +++ b/rtl/tb_croc_soc.sv @@ -323,8 +323,8 @@ module tb_croc_soc #( logic uart_reading_byte; initial begin - uart_rx_i = 1; - uart_reading_byte = 0; + uart_rx_i = 1'b1; + uart_reading_byte = 1'b0; end task automatic uart_read_byte(output byte_bt bite); @@ -447,7 +447,6 @@ module tb_croc_soc #( $dumpvars(1,i_croc_soc); `endif - uart_rx_i = 1'b0; fetch_en_i = 1'b0; // wait for reset diff --git a/sw/helloworld.c b/sw/helloworld.c index 8c3da8ae..c7ecd927 100644 --- a/sw/helloworld.c +++ b/sw/helloworld.c @@ -31,6 +31,8 @@ uint32_t isqrt(uint32_t n) { return res; } +char receive_buff[16] = {0}; + int main() { uart_init(); // setup the uart peripheral @@ -39,6 +41,22 @@ int main() { // wait until uart has finished sending uart_write_flush(); + // uart loopback + uart_loopback_enable(); + printf("internal msg\n"); + sleep_ms(1); + for(uint8_t idx = 0; idx<15; idx++) { + receive_buff[idx] = uart_read(); + if(receive_buff[idx] == '\n') { + break; + } + } + uart_loopback_disable(); + + printf("Loopback received: "); + printf(receive_buff); + uart_write_flush(); + // toggling some GPIOs gpio_set_direction(0xFFFF, 0x000F); // lowest four as outputs gpio_write(0x0A); // ready output pattern diff --git a/sw/lib/inc/print.h b/sw/lib/inc/print.h index 9265bbb8..4ed921cc 100644 --- a/sw/lib/inc/print.h +++ b/sw/lib/inc/print.h @@ -11,4 +11,4 @@ extern void putchar(char); // simple printf with support for %x formatter but no others -void printf(const char *fmt, ...); +void printf(char *fmt, ...); diff --git a/sw/lib/inc/uart.h b/sw/lib/inc/uart.h index d62ff11b..eaf907d0 100644 --- a/sw/lib/inc/uart.h +++ b/sw/lib/inc/uart.h @@ -30,11 +30,15 @@ // Register fields #define UART_LINE_STATUS_DATA_READY_BIT 0 -#define UART_LINE_STATUS_THR_EMPTY_BIT 5 +#define UART_LINE_STATUS_THR_EMPTY_BIT 5 #define UART_LINE_STATUS_TMIT_EMPTY_BIT 6 void uart_init(); +void uart_loopback_enable(); + +void uart_loopback_disable(); + int uart_read_ready(); void uart_write(uint8_t byte); diff --git a/sw/lib/src/print.c b/sw/lib/src/print.c index 4ec0883d..d3ddd67b 100644 --- a/sw/lib/src/print.c +++ b/sw/lib/src/print.c @@ -27,7 +27,7 @@ uint8_t format_hex32(char *buffer, uint32_t num) { return idx; } -void printf(const char *fmt, ...) { +void printf(char *fmt, ...) { va_list args; va_start(args, fmt); char buffer[12]; // holds string while assembling diff --git a/sw/lib/src/uart.c b/sw/lib/src/uart.c index 25d57a0b..e38a0b6c 100644 --- a/sw/lib/src/uart.c +++ b/sw/lib/src/uart.c @@ -15,15 +15,27 @@ void uart_init() { const uint16_t divisor = UART_DIVISOR(UART_FREQ, UART_BAUD); // Calculate from provided config uint8_t dlo = (uint8_t)(divisor); uint8_t dhi = (uint8_t)(divisor >> 8); - *reg8(UART_BASE_ADDR, UART_INTR_ENABLE_REG_OFFSET) = 0x00; // Disable all interrupts - *reg8(UART_BASE_ADDR, UART_LINE_CONTROL_REG_OFFSET) = 0x80; // Enable DLAB (set baud rate divisor) - *reg8(UART_BASE_ADDR, UART_DLAB_LSB_REG_OFFSET) = dlo; // divisor (lo byte) - *reg8(UART_BASE_ADDR, UART_DLAB_MSB_REG_OFFSET) = dhi; // divisor (hi byte) - *reg8(UART_BASE_ADDR, UART_LINE_CONTROL_REG_OFFSET) = 0x03; // 8 bits, no parity, one stop bit - *reg8(UART_BASE_ADDR, UART_FIFO_CONTROL_REG_OFFSET) = 0xC7; // Enable & clear FIFO, 14B threshold + *reg8(UART_BASE_ADDR, UART_INTR_ENABLE_REG_OFFSET) = 0x00; // Disable all interrupts + *reg8(UART_BASE_ADDR, UART_LINE_CONTROL_REG_OFFSET) = 0x80; // Enable DLAB (set baud rate divisor) + *reg8(UART_BASE_ADDR, UART_DLAB_LSB_REG_OFFSET) = dlo; // divisor (lo byte) + *reg8(UART_BASE_ADDR, UART_DLAB_MSB_REG_OFFSET) = dhi; // divisor (hi byte) + *reg8(UART_BASE_ADDR, UART_LINE_CONTROL_REG_OFFSET) = 0x03; // 8 bits, no parity, one stop bit + *reg8(UART_BASE_ADDR, UART_FIFO_CONTROL_REG_OFFSET) = 0xC7; // Enable & clear FIFO, 14B threshold *reg8(UART_BASE_ADDR, UART_MODEM_CONTROL_REG_OFFSET) = 0x20; // Autoflow mode } +void uart_loopback_enable() { + uart_write_flush(); + uint8_t mcr = *reg8(UART_BASE_ADDR, UART_MODEM_CONTROL_REG_OFFSET); + *reg8(UART_BASE_ADDR, UART_MODEM_CONTROL_REG_OFFSET) = mcr | (1 << 4); +} + +void uart_loopback_disable() { + uart_write_flush(); + uint8_t mcr = *reg8(UART_BASE_ADDR, UART_MODEM_CONTROL_REG_OFFSET); + *reg8(UART_BASE_ADDR, UART_MODEM_CONTROL_REG_OFFSET) = mcr & ~(1 << 4); +} + int uart_read_ready() { return *reg8(UART_BASE_ADDR, UART_LINE_STATUS_REG_OFFSET) & (1 << UART_LINE_STATUS_DATA_READY_BIT); } diff --git a/sw/link.ld b/sw/link.ld index dd434411..590658c2 100644 --- a/sw/link.ld +++ b/sw/link.ld @@ -19,12 +19,25 @@ SECTIONS { /DISCARD/ : { *(.riscv.attributes) *(.comment) } - .text._start 0x10000000 : { *(.text._start) } >SRAM - .text : { *(.text) *(.text.*) } >SRAM - .misc : { *(.sdata) *(.*) } >SRAM - - __global_pointer$ = ADDR(.misc) + SIZEOF(.misc) / 2; - __stack_pointer$ = ORIGIN(SRAM) + LENGTH(SRAM); + .text._start : { + *(.text._start) + } >SRAM - status = 0x03000008; + .misc : ALIGN(4) { + *(.sdata) + *(.sbss) + *(.*data*) + *(.*bss*) + *(COMMON) + } >SRAM + + .text : ALIGN(4) { + *(.text) + *(.text.*) + } >SRAM } + +/* Global absolute symbols */ +PROVIDE(__global_pointer$ = ADDR(.misc) + SIZEOF(.misc)/2); +PROVIDE(__stack_pointer$ = ORIGIN(SRAM) + LENGTH(SRAM)); +PROVIDE(status = 0x03000008);