diff options
author | Bert Lange <b.lange@fzd.de> | 2011-01-07 14:55:05 +0100 |
---|---|---|
committer | Bert Lange <b.lange@fzd.de> | 2011-01-07 14:55:05 +0100 |
commit | 09acf7f43a4fff055599637122b73febf2dd2f1b (patch) | |
tree | 66d58c7be6ce5b422975c3c80ce45c6a6c723a46 /gaisler | |
parent | 72fa0c4b8d3a07ea4cff4265c9b27685178ae74e (diff) | |
download | zpu-09acf7f43a4fff055599637122b73febf2dd2f1b.zip zpu-09acf7f43a4fff055599637122b73febf2dd2f1b.tar.gz |
add: UART with debug functionalitiy
Diffstat (limited to 'gaisler')
-rw-r--r-- | gaisler/rtl/ahbmst.vhd | 167 | ||||
-rw-r--r-- | gaisler/rtl/ahbuart.vhd | 81 | ||||
-rw-r--r-- | gaisler/rtl/dcom.vhd | 149 | ||||
-rw-r--r-- | gaisler/rtl/dcom_uart.vhd | 325 | ||||
-rw-r--r-- | gaisler/rtl/libdcom.vhd | 171 |
5 files changed, 893 insertions, 0 deletions
diff --git a/gaisler/rtl/ahbmst.vhd b/gaisler/rtl/ahbmst.vhd new file mode 100644 index 0000000..de2b144 --- /dev/null +++ b/gaisler/rtl/ahbmst.vhd @@ -0,0 +1,167 @@ +------------------------------------------------------------------------------ +-- This file is a part of the GRLIB VHDL IP LIBRARY +-- Copyright (C) 2003 - 2008, Gaisler Research +-- Copyright (C) 2008 - 2010, Aeroflex Gaisler +-- +-- 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: ahbmst +-- File: ahbmst.vhd +-- Author: Jiri Gaisler - Gaisler Research +-- Description: Generic AHB master interface +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; +library grlib; +use grlib.amba.all; +use grlib.stdlib.all; +use grlib.devices.all; +library gaisler; +use gaisler.misc.all; + +entity ahbmst is + generic ( + hindex : integer := 0; + hirq : integer := 0; + venid : integer := VENDOR_GAISLER; + devid : integer := 0; + version : integer := 0; + chprot : integer := 3; + incaddr : integer := 0); + port ( + rst : in std_ulogic; + clk : in std_ulogic; + dmai : in ahb_dma_in_type; + dmao : out ahb_dma_out_type; + ahbi : in ahb_mst_in_type; + ahbo : out ahb_mst_out_type + ); +end; + +architecture rtl of ahbmst is + +constant hconfig : ahb_config_type := ( + 0 => ahb_device_reg ( venid, devid, 0, version, 0), + others => zero32); + +type reg_type is record + start : std_ulogic; + retry : std_ulogic; + grant : std_ulogic; + active : std_ulogic; +end record; + +signal r, rin : reg_type; + +begin + + comb : process(ahbi, dmai, rst, r) + variable v : reg_type; + variable ready : std_ulogic; + variable retry : std_ulogic; + variable mexc : std_ulogic; + variable inc : std_logic_vector(3 downto 0); -- address increment + + variable haddr : std_logic_vector(31 downto 0); -- AHB address + variable hwdata : std_logic_vector(31 downto 0); -- AHB write data + variable htrans : std_logic_vector(1 downto 0); -- transfer type + variable hwrite : std_ulogic; -- read/write + variable hburst : std_logic_vector(2 downto 0); -- burst type + variable newaddr : std_logic_vector(9 downto 0); -- next sequential address + variable hbusreq : std_ulogic; -- bus request + variable hprot : std_logic_vector(3 downto 0); -- transfer type + variable xhirq : std_logic_vector(NAHBIRQ-1 downto 0); + begin + + v := r; ready := '0'; mexc := '0'; retry := '0'; inc := (others => '0'); + hprot := conv_std_logic_vector(chprot, 4); -- non-cached supervisor data + xhirq := (others => '0'); xhirq(hirq) := dmai.irq; + + haddr := dmai.address; hbusreq := dmai.start; hwdata := dmai.wdata; + newaddr := dmai.address(9 downto 0); + + if INCADDR > 0 then + inc(conv_integer(dmai.size)) := '1'; + newaddr := haddr(9 downto 0) + inc; + end if; + + if dmai.burst = '0' then hburst := HBURST_SINGLE; + else hburst := HBURST_INCR; end if; + if dmai.start = '1' then + if (r.active and dmai.burst and not r.retry) = '1' then + haddr(9 downto 0) := newaddr; + if dmai.busy = '1' then htrans := HTRANS_BUSY; + else htrans := HTRANS_SEQ; end if; + hburst := HBURST_INCR; + else htrans := HTRANS_NONSEQ; end if; + else htrans := HTRANS_IDLE; end if; + + if r.active = '1' then + if ahbi.hready = '1' then + case ahbi.hresp is + when HRESP_OKAY => ready := '1'; + when HRESP_RETRY | HRESP_SPLIT=> retry := '1'; + when others => ready := '1'; mexc := '1'; + end case; + end if; + if ((ahbi.hresp = HRESP_RETRY) or (ahbi.hresp = HRESP_SPLIT)) then + v.retry := not ahbi.hready; + else v.retry := '0'; end if; + end if; + + if r.retry = '1' then htrans := HTRANS_IDLE; end if; + + v.start := '0'; + if ahbi.hready = '1' then + v.grant := ahbi.hgrant(hindex); + if (htrans = HTRANS_NONSEQ) or (htrans = HTRANS_SEQ) or (htrans = HTRANS_BUSY) then + v.active := r.grant; v.start := r.grant; + else + v.active := '0'; + end if; + end if; + + if rst = '0' then v.retry := '0'; v.active := '0'; end if; + + rin <= v; + + ahbo.haddr <= haddr; + ahbo.htrans <= htrans; + ahbo.hbusreq <= hbusreq; + ahbo.hwdata <= dmai.wdata; + ahbo.hconfig <= hconfig; + ahbo.hlock <= '0'; + ahbo.hwrite <= dmai.write; + ahbo.hsize <= '0' & dmai.size; + ahbo.hburst <= hburst; + ahbo.hprot <= hprot; + ahbo.hirq <= xhirq; + ahbo.hindex <= hindex; + + dmao.start <= r.start; + dmao.active <= r.active; + dmao.ready <= ready; + dmao.mexc <= mexc; + dmao.retry <= retry; + dmao.haddr <= newaddr; + dmao.rdata <= ahbi.hrdata; + + end process; + + regs : process(clk) + begin if rising_edge(clk) then r <= rin; end if; end process; + +end; diff --git a/gaisler/rtl/ahbuart.vhd b/gaisler/rtl/ahbuart.vhd new file mode 100644 index 0000000..3f72b26 --- /dev/null +++ b/gaisler/rtl/ahbuart.vhd @@ -0,0 +1,81 @@ +------------------------------------------------------------------------------ +-- This file is a part of the GRLIB VHDL IP LIBRARY +-- Copyright (C) 2003 - 2008, Gaisler Research +-- Copyright (C) 2008 - 2010, Aeroflex Gaisler +-- +-- 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: ahbuart +-- File: ahbuart.vhd +-- Author: Jiri Gaisler - Gaisler Research +-- Description: UART with AHB master interface +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; +library grlib; +use grlib.amba.all; +use grlib.stdlib.all; +use grlib.devices.all; +library gaisler; +use gaisler.misc.all; +use gaisler.uart.all; +use gaisler.libdcom.all; + +entity ahbuart is + generic ( + hindex : integer := 0; + pindex : integer := 0; + paddr : integer := 0; + pmask : integer := 16#fff# + ); + port ( + rst : in std_ulogic; + clk : in std_ulogic; + uarti : in uart_in_type; + uarto : out uart_out_type; + apbi : in apb_slv_in_type; + apbo : out apb_slv_out_type; + ahbi : in ahb_mst_in_type; + ahbo : out ahb_mst_out_type ); +end; + +architecture struct of ahbuart is + +constant REVISION : integer := 0; + +signal dmai : ahb_dma_in_type; +signal dmao : ahb_dma_out_type; +signal duarti : dcom_uart_in_type; +signal duarto : dcom_uart_out_type; + +begin + + ahbmst0 : ahbmst + generic map (hindex => hindex, venid => VENDOR_GAISLER, devid => GAISLER_AHBUART) + port map (rst, clk, dmai, dmao, ahbi, ahbo); + + dcom_uart0 : dcom_uart generic map (pindex, paddr, pmask) + port map (rst, clk, uarti, uarto, apbi, apbo, duarti, duarto); + + dcom0 : dcom port map (rst, clk, dmai, dmao, duarti, duarto, ahbi); + +-- pragma translate_off + bootmsg : report_version + generic map ("ahbuart" & tost(pindex) & + ": AHB Debug UART rev " & tost(REVISION)); +-- pragma translate_on + +end; diff --git a/gaisler/rtl/dcom.vhd b/gaisler/rtl/dcom.vhd new file mode 100644 index 0000000..12e46f8 --- /dev/null +++ b/gaisler/rtl/dcom.vhd @@ -0,0 +1,149 @@ +------------------------------------------------------------------------------ +-- This file is a part of the GRLIB VHDL IP LIBRARY +-- Copyright (C) 2003 - 2008, Gaisler Research +-- Copyright (C) 2008 - 2010, Aeroflex Gaisler +-- +-- 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: dcom +-- File: dcom.vhd +-- Author: Jiri Gaisler - Gaisler Research +-- Description: DSU Communications module +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; +library grlib; +use grlib.amba.all; +use grlib.stdlib.all; +library gaisler; +use gaisler.misc.all; +use gaisler.libdcom.all; + +entity dcom is + port ( + rst : in std_ulogic; + clk : in std_ulogic; + dmai : out ahb_dma_in_type; + dmao : in ahb_dma_out_type; + uarti : out dcom_uart_in_type; + uarto : in dcom_uart_out_type; + ahbi : in ahb_mst_in_type + ); +end; + +architecture struct of dcom is + +type dcom_state_type is (idle, addr1, read1, read2, write1, write2); + +type reg_type is record + addr : std_logic_vector(31 downto 0); + data : std_logic_vector(31 downto 0); + len : std_logic_vector(5 downto 0); + write : std_ulogic; + clen : std_logic_vector(1 downto 0); + state : dcom_state_type; + hresp : std_logic_vector(1 downto 0); +end record; + +signal r, rin : reg_type; + +begin + + comb : process(dmao, rst, uarto, ahbi, r) + variable v : reg_type; + variable enable : std_ulogic; + variable newlen : std_logic_vector(5 downto 0); + variable vuarti : dcom_uart_in_type; + variable vdmai : ahb_dma_in_type; + variable newaddr : std_logic_vector(31 downto 2); + + begin + + v := r; + vuarti.read := '0'; vuarti.write := '0'; vuarti.data := r.data(31 downto 24); + vdmai.start := '0'; vdmai.burst := '0'; vdmai.size := "10"; vdmai.busy := '0'; + vdmai.address := r.addr; vdmai.wdata := r.data; + vdmai.write := r.write; vdmai.irq := '0'; + + -- save hresp + if dmao.ready = '1' then v.hresp := ahbi.hresp; end if; + + -- address incrementer + newlen := r.len - 1; + newaddr := r.addr(31 downto 2) + 1; + + case r.state is + when idle => -- idle state + v.clen := "00"; + if uarto.dready = '1' then + if uarto.data(7) = '1' then v.state := addr1; end if; + v.write := uarto.data(6); v.len := uarto.data(5 downto 0); + vuarti.read := '1'; + end if; + when addr1 => -- receive address + if uarto.dready = '1' then + v.addr := r.addr(23 downto 0) & uarto.data; + vuarti.read := '1'; v.clen := r.clen + 1; + end if; + if (r.clen(1) and not v.clen(1)) = '1' then + if r.write = '1' then v.state := write1; else v.state := read1; end if; + end if; + when read1 => -- read AHB + if dmao.active = '1' then + if dmao.ready = '1' then + v.data := dmao.rdata; v.state := read2; + end if; + else vdmai.start := '1'; end if; + v.clen := "00"; + when read2 => -- send read-data on uart + if uarto.thempty = '1' then + v.data := r.data(23 downto 0) & uarto.data; + vuarti.write := '1'; v.clen := r.clen + 1; + if (r.clen(1) and not v.clen(1)) = '1' then + v.addr(31 downto 2) := newaddr; v.len := newlen; + if (v.len(5) and not r.len(5)) = '1' then v.state := idle; + else v.state := read1; end if; + end if; + end if; + when write1 => -- receive write-data + if uarto.dready = '1' then + v.data := r.data(23 downto 0) & uarto.data; + vuarti.read := '1'; v.clen := r.clen + 1; + end if; + if (r.clen(1) and not v.clen(1)) = '1' then v.state := write2; end if; + when write2 => -- write AHB + if dmao.active = '1' then + if dmao.ready = '1' then + v.addr(31 downto 2) := newaddr; v.len := newlen; + if (v.len(5) and not r.len(5)) = '1' then v.state := idle; + else v.state := write1; end if; + end if; + else vdmai.start := '1'; end if; + v.clen := "00"; + end case; + + if (uarto.lock and rst) = '0' then + v.state := idle; v.write := '0'; + end if; + + rin <= v; dmai <= vdmai; uarti <= vuarti; + + end process; + + regs : process(clk) + begin if rising_edge(clk) then r <= rin; end if; end process; + +end; diff --git a/gaisler/rtl/dcom_uart.vhd b/gaisler/rtl/dcom_uart.vhd new file mode 100644 index 0000000..7df6a78 --- /dev/null +++ b/gaisler/rtl/dcom_uart.vhd @@ -0,0 +1,325 @@ +------------------------------------------------------------------------------ +-- This file is a part of the GRLIB VHDL IP LIBRARY +-- Copyright (C) 2003 - 2008, Gaisler Research +-- Copyright (C) 2008 - 2010, Aeroflex Gaisler +-- +-- 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: dcom_uart +-- File: dcom_uart.vhd +-- Author: Jiri Gaisler - Gaisler Research +-- Description: Asynchronous UART with baud-rate detection. +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; +library grlib; +use grlib.amba.all; +use grlib.stdlib.all; +use grlib.devices.all; +library gaisler; +use gaisler.libdcom.all; +use gaisler.uart.all; +--pragma translate_off +use std.textio.all; +--pragma translate_on + +entity dcom_uart is + generic ( + pindex : integer := 0; + paddr : integer := 0; + pmask : integer := 16#fff# + ); + port ( + rst : in std_ulogic; + clk : in std_ulogic; + ui : in uart_in_type; + uo : out uart_out_type; + apbi : in apb_slv_in_type; + apbo : out apb_slv_out_type; + uarti : in dcom_uart_in_type; + uarto : out dcom_uart_out_type + ); +end; + +architecture rtl of dcom_uart is + +constant REVISION : integer := 0; + +constant pconfig : apb_config_type := ( + 0 => ahb_device_reg ( VENDOR_GAISLER, GAISLER_AHBUART, 0, REVISION, 0), + 1 => apb_iobar(paddr, pmask)); + +type rxfsmtype is (idle, startbit, data, stopbit); +type txfsmtype is (idle, data, stopbit); + +type uartregs is record + rxen : std_ulogic; -- receiver enabled + dready : std_ulogic; -- data ready + rsempty : std_ulogic; -- receiver shift register empty (internal) + tsempty : std_ulogic; -- transmitter shift register empty + thempty : std_ulogic; -- transmitter hold register empty + break : std_ulogic; -- break detected + ovf : std_ulogic; -- receiver overflow + frame : std_ulogic; -- framing error + rhold : std_logic_vector(7 downto 0); + rshift : std_logic_vector(7 downto 0); + tshift : std_logic_vector(10 downto 0); + thold : std_logic_vector(7 downto 0); + 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 data filtering buffer + rxtick : std_ulogic; -- rx clock (internal) + tick : std_ulogic; -- rx clock (internal) + scaler : std_logic_vector(17 downto 0); + brate : std_logic_vector(17 downto 0); + tcnt : std_logic_vector(1 downto 0); -- autobaud counter + rxf : std_logic_vector(4 downto 0); -- rx data filtering buffer + fedge : std_ulogic; -- rx falling edge +end record; + +signal r, rin : uartregs; + +begin + + uartop : process(rst, r, apbi, uarti, ui ) + variable rdata : std_logic_vector(31 downto 0); + variable scaler : std_logic_vector(17 downto 0); + variable rxclk, txclk : std_logic_vector(2 downto 0); + variable irxd : std_ulogic; + variable v : uartregs; + + begin + + v := r; + v.txtick := '0'; v.rxtick := '0'; v.tick := '0'; rdata := (others => '0'); + v.rxdb(1) := r.rxdb(0); + +-- scaler + + if r.tcnt = "11" then scaler := r.scaler - 1; + else scaler := r.scaler + 1; end if; + + if r.tcnt /= "11" then + if (r.rxdb(1) and not r.rxdb(0)) = '1' then v.fedge := '1'; end if; + if (r.fedge) = '1' then + v.scaler := scaler; + if (v.scaler(17) and not r.scaler(16)) = '1' then + v.scaler := "111111111111111011"; + v.fedge := '0'; v.tcnt := "00"; + end if; + end if; + if (r.rxdb(1) and r.fedge and not r.rxdb(0)) = '1' then + if (r.brate(17 downto 4)> r.scaler(17 downto 4)) then + v.brate := r.scaler; v.tcnt := "00"; + end if; + v.scaler := "111111111111111011"; + if (r.brate(17 downto 4) = r.scaler(17 downto 4)) then + v.tcnt := r.tcnt + 1; + if r.tcnt = "10" then + v.brate := "0000" & r.scaler(17 downto 4); + v.scaler := v.brate; v.rxen := '1'; + end if; + end if; + end if; + else + if (r.break and r.rxdb(1)) = '1' then + v.scaler := "111111111111111011"; + v.brate := (others => '1'); v.tcnt := "00"; + v.break := '0'; v.rxen := '0'; + end if; + end if; + + if r.rxen = '1' then + v.scaler := scaler; + v.tick := scaler(15) and not r.scaler(15); + if v.tick = '1' then v.scaler := r.brate; end if; + end if; + +-- read/write registers + + if uarti.read = '1' then v.dready := '0'; end if; + + case apbi.paddr(3 downto 2) is + when "01" => + rdata(9 downto 0) := r.tcnt & r.rxdb(0) & r.frame & '0' & r.ovf & + r.break & r.thempty & r.tsempty & r.dready; + when "10" => + rdata(1 downto 0) := (r.tcnt(1) or r.tcnt(0)) & r.rxen; + when others => + rdata(17 downto 0) := r.brate; + end case; + + if (apbi.psel(pindex) and apbi.penable and apbi.pwrite) = '1' then + case apbi.paddr(3 downto 2) is + when "01" => + v.frame := apbi.pwdata(6); + v.ovf := apbi.pwdata(4); + v.break := apbi.pwdata(3); + when "10" => + v.tcnt := apbi.pwdata(1) & apbi.pwdata(1); + v.rxen := apbi.pwdata(0); + when "11" => + v.brate := apbi.pwdata(17 downto 0); + v.scaler := apbi.pwdata(17 downto 0); + when others => + end case; + end if; + +-- tx clock + + txclk := r.txclk + 1; + if r.tick = '1' then + v.txclk := txclk; v.txtick := r.txclk(2) and not txclk(2); + end if; + +-- rx clock + + rxclk := r.rxclk + 1; + if r.tick = '1' then + v.rxclk := rxclk; v.rxtick := r.rxclk(2) and not rxclk(2); + end if; + +-- filter rx data + + v.rxf(1 downto 0) := r.rxf(0) & ui.rxd; -- meta-stability filter + if ((r.tcnt /= "11") and (r.scaler(0 downto 0) = "1")) or + ((r.tcnt = "11") and (r.tick = '1')) + then v.rxf(4 downto 2) := r.rxf(3 downto 1); end if; + v.rxdb(0) := (r.rxf(4) and r.rxf(3)) or (r.rxf(4) and r.rxf(2)) or + (r.rxf(3) and r.rxf(2)); + irxd := r.rxdb(0); + +-- transmitter operation + + case r.txstate is + when idle => -- idle state + if (r.txtick = '1') then v.tsempty := '1'; end if; + if (r.rxen and (not r.thempty) and r.txtick) = '1' then + v.tshift := "10" & r.thold & '0'; v.txstate := data; + v.thempty := '1'; + v.tsempty := '0'; v.txclk := "00" & r.tick; v.txtick := '0'; + end if; + when data => -- transmitt data frame + if r.txtick = '1' then + v.tshift := '1' & r.tshift(10 downto 1); + if r.tshift(10 downto 1) = "1111111110" then + v.tshift(0) := '1'; v.txstate := stopbit; + end if; + end if; + when stopbit => -- transmitt stop bit + if r.txtick = '1' then + v.tshift := '1' & r.tshift(10 downto 1); v.txstate := idle; + end if; + + end case; + +-- writing of tx data register must be done after tx fsm to get correct +-- operation of thempty flag + + if uarti.write = '1' then + v.thold := uarti.data(7 downto 0); v.thempty := '0'; + end if; + +-- receiver operation + + case r.rxstate is + when idle => -- wait for start bit + if ((not r.rsempty) and not r.dready) = '1' then + v.rhold := r.rshift; v.rsempty := '1'; v.dready := '1'; + end if; + if (r.rxen and r.rxdb(1) and (not irxd)) = '1' then + v.rxstate := startbit; v.rshift := (others => '1'); v.rxclk := "100"; + if v.rsempty = '0' then v.ovf := '1'; end if; + v.rsempty := '0'; v.rxtick := '0'; + end if; + when startbit => -- check validity of start bit + if r.rxtick = '1' then + if irxd = '0' then + v.rshift := irxd & r.rshift(7 downto 1); v.rxstate := data; + else + v.rxstate := idle; + end if; + end if; + when data => -- receive data frame + if r.rxtick = '1' then + v.rshift := irxd & r.rshift(7 downto 1); + if r.rshift(0) = '0' then + v.rxstate := stopbit; + end if; + end if; + when stopbit => -- receive stop bit + if r.rxtick = '1' then + if irxd = '1' then + v.rsempty := '0'; + if v.dready = '0' then + v.rhold := r.rshift; v.rsempty := '1'; v.dready := '1'; + end if; + else + if r.rshift = "00000000" then + v.break := '1'; -- break + else + v.frame := '1'; -- framing error + end if; + v.rsempty := '1'; + end if; + v.rxstate := idle; + end if; + + end case; + +-- reset operation + + if rst = '0' then + v.frame := '0'; v.rsempty := '1'; + v.ovf := '0'; v.break := '0'; v.thempty := '1'; + v.tsempty := '1'; v.dready := '0'; v.fedge := '0'; + v.txstate := idle; v.rxstate := idle; v.tshift(0) := '1'; + v.scaler := "111111111111111011"; v.brate := (others => '1'); + v.rxen := '0'; v.tcnt := "00"; + v.txclk := (others => '0'); v.rxclk := (others => '0'); + end if; + +-- update registers + + rin <= v; + +-- drive outputs + uo.txd <= r.tshift(0); + uo.scaler <= r.brate; + uo.rtsn <= '0'; + uo.rxen <= andv(r.tcnt); + uarto.dready <= r.dready; + uarto.tsempty <= r.tsempty; + uarto.thempty <= r.thempty; + uarto.lock <= r.tcnt(1) and r.tcnt(0); + uarto.enable <= r.rxen; + uarto.data <= r.rhold; + + apbo.prdata <= rdata; + + end process; + + apbo.pirq <= (others => '0'); + apbo.pconfig <= pconfig; + apbo.pindex <= pindex; + + regs : process(clk) + begin if rising_edge(clk) then r <= rin; end if; end process; + +end; diff --git a/gaisler/rtl/libdcom.vhd b/gaisler/rtl/libdcom.vhd new file mode 100644 index 0000000..64838ba --- /dev/null +++ b/gaisler/rtl/libdcom.vhd @@ -0,0 +1,171 @@ +------------------------------------------------------------------------------ +-- This file is a part of the GRLIB VHDL IP LIBRARY +-- Copyright (C) 2003 - 2008, Gaisler Research +-- Copyright (C) 2008 - 2010, Aeroflex Gaisler +-- +-- 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 +----------------------------------------------------------------------------- +-- Package: libdcom +-- File: libdcom.vhd +-- Author: Jiri Gaisler - Gaisler Research +-- Description: Types, functions and components for DSU uart +----------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +library grlib; +use grlib.amba.all; +use grlib.stdlib.all; +library gaisler; +use gaisler.uart.all; +use gaisler.misc.all; + +package libdcom is + +type dcom_uart_in_type is record + read : std_ulogic; + write : std_ulogic; + data : std_logic_vector(7 downto 0); +end record; + +type dcom_uart_out_type is record + dready : std_ulogic; + tsempty : std_ulogic; + thempty : std_ulogic; + lock : std_ulogic; + enable : std_ulogic; + data : std_logic_vector(7 downto 0); +end record; + +component dcom_uart + generic ( + pindex : integer := 0; + paddr : integer := 0; + pmask : integer := 16#fff# + ); + port ( + rst : in std_ulogic; + clk : in std_ulogic; + ui : in uart_in_type; + uo : out uart_out_type; + apbi : in apb_slv_in_type; + apbo : out apb_slv_out_type; + uarti : in dcom_uart_in_type; + uarto : out dcom_uart_out_type + ); +end component; + +component dcom + port ( + rst : in std_ulogic; + clk : in std_ulogic; + dmai : out ahb_dma_in_type; + dmao : in ahb_dma_out_type; + uarti : out dcom_uart_in_type; + uarto : in dcom_uart_out_type; + ahbi : in ahb_mst_in_type + ); +end component; + + +-- pragma translate_off + + procedure rxc(signal rxd : in std_logic; d: out std_logic_vector; + txperiod : time); + + procedure rxi(signal rxd : in std_logic; d: out std_logic_vector; + txperiod : time; lresp : boolean); + + procedure txc(signal txd : out std_logic; td : integer; + txperiod : time); + + procedure txa(signal txd : out std_logic; td1, td2, td3, td4 : integer; + txperiod : time); + + procedure txi(signal rxd : in std_logic; signal txd : out std_logic; + td1, td2, td3, td4 : integer; txperiod : time; + lresp : boolean); + +-- pragma translate_on + +end; + +-- pragma translate_off + +package body libdcom is + + procedure rxc(signal rxd : in std_logic; d: out std_logic_vector; + txperiod : time) is + variable rxdata : std_logic_vector(7 downto 0); + begin + wait until rxd = '0'; wait for TXPERIOD/2; + for i in 0 to 7 loop wait for TXPERIOD; rxdata(i):= rxd; end loop; + wait for TXPERIOD ; + d := rxdata; + end; + + procedure rxi(signal rxd : in std_logic; d: out std_logic_vector; + txperiod : time; lresp : boolean) is + variable rxdata : std_logic_vector(31 downto 0); + variable resp : std_logic_vector(7 downto 0); + begin + for i in 3 downto 0 loop + rxc(rxd, rxdata((i*8 +7) downto i*8), txperiod); + end loop; + d := rxdata; + if LRESP then + rxc(rxd, resp, txperiod); +-- print("RESP : 0x" & tosth(resp)); + end if; + end; + + procedure txc(signal txd : out std_logic; td : integer; + txperiod : time) is + variable txdata : std_logic_vector(10 downto 0); + begin + txdata := "11" & conv_std_logic_vector(td, 8) & '0'; + for i in 0 to 10 loop wait for TXPERIOD ; txd <= txdata(i); end loop; + end; + + procedure txa(signal txd : out std_logic; td1, td2, td3, td4 : integer; + txperiod : time) is + variable txdata : std_logic_vector(43 downto 0); + begin + txdata := "11" & conv_std_logic_vector(td4, 8) & '0' + & "11" & conv_std_logic_vector(td3, 8) & '0' + & "11" & conv_std_logic_vector(td2, 8) & '0' + & "11" & conv_std_logic_vector(td1, 8) & '0'; + for i in 0 to 43 loop wait for TXPERIOD ; txd <= txdata(i); end loop; + end; + + procedure txi(signal rxd : in std_logic; signal txd : out std_logic; + td1, td2, td3, td4 : integer; txperiod : time; + lresp : boolean) is + variable txdata : std_logic_vector(43 downto 0); + begin + txdata := "11" & conv_std_logic_vector(td4, 8) & '0' + & "11" & conv_std_logic_vector(td3, 8) & '0' + & "11" & conv_std_logic_vector(td2, 8) & '0' + & "11" & conv_std_logic_vector(td1, 8) & '0'; + for i in 0 to 43 loop wait for TXPERIOD ; txd <= txdata(i); end loop; + if LRESP then + rxc(rxd, txdata(7 downto 0), txperiod); +-- print("RESP : 0x" & tosth(txdata(7 downto 0))); + end if; + end; + +end; + +-- pragma translate_on |