OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [processor/] [VHDL/] [ext_modules/] [ext_miniUART/] [ext_miniUART.vhd] - Rev 3

Compare with Previous | Blame | View Log

-----------------------------------------------------------------------
-- This file is part of SCARTS.
-- 
-- SCARTS 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 3 of the License, or
-- (at your option) any later version.
-- 
-- SCARTS 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 SCARTS.  If not, see <http://www.gnu.org/licenses/>.
-----------------------------------------------------------------------
 
 
-------------------------------------------------------------------------------
-- Title      : Extension Module: miniUART
-- Project    : HW/SW-Codesign
-------------------------------------------------------------------------------
-- File       : ext_miniUART.vhd
-- Author     : Roman Seiger
-- Company    : TU Wien - Institut für Technische Informatik
-- Created    : 2005-03-10
-- Last update: 2007-05-17
-------------------------------------------------------------------------------
 
-- TODO: Herstellernummer
 
----------------------------------------------------------------------------------
-- LIBRARY
----------------------------------------------------------------------------------
LIBRARY IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.numeric_std.all;
USE work.pkg_basic.all;
use work.pkg_miniUART.all;
 
----------------------------------------------------------------------------------
-- ARCHITECTURE
----------------------------------------------------------------------------------
ARCHITECTURE behaviour OF ext_miniUART IS
 
------------------------------------------------------------------------------
-- Definition der Constanten für Module Type und versionsnummer
-------------------------------------------------------------------------------
-- ID für miniUART definieren
  constant MOD_TYPE     : std_logic_vector(15 downto 0):="0000000100000001";
  constant MOD_VERSION  : std_logic_vector(15 downto 0):="0000000000000000";
 
 
-------------------------------------------------------------------------------
-- Definieren eines Types "ext_register_set" : Array vom 8 Registern die
-- jeweils 16 Bit breit sind => Register der Module Interfaces
-------------------------------------------------------------------------------  
  subtype ext_register is std_logic_vector(7 downto 0);
  type    ext_register_set is array (0 to 9) of ext_register;
  signal  ExtReg,ExtReg_next         : ext_register_set;
 
-------------------------------------------------------------------------------
--  Interne Signale, siehe Programm-Code 
-------------------------------------------------------------------------------    
  signal ExtReset                        : std_logic;  -- reset oder SRes
--  signal Ena                             : std_logic;  -- Modul angesprochen
  signal IntAckClrNxt                    : std_logic;
  --signal WriteDataNxt                    : std_logic_vector(DATA_W-1 downto 0);
  -- ganzes Statusregister überschreiben!
--  signal StatusNxt                       : std_logic_vector((DATA_W/2)-1 downto 0);
  signal StatusNxt                       : std_logic_vector(DATA_W-1 downto 0);
--  signal MsgNxt                          : std_logic_vector(DATA_W-1 downto 0);
--  signal CmdNxt                          : std_logic_vector(DATA_W-1 downto 0);
  signal UBRS                            : std_logic_vector(DATA_W-1 downto 0);
 
--  signal parity : std_logic;            -- für Parityberechnung
  signal newmessage : std_logic;        -- neue Nachricht ins Messageregister geschrieben?
  signal messageread : std_logic;       -- empfangene Nachricht abgeholt?
  signal statusread : std_logic;        -- Status gelesen? (für Eventflag)
  signal old_statusread : std_logic;
 
  --signal MINIUART_BADDR                  : std_logic_vector(DATA_W-1 downto 3);
 
-------------------------------------------------------------------------------
-- Verbindungssignale
-------------------------------------------------------------------------------
  -- Transmitter
  signal ParBit : std_logic;            -- berechnetes Paritybit für Transmitter
 
  -- Busdriver
  signal OutD : std_logic;              -- Output disable
 
  -- UARTCtrl
  signal ParErr : std_logic;          -- Parity Error
  signal FrameErr : std_logic;        -- Frame Error (Transmission Error)
  signal Data_r : Data_type;            -- empfangene Daten
  signal RBR : std_logic;               -- Receive Buffer Ready
  signal TBR : std_logic;               -- Transmit Buffer Ready
  signal event : std_logic;             -- event occured?
 
  -- UARTCtrl <=> receiver
  signal Data_r2c : Data_type;  
  signal Data_c2t : Data_type;
  signal ParBit_r2c : std_logic;
  signal FrameErr_r2c : std_logic;
  signal RecComp_r2c : std_logic;
  signal RecBusy_r2c : std_logic;
  signal EnaRec_c2r : std_logic;
 
  -- UARTCtrl <=> transmitter
  signal TransComp_t2c : std_logic;
 
  -- UARTcontrol <=> BRG
  signal StartTrans_c2brg : std_logic;
 
  -- transmitter <=> BRG
  signal tp_brg2t : std_logic;
 
  -- transmitter <=> busdriver
  signal TransEna_t2bd : std_logic;
  signal TxD_t2bd : std_logic;
 
  -- receiver <=> BRG
  signal rp_brg2r : std_logic;
  signal StartRecPulse_r2brg : std_logic;
 
  -- receiver <=> busdriver
  signal RecEna_r2bd : std_logic;
  signal RxD_bd2r : std_logic;
 
-------------------------------------------------------------------------------
-- begin architecture
-------------------------------------------------------------------------------
  begin  -- behaviour
 
-------------------------------------------------------------------------------
-- Port mapping der Komponenten
-------------------------------------------------------------------------------
    -- miniUART_control
    miniUART_control_unit : miniUART_control
      port map (
        clk => clk,
        reset => ExtReset,
        ParEna => ExtReg(EXTUARTCONF)(EXTCONF_PARENA),
        Odd => ExtReg(EXTUARTCONF)(EXTCONF_PARODD),
        AsA => ExtReg(EXTCMD)(EXTCMD_ASA_H downto EXTCMD_ASA_L),
        EvS => ExtReg(EXTCMD)(EXTCMD_EVS_H downto EXTCMD_EVS_L),
        Data_r => Data_r2c,
        ParBit_r => ParBit_r2c,
        FrameErr => FrameErr_r2c,
        RecComp => RecComp_r2c,
        RecBusy => RecBusy_r2c,
        TransComp => TransComp_t2c,
        EnaRec => EnaRec_c2r,
        Data_r_out => Data_r,
        FrameErr_out => FrameErr,
        ParityErr => ParErr,
        RBR => RBR,
        StartTrans => StartTrans_c2brg,
        TBR => TBR,
        event => event
        );
 
		Data_c2t(7 downto 0) <= ExtReg(MSGREG_LOW);
		Data_c2t(15 downto 8) <= ExtReg(MSGREG_HIGH);
 
    -- miniUART_transmitter
    miniUART_transmitter_unit : miniUART_transmitter
      port map (
        clk => clk,
        reset => ExtReset,
        MsgLength => ExtReg(EXTUARTCONF)(EXTCONF_MSGL_H downto EXTCONF_MSGL_L),
        Stop2 => ExtReg(EXTUARTCONF)(EXTCONF_STOP),
        ParEna => ExtReg(EXTUARTCONF)(EXTCONF_PARENA),
        ParBit => ParBit,
        Data => Data_c2t,
        tp => tp_brg2t,
        TransEna => TransEna_t2bd,
        TrComp => TransComp_t2c,
        TxD => TxD_t2bd
        );
 
    -- miniUART_receiver
    miniUART_receiver_unit : miniUART_receiver
      port map (
        clk => clk,
		reset => ExtReset,
        enable => EnaRec_c2r,
        MsgLength => ExtReg(EXTUARTCONF)(EXTCONF_MSGL_H downto EXTCONF_MSGL_L),
        Stop2 => ExtReg(EXTUARTCONF)(EXTCONF_STOP),
        ParEna => ExtReg(EXTUARTCONF)(EXTCONF_PARENA),
        rp => rp_brg2r,
        RxD => RxD_bd2r,
        Data => Data_r2c,
        ParBit => ParBit_r2c,
        RecEna => RecEna_r2bd,
        StartRecPulse => StartRecPulse_r2brg,
        busy => RecBusy_r2c,
        RecComplete => RecComp_r2c,
        FrameErr => FrameErr_r2c
        );
 
     UBRS(7 downto 0)  <= ExtReg(UBRSREG_LOW);
     UBRS(15 downto 8) <= ExtReg(UBRSREG_HIGH);
 
    -- miniUART_BRG
    miniUART_BRG_unit : miniUART_BRG
      port map (
        clk => clk, 
		reset => ExtReset,
        StartTrans => StartTrans_c2brg,
        StartRec => StartRecPulse_r2brg,
        UBRS => UBRS,--ExtReg(UBRSREG),
        tp => tp_brg2t,
        rp => rp_brg2r
        );
 
 
    -- miniUART_busdriver
    miniUART_busdriver_unit : miniUART_busdriver
      port map (
        clk => clk, 
		reset => ExtReset,
        OutD => OutD,
        TransEna => TransEna_t2bd,
        RecEna => RecEna_r2bd,
        Data_t => TxD_t2bd,
        Data_r => RxD_bd2r,
        TxD => TxD,
        RxD => RxD
        );
 
 
-------------------------------------------------------------------------------
-- Synchroner Prozess:
-- Bei einem Reset werden alle Register mit Null initialisiert.
-- Anschliessend werden mit jeder steigenden Flanke die neuen Werte in das
-- Register geschrieben.
-- Zu beachten ist dabei die Reigenfolge: StatusNxt wird
-- als letztes zugewiesen - daher wird in jedem Fall das Status Register mit
-- diesem Wert beschreiben, auch wenn man von aussen versucht  dieses zu
-- überschreiben  -> read-only Funktion  (nur die unteren 8 Bits). Beim
-- Config-Register ist es genau umgekehrt - dadurch kann man das INTA-Bit vom
-- Prozessor aus überschreiben..
-------------------------------------------------------------------------------        
    SYNC_SM: process (clk, ExtReset)
    begin  
 
      if ExtReset = RST_ACT then
        for i in 0 to 9 loop
          ExtReg(i) <= (others => '0');
        end loop;  -- i
        old_statusread <= '0';
      elsif clk'event and clk = '1' then    
        ExtReg <= ExtReg_next;
 
        ExtReg(STATUSREG) <= StatusNxt(7 downto 0);
        ExtReg(STATUSREG_CUST) <= StatusNxt(15 downto 8);
        old_statusread <= statusread;
 
      end if;
    end process SYNC_SM;
 
 
 
 
-------------------------------------------------------------------------------
-- Schreiben in die Register:
-- Defaultmässig wird der ältere Wert beibehalten
------------------------------------------------------------------------------- 
    WRITE_REG: process (exti, ExtReg, RBR, TBR,  Data_r, extsel, IntAckClrNxt)--(ExtAddr, Data2Ext, ExtWr, Ena, ExtReg) --DE, AccViol)
    begin
 
      -- Defaultwert
      ExtReg_next <= ExtReg;
      ExtReg_next(CONFIGREG)(CONF_INTA)  <= IntAckClrNxt;      
      --WriteDataNxt <=  ExtReg(conv_integer(unsigned(exti.ExtAddr)));
      newmessage <= '0';
      if RBR = RB_READY then
        ExtReg_next(MSGREG_LOW)   <= Data_r(7 downto 0);       -- empfangene Nachricht übernehmen
        ExtReg_next(MSGREG_HIGH) <= Data_r(15 downto 8);
      end if;
 
      if TBR = TB_READY then
        if ExtReg(EXTCMD)(EXTCMD_ASA_H downto EXTCMD_ASA_L) = ASA_STRANS then
             ExtReg_next(EXTCMD)(EXTCMD_ASA_H downto EXTCMD_ASA_L) <= "000"; 
        end if;
      end if;
 
 
      -- neue Daten übernehmen
      if ((extsel = '1') and (exti.write_en = '1')) then
        case exti.addr(4 downto 2) is
          when "000" =>
            if ((exti.byte_en(0) = '1')) then
              ExtReg_next(2) <= exti.data(7 downto 0);
            end if;
            if ((exti.byte_en(1) = '1')) then
              ExtReg_next(3) <= exti.data(15 downto 8);
            end if;
            if ((exti.byte_en(2) = '1')) then
              ExtReg_next(2) <= exti.data(23 downto 16);
            end if;
            if ((exti.byte_en(3) = '1')) then
              ExtReg_next(3) <= exti.data(31 downto 24);
            end if;
          when "001" =>
            if ((exti.byte_en(0) = '1')) then
              ExtReg_next(4) <= exti.data(7 downto 0);
            end if;
            if ((exti.byte_en(1) = '1')) then
              ExtReg_next(5) <= exti.data(15 downto 8);
            end if;
            if ((exti.byte_en(2) = '1')) then
              ExtReg_next(6) <= exti.data(23 downto 16);
              newmessage <= '1';
            end if;
            if ((exti.byte_en(3) = '1')) then
              ExtReg_next(7) <= exti.data(31 downto 24);
            end if;
          when "010" =>
            if ((exti.byte_en(0) = '1')) then
              ExtReg_next(8) <= exti.data(7 downto 0);
            end if;
            if ((exti.byte_en(1) = '1')) then
              ExtReg_next(9) <= exti.data(15 downto 8);
            end if;
          when others =>
            null;
        end case;
      end if;
    end process WRITE_REG;
 
-------------------------------------------------------------------------------
-- Lesezugriff auf das Extension Module
-- Wenn das ID-Bit im Config Register gesetzt ist, so wird auf Data 0/1 der
-- Module Type und die Versionsnummer ausgegeben
-- Bei einem Interrupt wird auf DATA0 der Interruptvector ausgegeben
-------------------------------------------------------------------------------
    READ_REG: process (exti, ExtReg, extsel) --DE AccViol)
    begin
      --Defaultwert (Hochohmig)-> neue Konvention, Default auf 0
--      WrBData <= (others => 'Z');
      exto.data <= (others => '0');
 
      messageread <= '0';
      statusread <= '0';
 
      -- Lesezugriff auf das Module? (ohne Access Violation (AccViol))
      if ((extsel = '1') and (exti.write_en = '0')) then
        case exti.addr(4 downto 2) is
          when "000" =>
              if ((exti.byte_en(0) = '1')) then
                statusread <= '1';
              end if;
            exto.data<= ExtReg(3) & ExtReg(2) & ExtReg(1) & ExtReg(0);
          when "001" =>
            if (ExtReg(CONFIGREG)(CONF_ID) = '1') then
              exto.data<= MODULE_VER & MODULE_ID;
            else
              if ((exti.byte_en(2) = '1')) then
                messageread <= '1';
              end if;
              exto.data<= ExtReg(7) & ExtReg(6) & ExtReg(5) & ExtReg(4);
            end if;
          when "010" =>
            exto.data<= "00000000" & "00000000" & ExtReg(9) & ExtReg(8);
          when others =>
            null;
        end case;
      end if;
    end process READ_REG;
 
 
-------------------------------------------------------------------------------
-- Setzen der Status-Bits
-------------------------------------------------------------------------------    
    STATUS_EXT: process(ExtReg, RBR, TBR, ParErr, FrameErr, --Data_r,
                        newmessage, messageread, statusread, event, old_statusread)
    begin
      -- Defaultwerte
     -- MsgNxt(7 downto 0) <= ExtReg(MSGREG_LOW);   
	--  MsgNxt(15 downto 8) <= ExtReg(MSGREG_HIGH);
    --  CmdNxt(7 downto 0) <= ExtReg(EXTCMD);
  --    CmdNxt(15 downto 8) <= (others =>'0');
 
      StatusNxt(STA_LOOR) <= ExtReg(CONFIGREG)(CONF_LOOW);
      StatusNxt(STA_FSS)  <= ExtReg(STATUSREG)(STA_FSS);      -- Failsafestate
      StatusNxt(STA_RESH) <= '0';                               --not used
      StatusNxt(STA_RESL) <= '0';                               --not used
      StatusNxt(STA_BUSY) <= '0';      -- miniUART is never too busy!
      StatusNxt(STA_ERR)  <= ExtReg(STATUSREG)(STA_ERR);  -- Error occured
      StatusNxt(STA_RDY)  <= '1';                               --not used
      StatusNxt(STA_INT)  <= ExtReg(STATUSREG)(STA_INT); 
      IntAckClrNxt         <= ExtReg(CONFIGREG)(CONF_INTA);
 
      StatusNxt(15)          <= '0';    -- not used
      StatusNxt(STA_TRANSERR +8) <= ExtReg(STATUSREG_CUST)(STA_TRANSERR); -- Transmission Error (Frame Error)
      StatusNxt(STA_PARERR+8)   <= ExtReg(STATUSREG_CUST)(STA_PARERR); -- Parity Error
      StatusNxt(STA_EVF+8)      <= ExtReg(STATUSREG_CUST)(STA_EVF);    -- EventFlag
      StatusNxt(STA_OVF+8)      <= ExtReg(STATUSREG_CUST)(STA_OVF);    -- OverflowFlag
      StatusNxt(STA_RBR+8)      <= ExtReg(STATUSREG_CUST)(STA_RBR);     -- Receive Buffer Ready
      StatusNxt(STA_TBR+8)      <= ExtReg(STATUSREG_CUST)(STA_TBR);    -- Transmit Buffer Ready
      StatusNxt(8)           <= '0';    -- not used
 
      -- Nachricht empfangen
      if RBR = RB_READY then
        StatusNxt(STA_RBR+8) <= RB_READY;
        -- Overflow?
        if ExtReg(STATUSREG_CUST)(STA_RBR) = RB_READY then
          StatusNxt(STA_OVF) <= OVERFLOW;
        end if;
        -- übernehmen
   --     MsgNxt <= Data_r;
        -- Parity bzw. Transmission (Frame) Error (nur wenn TrCtrl oder ERRI)
        if (ExtReg(EXTUARTCONF)(EXTCONF_TRCTRL) = TRCTRL_ENA) or (ExtReg(EXTCMD)(EXTCMD_ERRI) = TRCTRL_ENA) then
          StatusNxt(STA_PARERR+8) <= ParErr;
          StatusNxt(STA_TRANSERR +8) <= FrameErr;
          if (ParErr = PARITY_ERROR) or (FrameErr = FRAME_ERROR) then
            StatusNxt(STA_ERR) <= '1';
          end if;
          -- Interrupt auslösen?
          if (ExtReg(EXTCMD)(EXTCMD_ERRI) = TRCTRL_ENA) and ((ParErr = PARITY_ERROR) or (FrameErr = FRAME_ERROR)) then
            StatusNxt(STA_INT) <= '1';
            IntAckClrNxt <= '0';            
          end if;
        end if;
      elsif messageread = '1' then
        -- clear receive flags
        StatusNxt(STA_RBR+8) <= not RB_READY;
        StatusNxt(STA_OVF+8) <= not OVERFLOW;
        StatusNxt(STA_PARERR+8) <= not PARITY_ERROR;
        StatusNxt(STA_TRANSERR+8) <= not FRAME_ERROR;
        StatusNxt(STA_ERR) <= '0';
      end if;
 
      -- Nachricht wird gesendet, TBR für eine Taktperiode auf high => signal
-- ist irreführend, es zeigt legilich an, dass mit dem Senden der Nachricht
-- begonnen wurde, nicht dass sie erfolgreich übertragen wurde. 
      if TBR = TB_READY then
        StatusNxt(STA_TBR+8) <= TB_READY;
        -- erneutes Senden verhindern!
       -- if ExtReg(EXTCMD)(EXTCMD_ASA_H downto EXTCMD_ASA_L) = ASA_STRANS then
       --   CmdNxt(EXTCMD_ASA_H downto EXTCMD_ASA_L) <= "000"; 
       -- end if;
      elsif newmessage = '1' then
        -- clear TBR
        StatusNxt(STA_TBR+8) <= not TB_READY;        
      end if;
 
      -- Event
      if event = EV_OCC then
        StatusNxt(STA_EVF+8) <= EV_OCC;
        -- Interrupt auslösen
        if ExtReg(EXTCMD)(EXTCMD_EI) = EV_INT then
          StatusNxt(STA_INT) <= '1';
          IntAckClrNxt <= '0';                      
        end if;
      elsif (old_statusread = '1') and (statusread = '0') then
        StatusNxt(STA_EVF+8) <= not EV_OCC;
      end if;
 
      -- Failsafestate
      if ExtReg(CONFIGREG)(CONF_EFSS) = FAILSAFE then
        StatusNxt(STA_FSS) <= '1';
        StatusNxt(STA_INT) <= '1';
        IntAckClrNxt <= '0';
      else
        StatusNxt(STA_FSS) <= '0';       
      end if;
 
      -- Interruptstatus (bei Acknowledge abdrehen)
      if ExtReg(CONFIGREG)(CONF_INTA) = '1' then
        StatusNxt(STA_INT)  <= '0';
        IntAckClrNxt        <= '0';
      end if;
 
    end process STATUS_EXT;
 
 
-------------------------------------------------------------------------------
-- Ein Reset kann durch ein externes Signal oder durch setzen eines Bits im
-- Config-Register ausgelöst werden.
-------------------------------------------------------------------------------
    RESET_EXT: process (exti, ExtReg)
    begin
      -- Defaultwert
      ExtReset <= not RST_ACT;
      if exti.reset = RST_ACT or ExtReg(CONFIGREG)(CONF_SRES)= '1' then
        ExtReset <= RST_ACT;
      end if;
    end process RESET_EXT;
 
 
 
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-- Module Specific Part
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
 
-------------------------------------------------------------------------------
-- Parity berechnen
-------------------------------------------------------------------------------    
    PARITY_CALC: process (ExtReg)
--      variable i : integer;
      variable parity : std_logic;
    begin  -- process PARITY_CALC
      parity := '0';
      for i in 15 downto 0 loop
        if to_integer(unsigned(ExtReg(EXTUARTCONF)(EXTCONF_MSGL_H downto EXTCONF_MSGL_L))) < i then
          parity := parity;
        else
		  if i < 8 then
          	parity := parity xor ExtReg(MSGREG_LOW)(i);
		  else  	
			parity := parity xor ExtReg(MSGREG_HIGH)(i-8);
          end if;
		end if;
      end loop;
 
      -- Odd oder even?
      ParBit <= parity xor ExtReg(EXTUARTCONF)(EXTCONF_PARODD);    
    end process PARITY_CALC;
 
-------------------------------------------------------------------------------
-- Output disable (explizit oder im FSS)
-------------------------------------------------------------------------------    
    OUTPUT_CONTROL: process (ExtReg)
    begin  -- process FSS_CONTROL
      if (ExtReg(STATUSREG)(STA_FSS) = '1') or (ExtReg(CONFIGREG)(EXTCONF_OUTD) = OUTD_ACT) then
        OutD <= OUTD_ACT;
      else
        OutD <= not OUTD_ACT;
      end if;
    end process OUTPUT_CONTROL;
 
 
-------------------------------------------------------------------------------
-- Interrupt request
-------------------------------------------------------------------------------    
 
   INT_CONTROL: process (ExtReg)
   begin  -- process INT_CONTROL
     if ExtReg(STATUSREG)(STA_INT) = '1' then
       exto.intreq <= '1';--EXC_ACT;
     else
       exto.intreq <= '0';--not EXC_ACT;
     end if;
   end process INT_CONTROL;
 
end behaviour;
 
----------------------------------------------------------------------------------
-- END ARCHITECTURE
----------------------------------------------------------------------------------
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.