From 623639aa823346b8340d51ce1a9e7fc21ecb0882 Mon Sep 17 00:00:00 2001 From: "Walter F.J. Mueller" Date: Mon, 17 Apr 2017 20:56:28 +0200 Subject: [PATCH] add DEUNA device (xu) for ibus --- rtl/ibus/ibdr_deuna.vbom | 6 + rtl/ibus/ibdr_deuna.vhd | 349 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 355 insertions(+) create mode 100644 rtl/ibus/ibdr_deuna.vbom create mode 100644 rtl/ibus/ibdr_deuna.vhd diff --git a/rtl/ibus/ibdr_deuna.vbom b/rtl/ibus/ibdr_deuna.vbom new file mode 100644 index 00000000..88e38e19 --- /dev/null +++ b/rtl/ibus/ibdr_deuna.vbom @@ -0,0 +1,6 @@ +# libs +../vlib/slvtypes.vhd +iblib.vhd +# components +# design +ibdr_deuna.vhd diff --git a/rtl/ibus/ibdr_deuna.vhd b/rtl/ibus/ibdr_deuna.vhd new file mode 100644 index 00000000..a154cac2 --- /dev/null +++ b/rtl/ibus/ibdr_deuna.vhd @@ -0,0 +1,349 @@ +-- $Id: ibdr_deuna.vhd 874 2017-04-14 17:53:07Z mueller $ +-- +-- Copyright 2014-2017 by Walter F.J. Mueller +-- +-- 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 2, 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: ibdr_deuna - syn +-- Description: ibus dev(rem): DEUNA +-- +-- Dependencies: - +-- Test bench: - +-- Target Devices: generic +-- Tool versions: ise 14.7; viv 2016.4; ghdl 0.33 +-- +-- Synthesized (xst): +-- Date Rev ise Target flop lutl lutm slic t peri +-- 2017-04-14 874 14.7 131013 xc6slx16-2 50 79 0 40 s 4.1 +-- 2017-01-29 847 14.7 131013 xc6slx16-2 42 70 0 36 s 4.1 +-- +-- Revision History: +-- Date Rev Version Comment +-- 2017-04-14 875 1.0 Initial version +-- 2014-06-09 561 0.1 First draft +------------------------------------------------------------------------------ + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use work.slvtypes.all; +use work.iblib.all; + +-- ---------------------------------------------------------------------------- +entity ibdr_deuna is -- ibus dev(rem): DEUNA + -- fixed address: 174510 + port ( + CLK : in slbit; -- clock + BRESET : in slbit; -- ibus reset + RB_LAM : out slbit; -- remote attention + IB_MREQ : in ib_mreq_type; -- ibus request + IB_SRES : out ib_sres_type; -- ibus response + EI_REQ : out slbit; -- interrupt request + EI_ACK : in slbit -- interrupt acknowledge + ); +end ibdr_deuna; + +architecture syn of ibdr_deuna is + + constant ibaddr_deuna : slv16 := slv(to_unsigned(8#174510#,16)); + + constant ibaddr_pr0 : slv2 := "00"; -- pcsr0 address offset + constant ibaddr_pr1 : slv2 := "01"; -- pcsr1 address offset + constant ibaddr_pr2 : slv2 := "10"; -- pcsr2 address offset + constant ibaddr_pr3 : slv2 := "11"; -- pcsr3 address offset + + constant pr0_ibf_seri : integer := 15; + constant pr0_ibf_pcei : integer := 14; + constant pr0_ibf_rxi : integer := 13; + constant pr0_ibf_txi : integer := 12; + constant pr0_ibf_dni : integer := 11; + constant pr0_ibf_rcbi : integer := 10; + constant pr0_ibf_usci : integer := 8; + constant pr0_ibf_intr : integer := 7; + constant pr0_ibf_inte : integer := 6; + constant pr0_ibf_rset : integer := 5; + subtype pr0_ibf_pcmd is integer range 3 downto 0; + -- additional rem view assignments + subtype pr0_ibf_pcmdbp is integer range 15 downto 12; + constant pr0_ibf_busy : integer := 9; + constant pr0_ibf_pcwwb : integer := 8; + constant pr0_ibf_brst : integer := 4; + + constant pcmd_noop : slv4 := "0000"; -- pcmd: noop (DNI not set !) + + constant pr1_ibf_xpwr : integer := 15; + constant pr1_ibf_icab : integer := 14; + subtype pr1_ibf_ecod is integer range 13 downto 8; + constant pr1_ibf_pcto : integer := 7; + constant pr1_ibf_deuna : integer := 4; -- id bit 0 (0=DEUNA;1=DELUA) + subtype pr1_ibf_state is integer range 3 downto 0; + + constant state_reset : slv4 := "0000"; -- state: reset + constant state_ready : slv4 := "0010"; -- state: ready + + type regs_type is record -- state registers + ibsel : slbit; -- ibus select + pr0seri : slbit; -- pr0: status error intr + pr0pcei : slbit; -- pr0: port command error intr + pr0rxi : slbit; -- pr0: receive ring intr + pr0txi : slbit; -- pr0: transmit ring intr + pr0dni : slbit; -- pr0: done interrupt + pr0rcbi : slbit; -- pr0: receive buffer unavail intr + pr0usci : slbit; -- pr0: unsolicited state change intr + pr0intr : slbit; -- pr0: intr summary + pr0inte : slbit; -- pr0: intr enable + pr0rset : slbit; -- pr0: software reset + pr0brst : slbit; -- pr0: BRESET reset + pr0pcmd : slv4; -- pr0: port command + pr1xpwr : slbit; -- pr1: transmitter power fail + pr1icab : slbit; -- pr1: port/link cabling fail + pr1pcto : slbit; -- pr1: port command time out + pr1deuna : slbit; -- pr1: bit 0 of ID (0=DEUNA;1=DELUA) + pr1state : slv4; -- pr1: port status + pcbb : slv18_1; -- pr2+3: port conrol block base + busy : slbit; -- busy + pcmdwwb : slbit; -- pcmd written while busy + pcmdbp : slv4; -- pcmd busy protected + resreq : slbit; -- reset requested + ireq : slbit; -- interrupt request flag + end record regs_type; + + constant regs_init : regs_type := ( + '0', -- ibsel + '0','0','0','0', -- pr0seri,pr0pcei,pr0rxi,pr0txi + '0','0','0', -- pr0dni,pr0rcbi,pr0usci + '0','0', -- pr0intr,pr0inte + '0','0', -- pr0rset,pr0brst + (others=>'0'), -- pr0pcmd + '1','1', -- pr1xpwr,pr1icab + '0','0', -- pr1pcto,pr1deuna + state_reset, -- pr1state + (others=>'0'), -- pcbb + '0','0', -- busy,pcmdwwb + (others=>'0'), -- pcmdbp + '0', -- resreq + '0' -- ireq + ); + + signal R_REGS : regs_type := regs_init; + signal N_REGS : regs_type := regs_init; + +begin + + proc_regs: process (CLK) + begin + if rising_edge(CLK) then + R_REGS <= N_REGS; + end if; + end process proc_regs; + + proc_next : process (R_REGS, IB_MREQ, EI_ACK, BRESET) + variable r : regs_type := regs_init; + variable n : regs_type := regs_init; + variable ibhold : slbit := '0'; + variable idout : slv16 := (others=>'0'); + variable ibrem : slbit := '0'; + variable ibreq : slbit := '0'; + variable ibrd : slbit := '0'; + variable ibw0 : slbit := '0'; + variable ibw1 : slbit := '0'; + variable ibwrem : slbit := '0'; + variable ilam : slbit := '0'; + + begin + + r := R_REGS; + n := R_REGS; + + ibhold := '0'; + idout := (others=>'0'); + ibrem := IB_MREQ.racc; + ibreq := IB_MREQ.re or IB_MREQ.we; + ibrd := IB_MREQ.re; + ibw0 := IB_MREQ.we and IB_MREQ.be0; + ibw1 := IB_MREQ.we and IB_MREQ.be1; + ibwrem := IB_MREQ.we and ibrem; + ilam := '0'; + + -- ibus address decoder + n.ibsel := '0'; + if IB_MREQ.aval = '1' and + IB_MREQ.addr(12 downto 3)=ibaddr_deuna(12 downto 3) then + n.ibsel := '1'; + end if; + + -- ibus transactions + + if r.ibsel='1' then -- selected + + case IB_MREQ.addr(2 downto 1) is + + when ibaddr_pr0 => -- PCSR0 - intr and pcmd ----------- + if ibrem = '0' then -- loc view of upper byte + idout(pr0_ibf_seri) := r.pr0seri; + idout(pr0_ibf_pcei) := r.pr0pcei; + idout(pr0_ibf_rxi) := r.pr0rxi; + idout(pr0_ibf_txi) := r.pr0txi; + idout(pr0_ibf_dni) := r.pr0dni; + idout(pr0_ibf_rcbi) := r.pr0rcbi; + idout(pr0_ibf_usci) := r.pr0usci; + else -- rem view of upper byte + idout(pr0_ibf_pcmdbp) := r.pcmdbp; + idout(pr0_ibf_busy) := r.busy; + idout(pr0_ibf_pcwwb) := r.pcmdwwb; + end if; + idout(pr0_ibf_intr) := r.pr0intr; + idout(pr0_ibf_inte) := r.pr0inte; + if ibrem = '1' then + idout(pr0_ibf_rset) := r.pr0rset; -- only seen from rem side + idout(pr0_ibf_brst) := r.pr0brst; -- only seen from rem side + end if; + idout(pr0_ibf_pcmd) := r.pr0pcmd; + + if IB_MREQ.we = '1' then + if ibrem = '1' then -- rem write + if IB_MREQ.din(pr0_ibf_seri) = '1' then n.pr0seri := '1'; end if; + if IB_MREQ.din(pr0_ibf_pcei) = '1' then n.pr0pcei := '1'; end if; + if IB_MREQ.din(pr0_ibf_rxi) = '1' then n.pr0rxi := '1'; end if; + if IB_MREQ.din(pr0_ibf_txi) = '1' then n.pr0txi := '1'; end if; + if IB_MREQ.din(pr0_ibf_dni) = '1' then n.pr0dni := '1'; end if; + if IB_MREQ.din(pr0_ibf_rcbi) = '1' then n.pr0rcbi := '1'; end if; + if IB_MREQ.din(pr0_ibf_usci) = '1' then n.pr0usci := '1'; end if; + if IB_MREQ.din(pr0_ibf_rset) = '1' then n.pr0rset := '0'; end if; + if IB_MREQ.din(pr0_ibf_brst) = '1' then n.pr0brst := '0'; end if; + if IB_MREQ.din(pr0_ibf_dni) = '1' or + IB_MREQ.din(pr0_ibf_pcei) = '1' or + IB_MREQ.din(pr0_ibf_busy) = '1' or + IB_MREQ.din(pr0_ibf_rset) = '1' or + IB_MREQ.din(pr0_ibf_brst) = '1' then + n.busy := '0'; + end if; + else -- loc write + if IB_MREQ.be1 = '1' then + if IB_MREQ.din(pr0_ibf_seri) = '1' then n.pr0seri := '0'; end if; + if IB_MREQ.din(pr0_ibf_pcei) = '1' then n.pr0pcei := '0'; end if; + if IB_MREQ.din(pr0_ibf_rxi) = '1' then n.pr0rxi := '0'; end if; + if IB_MREQ.din(pr0_ibf_txi) = '1' then n.pr0txi := '0'; end if; + if IB_MREQ.din(pr0_ibf_dni) = '1' then n.pr0dni := '0'; end if; + if IB_MREQ.din(pr0_ibf_rcbi) = '1' then n.pr0rcbi := '0'; end if; + if IB_MREQ.din(pr0_ibf_usci) = '1' then n.pr0usci := '0'; end if; + end if; + if IB_MREQ.be0 = '1' then + if IB_MREQ.din(pr0_ibf_rset) = '1' then -- RESET requested ? + n.resreq := '1'; + n.pr0rset := '1'; + elsif IB_MREQ.din(pr0_ibf_inte) /= r.pr0inte then -- INTE change? + n.pr0inte := IB_MREQ.din(pr0_ibf_inte); + n.pr0dni := '1'; + elsif r.pr1state /= state_reset then -- not in reset + n.pr0pcmd := IB_MREQ.din(pr0_ibf_pcmd); + if r.busy = '0' then -- if not busy execute + n.pcmdbp := IB_MREQ.din(pr0_ibf_pcmd); + if IB_MREQ.din(pr0_ibf_pcmd) /= pcmd_noop then + n.busy := '1'; -- signal busy + ilam := '1'; -- rri lam + end if; + else -- if busy set pcmdwwf flag + n.pcmdwwb := '1'; + end if; + end if; + end if; -- if IB_MREQ.be0 = '1' + end if; -- else ibrem = '1' + end if; -- if IB_MREQ.we = '1' + + if IB_MREQ.re = '1' and ibrem = '1' then -- for rem pr0 reads + n.pcmdwwb := '0'; -- clear pcmdwwb + end if; + + when ibaddr_pr1 => -- PCSR1 - status ------------------ + idout(pr1_ibf_xpwr) := r.pr1xpwr; + idout(pr1_ibf_icab) := r.pr1icab; + idout(pr1_ibf_pcto) := r.pr1pcto; + idout(pr1_ibf_deuna) := r.pr1deuna; + idout(pr1_ibf_state) := r.pr1state; + if IB_MREQ.we = '1' then + if ibrem = '1' then + n.pr1xpwr := IB_MREQ.din(pr1_ibf_xpwr); + n.pr1icab := IB_MREQ.din(pr1_ibf_icab); + n.pr1pcto := IB_MREQ.din(pr1_ibf_pcto); + n.pr1deuna := IB_MREQ.din(pr1_ibf_deuna); + n.pr1state := IB_MREQ.din(pr1_ibf_state); + end if; + end if; + + when ibaddr_pr2 => -- PCSR2 - pcbb low order ---------- + idout(15 downto 1) := r.pcbb(15 downto 1); + if IB_MREQ.we = '1' then + n.pcbb(15 downto 1) := IB_MREQ.din(15 downto 1); + end if; + + when ibaddr_pr3 => -- PCSR2 - pcbb high order --------- + idout( 1 downto 0) := r.pcbb(17 downto 16); + if IB_MREQ.we = '1' then + n.pcbb(17 downto 16) := IB_MREQ.din( 1 downto 0); + end if; + + when others => null; + + end case; + end if; + + if BRESET = '1' then + n.resreq := '1'; + n.pr0brst := '1'; + end if; + + if r.resreq = '1' then + n.pr0seri := '0'; + n.pr0pcei := '0'; + n.pr0rxi := '0'; + n.pr0txi := '0'; + n.pr0dni := '0'; + n.pr0rcbi := '0'; + n.pr0usci := '0'; + n.pr1pcto := '0'; + n.pr0inte := '0'; + n.pr1state := state_reset; + n.pcbb := (others => '0'); + n.resreq := '0'; + -- send lam on soft or bus reset only when not in state_reset + -- the startup default is state_reset, so without active backend + -- this device will not send lam's on bus resets + if r.pr1state /= state_reset then + n.busy := '1'; -- signal busy + ilam := '1'; -- rri lam unless reset handling pending + end if; + + end if; + + n.pr0intr := r.pr0seri or r.pr0pcei or r.pr0rxi or r.pr0txi or + r.pr0dni or r.pr0rcbi or r.pr0usci; + + if r.pr0inte = '1' then + n.ireq := r.pr0intr; + else + n.ireq := '0'; + end if; + + N_REGS <= n; + + IB_SRES.dout <= idout; + IB_SRES.ack <= r.ibsel and ibreq; + IB_SRES.busy <= ibhold and ibreq; + + RB_LAM <= ilam; + EI_REQ <= r.ireq; + + end process proc_next; + + +end syn;