📄 apbuart.vhd
字号:
-------------------------------------------------------------------------------- This file is a part of the GRLIB VHDL IP LIBRARY-- Copyright (C) 2003, Gaisler Research---- This program is free software; you can redistribute it and/or modify-- it under the terms of the GNU General Public License as published by-- the Free Software Foundation; either version 2 of the License, 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 more details.---- You should have received a copy of the GNU General Public License-- along with this program; if not, write to the Free Software-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ------------------------------------------------------------------------------- Entity: uart-- File: uart.vhd-- Authors: Jiri Gaisler - Gaisler Research-- Marko Isomaki - Gaisler Research-- Description: Asynchronous UART. Implements 8-bit data frame with one stop-bit.------------------------------------------------------------------------------library ieee;use ieee.std_logic_1164.all;--use ieee.numeric_std.all;library grlib;use grlib.amba.all;use grlib.stdlib.all;use grlib.devices.all;library gaisler;use gaisler.uart.all;--pragma translate_offuse std.textio.all;--pragma translate_onentity apbuart is generic ( pindex : integer := 0; paddr : integer := 0; pmask : integer := 16#fff#; console : integer := 0; pirq : integer := 0; parity : integer := 1; flow : integer := 1; fifosize : integer range 1 to 32 := 1; abits : integer := 8); port ( rst : in std_ulogic; clk : in std_ulogic; apbi : in apb_slv_in_type; apbo : out apb_slv_out_type; uarti : in uart_in_type; uarto : out uart_out_type);end;architecture rtl of apbuart isconstant REVISION : integer := 1;constant pconfig : apb_config_type := ( 0 => ahb_device_reg ( VENDOR_GAISLER, GAISLER_APBUART, 0, REVISION, pirq), 1 => apb_iobar(paddr, pmask));type rxfsmtype is (idle, startbit, data, cparity, stopbit);type txfsmtype is (idle, data, cparity, stopbit);type fifo is array (0 to fifosize - 1) of std_logic_vector(7 downto 0);type uartregs is record rxen : std_ulogic; -- receiver enabled txen : std_ulogic; -- transmitter enabled rirqen : std_ulogic; -- receiver irq enable tirqen : std_ulogic; -- transmitter irq enable parsel : std_ulogic; -- parity select paren : std_ulogic; -- parity select flow : std_ulogic; -- flow control enable loopb : std_ulogic; -- loop back mode enable rsempty : std_ulogic; -- receiver shift register empty (internal) tsempty : std_ulogic; -- transmitter shift register empty break : std_ulogic; -- break detected ovf : std_ulogic; -- receiver overflow parerr : std_ulogic; -- parity error frame : std_ulogic; -- framing error ctsn : std_logic_vector(1 downto 0); -- clear to send rtsn : std_ulogic; -- request to send extclken : std_ulogic; -- use external baud rate clock extclk : std_ulogic; -- rising edge detect register rhold : fifo; rshift : std_logic_vector(7 downto 0); tshift : std_logic_vector(10 downto 0); thold : fifo; irq : std_ulogic; -- tx/rx interrupt (internal) tpar : std_ulogic; -- tx data parity (internal) txstate : txfsmtype; txclk : std_logic_vector(2 downto 0); -- tx clock divider txtick : std_ulogic; -- tx clock (internal) rxstate : rxfsmtype; rxclk : std_logic_vector(2 downto 0); -- rx clock divider rxdb : std_logic_vector(1 downto 0); -- rx delay dpar : std_ulogic; -- rx data parity (internal) rxtick : std_ulogic; -- rx clock (internal) tick : std_ulogic; -- rx clock (internal) scaler : std_logic_vector(11 downto 0); brate : std_logic_vector(11 downto 0); rxf : std_logic_vector(4 downto 0); -- rx data filtering buffer txd : std_ulogic; -- transmitter data rfifoirqen : std_ulogic; -- receiver fifo interrupt enable tfifoirqen : std_ulogic; -- transmitter fifo interrupt enable --fifo counters rwaddr : std_logic_vector(log2x(fifosize) - 1 downto 0); rraddr : std_logic_vector(log2x(fifosize) - 1 downto 0); traddr : std_logic_vector(log2x(fifosize) - 1 downto 0); twaddr : std_logic_vector(log2x(fifosize) - 1 downto 0); rcnt : std_logic_vector(log2x(fifosize) downto 0); tcnt : std_logic_vector(log2x(fifosize) downto 0);end record;constant rcntzero : std_logic_vector(log2x(fifosize) downto 0) := (others => '0');signal r, rin : uartregs;begin uartop : process(rst, r, apbi, uarti ) variable rdata : std_logic_vector(31 downto 0); variable scaler : std_logic_vector(11 downto 0); variable rxclk, txclk : std_logic_vector(2 downto 0); variable rxd, ctsn : std_ulogic; variable irq : std_logic_vector(NAHBIRQ-1 downto 0); variable paddr : std_logic_vector(7 downto 2); variable v : uartregs; variable thalffull : std_ulogic; variable rhalffull : std_ulogic; variable rfull : std_ulogic; variable tfull : std_ulogic; variable dready : std_ulogic; variable thempty : std_ulogic;--pragma translate_off variable L1 : line; variable CH : character; variable FIRST : boolean := true; variable pt : time := 0 ns;--pragma translate_on begin v := r; irq := (others => '0'); irq(pirq) := r.irq; v.irq := '0'; v.txtick := '0'; v.rxtick := '0'; v.tick := '0'; rdata := (others => '0'); v.rxdb(1) := r.rxdb(0); dready := '0'; thempty := '1'; thalffull := '1'; rhalffull := '0'; v.ctsn := r.ctsn(0) & uarti.ctsn; if fifosize = 1 then dready := r.rcnt(0); rfull := dready; tfull := r.tcnt(0); thempty := not tfull; else tfull := r.tcnt(log2x(fifosize)); rfull := r.rcnt(log2x(fifosize)); if (r.rcnt(log2x(fifosize)) or r.rcnt(log2x(fifosize) - 1)) = '1' then rhalffull := '1'; end if; if ((r.tcnt(log2x(fifosize)) or r.tcnt(log2x(fifosize) - 1))) = '1' then thalffull := '0'; end if; if r.rcnt /= rcntzero then dready := '1'; end if; if r.tcnt /= rcntzero then thempty := '0'; end if; end if;-- scaler scaler := r.scaler - 1; if (r.rxen or r.txen) = '1' then v.scaler := scaler; v.tick := scaler(11) and not r.scaler(11); if v.tick = '1' then v.scaler := r.brate; end if; end if;-- optional external uart clock v.extclk := uarti.extclk; if r.extclken = '1' then v.tick := r.extclk and not uarti.extclk; end if;-- read/write registers case paddr(7 downto 2) is when "000000" => rdata(7 downto 0) := r.rhold(conv_integer(r.rraddr)); if (apbi.psel(pindex) and apbi.penable and (not apbi.pwrite)) = '1' then if fifosize = 1 then v.rcnt(0) := '0'; else if r.rcnt /= rcntzero then v.rraddr := r.rraddr + 1; v.rcnt := r.rcnt - 1; end if; end if; end if; when "000001" => if fifosize /= 1 then rdata (26 + log2x(fifosize) downto 26) := r.rcnt; rdata (20 + log2x(fifosize) downto 20) := r.tcnt; rdata (10 downto 7) := rfull & tfull & rhalffull & thalffull; end if; rdata(6 downto 0) := r.frame & r.parerr & r.ovf & r.break & thempty & r.tsempty & dready;--pragma translate_off if CONSOLE = 1 then rdata(2 downto 1) := "11"; end if;--pragma translate_on when "000010" => if fifosize /= 1 then rdata(10 downto 9) := r.rfifoirqen & r.tfifoirqen; end if; rdata(8 downto 0) := r.extclken & r.loopb & r.flow & r.paren & r.parsel & r.tirqen & r.rirqen & r.txen & r.rxen; when others => rdata(11 downto 0) := r.brate; end case; paddr := "000000"; paddr(abits-1 downto 2) := apbi.paddr(abits-1 downto 2); if (apbi.psel(pindex) and apbi.penable and apbi.pwrite) = '1' then case paddr(7 downto 2) is when "000000" => when "000001" => v.frame := apbi.pwdata(6); v.parerr := apbi.pwdata(5); v.ovf := apbi.pwdata(4); v.break := apbi.pwdata(3); when "000010" => if fifosize /= 1 then v.rfifoirqen := apbi.pwdata(10); v.tfifoirqen := apbi.pwdata(9); end if; v.extclken := apbi.pwdata(8); v.loopb := apbi.pwdata(7); v.flow := apbi.pwdata(6); v.paren := apbi.pwdata(5); v.parsel := apbi.pwdata(4); v.tirqen := apbi.pwdata(3);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -