1
0
mirror of https://github.com/wfjm/w11.git synced 2026-05-05 23:55:01 +00:00
Files
wfjm.w11/rtl/vlib/serport/serport_1clock.vhd

275 lines
8.4 KiB
VHDL

-- $Id: serport_1clock.vhd 984 2018-01-02 20:56:27Z mueller $
--
-- Copyright 2011-2015 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 3, or (at your option) any later version.
--
-- This program 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 General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Module Name: serport_1clock - syn
-- Description: serial port: serial port module, 1 clock domain
--
-- Dependencies: serport_uart_rxtx_ab
-- serport_xonrx
-- serport_xontx
-- memlib/fifo_1c_dram
-- Test bench: -
-- Target Devices: generic
-- Tool versions: ise 13.1-14.7; viv 2014.4; ghdl 0.29-0.31
--
-- Synthesized (xst):
-- Date Rev ise Target flop lutl lutm slic t peri
-- 2015-04-12 666 14.7 131013 xc6slx16-2 171 239 32 94 s 6.3
-- 2011-11-13 424 13.1 O40d xc3s1000-4 157 337 64 232 s 9.9
--
-- Revision History:
-- Date Rev Version Comment
-- 2015-04-11 666 1.1.1 add sim assertions for RXOVR and RXERR
-- 2015-02-01 641 1.1 add CLKDIV_F for autobaud;
-- 2011-12-10 438 1.0.2 internal reset on abact
-- 2011-12-09 437 1.0.1 rename stat->moni port
-- 2011-11-13 424 1.0 Initial version
-- 2011-10-23 419 0.5 First draft
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.slvtypes.all;
use work.serportlib.all;
use work.memlib.all;
entity serport_1clock is -- serial port module, 1 clock domain
generic (
CDWIDTH : positive := 13; -- clk divider width
CDINIT : natural := 15; -- clk divider initial/reset setting
RXFAWIDTH : natural := 5; -- rx fifo address width
TXFAWIDTH : natural := 5); -- tx fifo address width
port (
CLK : in slbit; -- clock
CE_MSEC : in slbit; -- 1 msec clock enable
RESET : in slbit; -- reset
ENAXON : in slbit; -- enable xon/xoff handling
ENAESC : in slbit; -- enable xon/xoff escaping
RXDATA : out slv8; -- receiver data out
RXVAL : out slbit; -- receiver data valid
RXHOLD : in slbit; -- receiver data hold
TXDATA : in slv8; -- transmit data in
TXENA : in slbit; -- transmit data enable
TXBUSY : out slbit; -- transmit busy
MONI : out serport_moni_type; -- serport monitor port
RXSD : in slbit; -- receive serial data (uart view)
TXSD : out slbit; -- transmit serial data (uart view)
RXRTS_N : out slbit; -- receive rts (uart view, act.low)
TXCTS_N : in slbit -- transmit cts (uart view, act.low)
);
end serport_1clock;
architecture syn of serport_1clock is
signal R_RXOK : slbit := '1';
signal RESET_INT : slbit := '0';
signal UART_RXDATA : slv8 := (others=>'0');
signal UART_RXVAL : slbit := '0';
signal UART_TXDATA : slv8 := (others=>'0');
signal UART_TXENA : slbit := '0';
signal UART_TXBUSY : slbit := '0';
signal XONTX_TXENA : slbit := '0';
signal XONTX_TXBUSY : slbit := '0';
signal RXFIFO_DI : slv8 := (others=>'0');
signal RXFIFO_ENA : slbit := '0';
signal RXFIFO_BUSY : slbit := '0';
signal RXFIFO_SIZE : slv(RXFAWIDTH downto 0) := (others=>'0');
signal TXFIFO_DO : slv8 := (others=>'0');
signal TXFIFO_VAL : slbit := '0';
signal TXFIFO_HOLD : slbit := '0';
signal RXERR : slbit := '0';
signal RXOVR : slbit := '0';
signal RXACT : slbit := '0';
signal ABACT : slbit := '0';
signal ABDONE : slbit := '0';
signal ABCLKDIV : slv(CDWIDTH-1 downto 0) := (others=>'0');
signal ABCLKDIV_F : slv3 := (others=>'0');
signal TXOK : slbit := '0';
signal RXOK : slbit := '0';
begin
assert CDWIDTH<=16
report "assert(CDWIDTH<=16): max width of UART clock divider"
severity failure;
UART : serport_uart_rxtx_ab -- uart, rx+tx+autobauder combo
generic map (
CDWIDTH => CDWIDTH,
CDINIT => CDINIT)
port map (
CLK => CLK,
CE_MSEC => CE_MSEC,
RESET => RESET,
RXSD => RXSD,
RXDATA => UART_RXDATA,
RXVAL => UART_RXVAL,
RXERR => RXERR,
RXACT => RXACT,
TXSD => TXSD,
TXDATA => UART_TXDATA,
TXENA => UART_TXENA,
TXBUSY => UART_TXBUSY,
ABACT => ABACT,
ABDONE => ABDONE,
ABCLKDIV => ABCLKDIV,
ABCLKDIV_F => ABCLKDIV_F
);
RESET_INT <= RESET or ABACT;
XONRX : serport_xonrx -- xon/xoff logic rx path
port map (
CLK => CLK,
RESET => RESET_INT,
ENAXON => ENAXON,
ENAESC => ENAESC,
UART_RXDATA => UART_RXDATA,
UART_RXVAL => UART_RXVAL,
RXDATA => RXFIFO_DI,
RXVAL => RXFIFO_ENA,
RXHOLD => RXFIFO_BUSY,
RXOVR => RXOVR,
TXOK => TXOK
);
XONTX : serport_xontx -- xon/xoff logic tx path
port map (
CLK => CLK,
RESET => RESET_INT,
ENAXON => ENAXON,
ENAESC => ENAESC,
UART_TXDATA => UART_TXDATA,
UART_TXENA => XONTX_TXENA,
UART_TXBUSY => XONTX_TXBUSY,
TXDATA => TXFIFO_DO,
TXENA => TXFIFO_VAL,
TXBUSY => TXFIFO_HOLD,
RXOK => RXOK,
TXOK => TXOK
);
RXFIFO : fifo_1c_dram -- input fifo, 1 clock, dram based
generic map (
AWIDTH => RXFAWIDTH,
DWIDTH => 8)
port map (
CLK => CLK,
RESET => RESET_INT,
DI => RXFIFO_DI,
ENA => RXFIFO_ENA,
BUSY => RXFIFO_BUSY,
DO => RXDATA,
VAL => RXVAL,
HOLD => RXHOLD,
SIZE => RXFIFO_SIZE
);
TXFIFO : fifo_1c_dram -- output fifo, 1 clock, dram based
generic map (
AWIDTH => TXFAWIDTH,
DWIDTH => 8)
port map (
CLK => CLK,
RESET => RESET_INT,
DI => TXDATA,
ENA => TXENA,
BUSY => TXBUSY,
DO => TXFIFO_DO,
VAL => TXFIFO_VAL,
HOLD => TXFIFO_HOLD,
SIZE => open
);
-- receive back pressure
-- on if fifo more than 3/4 full
-- off if fifo less than 1/2 full
proc_rxok: process (CLK)
constant rxsize_rxok_off : slv3 := "011";
constant rxsize_rxok_on : slv3 := "010";
variable rxsize_msb : slv3 := "000";
begin
if rising_edge(CLK) then
if RESET_INT = '1' then
R_RXOK <= '1';
else
rxsize_msb := RXFIFO_SIZE(RXFAWIDTH downto RXFAWIDTH-2);
if unsigned(rxsize_msb) >= unsigned(rxsize_rxok_off) then
R_RXOK <= '0';
elsif unsigned(rxsize_msb) <= unsigned(rxsize_rxok_on) then
R_RXOK <= '1';
end if;
end if;
end if;
end process proc_rxok;
RXOK <= R_RXOK;
RXRTS_N <= not R_RXOK;
proc_cts: process (TXCTS_N, XONTX_TXENA, UART_TXBUSY)
begin
if TXCTS_N = '0' then -- transmit cts asserted
UART_TXENA <= XONTX_TXENA;
XONTX_TXBUSY <= UART_TXBUSY;
else -- transmit cts not asserted
UART_TXENA <= '0';
XONTX_TXBUSY <= '1';
end if;
end process proc_cts;
MONI.rxerr <= RXERR;
MONI.rxovr <= RXOVR;
MONI.rxact <= RXACT;
MONI.txact <= UART_TXBUSY;
MONI.abact <= ABACT;
MONI.abdone <= ABDONE;
MONI.rxok <= RXOK;
MONI.txok <= TXOK;
proc_abclkdiv: process (ABCLKDIV, ABCLKDIV_F)
begin
MONI.abclkdiv <= (others=>'0');
MONI.abclkdiv(ABCLKDIV'range) <= ABCLKDIV;
MONI.abclkdiv_f <= ABCLKDIV_F;
end process proc_abclkdiv;
-- synthesis translate_off
proc_check: process (CLK)
begin
if rising_edge(CLK) then
assert RXOVR = '0'
report "serport_1clock-W: RXOVR = " & slbit'image(RXOVR) &
"; data loss in receive fifo"
severity warning;
assert RXERR = '0'
report "serport_1clock-W: RXERR = " & slbit'image(RXERR) &
"; spurious receive error"
severity warning;
end if;
end process proc_check;
-- synthesis translate_on
end syn;