URL
https://opencores.org/ocsvn/scarts/scarts/trunk
Subversion Repositories scarts
[/] [scarts/] [trunk/] [processor/] [VHDL/] [scarts_core/] [rs232.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: 2011-03-16 ------------------------------------------------------------------------------- -- TODO: Herstellernummer ---------------------------------------------------------------------------------- -- LIBRARY ---------------------------------------------------------------------------------- LIBRARY IEEE; USE IEEE.std_logic_1164.all; USE IEEE.numeric_std.all; use work.scarts_core_pkg.all; use work.scarts_pkg.all; ---------------------------------------------------------------------------------- -- ENTITY ---------------------------------------------------------------------------------- ENTITY ext_miniUART IS PORT( --------------------------------------------------------------- -- Generic Ports --------------------------------------------------------------- clk : IN std_logic; extsel : in std_logic; exti : in module_in_type; exto : out module_out_type; --------------------------------------------------------------- -- Module Specific Ports --------------------------------------------------------------- RxD : IN std_logic; -- Empfangsleitung TxD : OUT std_logic ); END ext_miniUART; ---------------------------------------------------------------------------------- -- 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 ---------------------------------------------------------------------------------- LIBRARY IEEE; USE IEEE.std_logic_1164.all; USE IEEE.std_logic_arith.all; use IEEE.std_logic_UNSIGNED.all; use work.scarts_core_pkg.all; use work.scarts_pkg.all; ---------------------------------------------------------------------------------- -- ENTITY ---------------------------------------------------------------------------------- entity miniUART_BRG is port ( clk : in std_logic; reset : in std_logic; StartTrans : in std_logic; -- Transmitterpulse eingeschaltet? StartRec : in std_logic; -- Receiverpulse eingeschaltet? UBRS : in std_logic_vector(15 downto 0); -- Baud Rate Selection Register -- (12 bit ganzzahlig, 4 bit fraction) tp : out std_logic; -- Transmitterpulse rp : out std_logic -- Receiverpulse ); end miniUART_BRG; ---------------------------------------------------------------------------------- -- ARCHITECTURE ---------------------------------------------------------------------------------- architecture behaviour of miniUART_BRG is -- Zählerbreite (11bit aus UBRS + 1bit Überlaufschutz) constant COUNTERWIDTH : integer := 12; -- Zählerkonstanten constant COUNTER_ZERO : std_logic_vector(COUNTERWIDTH-1 downto 0) := (0 => '1', others => '0'); -- Überlaufregisterbreite (4bit aus UBRS + 1bit Überlauf) constant OVERFLOWWIDTH : integer := 6; -- interne Signale zur Zwischenspeicherung der Eingänge signal UBRS_i, UBRS_nxt : std_logic_vector(16 downto 0); -- Zähler signal counter : std_logic_vector(COUNTERWIDTH-1 downto 0); signal next_counter : std_logic_vector(COUNTERWIDTH-1 downto 0); -- Überlaufregister signal overflow : std_logic_vector(OVERFLOWWIDTH-1 downto 0); signal next_overflow : std_logic_vector(OVERFLOWWIDTH-1 downto 0); -- Transmitpulse oder Receivepulse? signal pulse_toggle : std_logic; signal next_pulse_toggle : std_logic; begin -- behaviour BRG_COUNTER: process (clk, reset) begin -- process BRG_COUNTER -- ausgeschaltet, entspricht reset if reset = RST_ACT then counter <= COUNTER_ZERO; overflow(4 downto 0) <= (others => '0');-- UBRS(4 downto 0); overflow(OVERFLOWWIDTH-1) <= '0'; UBRS_i(16) <= '0'; UBRS_i(15 downto 0) <= (others => '1'); --UBRS; -- UBRS übernehmen pulse_toggle <= '0'; -- Transmitter zuerst! -- in Betrieb, runterzählen elsif (clk'event and clk = '1') then counter <= next_counter; overflow <= next_overflow; UBRS_i <= UBRS_nxt; pulse_toggle <= next_pulse_toggle; end if; end process BRG_COUNTER; BRG_CALC_NEXT: process (counter, overflow, UBRS_i, UBRS, StartTrans, StartRec, pulse_toggle) begin -- process BRG_CALC_NEXT -- Defaultwerte tp <= '0'; rp <= '0'; UBRS_nxt <= UBRS_i; -- counter weiterzählen next_counter <= counter - '1'; next_overflow <= overflow; -- pulse_toggle halten next_pulse_toggle <= pulse_toggle; if (StartTrans /= BRG_ON) and (StartRec /= BRG_ON) then next_counter <= COUNTER_ZERO; next_overflow(4 downto 0) <= UBRS(4 downto 0); next_overflow(OVERFLOWWIDTH-1) <= '0'; next_pulse_toggle <= '0'; UBRS_nxt(16) <= '0'; UBRS_nxt(15 downto 0) <= UBRS; -- counter zurücksetzen, neues overflow berechnen elsif counter = COUNTER_ZERO then next_counter <= UBRS_i(16 downto 5) + overflow(5); next_overflow <= (overflow and "011111") + UBRS_i(4 downto 0); -- Pulses ausgeben tp <= (not pulse_toggle) and StartTrans; rp <= pulse_toggle and StartRec; next_pulse_toggle <= not pulse_toggle; end if; end process BRG_CALC_NEXT; end behaviour; ---------------------------------------------------------------------------------- -- LIBRARY ---------------------------------------------------------------------------------- LIBRARY IEEE; USE IEEE.std_logic_1164.all; USE IEEE.std_logic_arith.all; use work.scarts_core_pkg.all; use work.scarts_pkg.all; ---------------------------------------------------------------------------------- -- ENTITY ---------------------------------------------------------------------------------- entity miniUART_busdriver is port ( clk : in std_logic; reset : in std_logic; OutD : in std_logic; -- Output disable TransEna : in std_logic; -- Einschalten, von Transmitter RecEna : in std_logic; -- Einschalten, von Receiver Data_t : in std_logic; -- zu sendendes Bit Data_r : out std_logic; -- empfangenes Bit TxD : out std_logic; -- Sendeleitung RxD : in std_logic -- Empfangsleitung ); end miniUART_busdriver; ---------------------------------------------------------------------------------- -- ARCHITECTURE ---------------------------------------------------------------------------------- architecture behaviour of miniUART_busdriver is signal Data_r_nxt : std_logic; signal Data_r_int : std_logic; -- Zwischenpuffer, um Spitzen auszugleichen signal buffer1, buffer1_nxt : std_logic; signal buffer2, buffer2_nxt : std_logic; signal buffer3, buffer3_nxt : std_logic; begin -- behaviour BUSDRIVER_BUFFER: process (clk, reset) begin -- process BUSDRIVER_BUFFER if reset = RST_ACT then buffer1 <= '1'; buffer2 <= '1'; buffer3 <= '1'; Data_r_int <= '1'; -- Zwischenpuffer der Reihe nach füllen elsif (clk'event and clk = '1') then buffer1 <= buffer1_nxt; buffer2 <= buffer2_nxt; buffer3 <= buffer3_nxt; Data_r_int <= Data_r_nxt; end if; end process BUSDRIVER_BUFFER; BUSDRIVER_FILTER: process (RecEna, buffer1, buffer2, buffer3, Data_r_int, RxD) begin -- process BUSDRIVER_FILTER Data_r_nxt <= Data_r_int; if RecEna /= BUSDRIVER_ON then buffer1_nxt <= '1'; buffer2_nxt <= '1'; buffer3_nxt <= '1'; Data_r_nxt <= '1'; else buffer3_nxt <= buffer2; buffer2_nxt <= buffer1; buffer1_nxt <= RxD; end if; -- nur bei gleichen Bufferinhalten weitergeben! if (buffer3 = '1' and buffer2 = '1' and buffer1 = '1') then Data_r_nxt <= '1'; elsif (buffer3 = '0' and buffer2 = '0' and buffer1 = '0') then Data_r_nxt <= '0'; end if; end process BUSDRIVER_FILTER; BUSDRIVER_TRANS: process (TransEna, OutD, Data_t) begin -- process BUSDRIVER_TRANS if (TransEna = BUSDRIVER_ON) and (OutD /= OUTD_ACT) then -- TODO: OutD Konstante!!! TxD <= Data_t; else -- interne Signale zur synchronisation der Ausgänge -- TxD <= 'Z'; -- Tri-State TxD <= '1'; -- Point2Point end if; end process BUSDRIVER_TRANS; Data_r <= Data_r_int; end behaviour; ---------------------------------------------------------------------------------- -- LIBRARY ---------------------------------------------------------------------------------- LIBRARY IEEE; USE IEEE.std_logic_1164.all; USE IEEE.std_logic_arith.all; use work.scarts_core_pkg.all; USE work.scarts_pkg.all; ---------------------------------------------------------------------------------- -- ENTITY ---------------------------------------------------------------------------------- entity miniUART_control is port ( clk : in std_logic; reset : in std_logic; -- MsgLength : in MsgLength_type; ParEna : in std_logic; -- Parity? Odd : in std_logic; -- Odd or Even Parity? AsA : in std_logic_vector(2 downto 0); -- Assigned Action EvS : in std_logic_vector(1 downto 0); -- Event Selector Data_r : in Data_type; -- received Data ParBit_r : in std_logic; -- empfangenes Paritybit FrameErr : in std_logic; RecComp : in std_logic; -- Receive Complete RecBusy : in std_logic; -- Reciever Busy (Startbit detected) TransComp : in std_logic; -- Transmission complete EnaRec : out std_logic; -- Enable receiver Data_r_out : out Data_type; -- empfangene Daten FrameErr_out : out std_logic; ParityErr : out std_logic; RBR : out std_logic; -- Receive Buffer Ready (Rec Complete) StartTrans : out std_logic; -- Start Transmitter (halten bis TrComp!) TBR : out std_logic; -- Transmit Buffer Ready (MSGREG read, -- transmitter started) event : out std_logic -- Selected Event occured! ); end miniUART_control; ---------------------------------------------------------------------------------- -- ARCHITECTURE ---------------------------------------------------------------------------------- architecture behaviour of miniUART_control is -- interne Signale zur synchronisation der Ausgänge signal EnaRec_i : std_logic; signal StartTrans_i : std_logic; signal EnaRec_old : std_logic; signal StartTrans_old : std_logic; signal ParityErr_i : std_logic; signal TBR_i : std_logic; signal RBR_i : std_logic; -- in/out signal Data_r_i : Data_type; signal FrameErr_i : std_logic; -- interne Signale zur Zwischenspeicherung der Eingänge -- signal MsgLength_i : MsgLength_type; signal ParEna_i : std_logic; signal Odd_i : std_logic; signal ParBit_r_i : std_logic; signal old_TransComp : std_logic; signal old_RecBusy : std_logic; signal old_RecComp : std_logic; -- Events signal event_i : std_logic; begin -- behaviour -- empfangene Daten direkt übernehmen Data_r_i <= Data_r; ParBit_r_i <= ParBit_r; FrameErr_i <= FrameErr; ------------------------------------------------------------------------------- -- Control Synchronisierung ------------------------------------------------------------------------------- CTRL_SYNC: process (clk, reset) begin -- process CTRL_SYNC --reset, alles zurücksetzen if reset = RST_ACT then Data_r_out <= (others => '0'); FrameErr_out <= not FRAME_ERROR; ParityErr <= not PARITY_ERROR; EnaRec <= not RECEIVER_ENABLED; EnaRec_old <= not RECEIVER_ENABLED; StartTrans <= not BRG_ON; StartTrans_old <= not BRG_ON; event <= not EV_OCC; TBR <= TB_READY; -- neue Nachricht annehmen RBR <= not RB_READY; old_TransComp <= not TRANS_COMP; old_RecBusy <= not REC_BUSY; old_RecComp <= not REC_COMPLETE; -- MsgLength_i <= (others => '0'); ParEna_i <= not PARITY_ENABLE; Odd_i <= '0'; elsif clk'event and clk = '1' then -- Daten ausgeben Data_r_out <= Data_r_i; FrameErr_out <= FrameErr_i; ParityErr <= ParityErr_i; EnaRec <= EnaRec_i; StartTrans <= StartTrans_i; EnaRec_old <= EnaRec_i; StartTrans_old <= StartTrans_i; event <= event_i; TBR <= TBR_i; RBR <= RBR_i; -- Zustand merken (um Flanke zu erkennen!) old_TransComp <= TransComp; old_RecBusy <= RecBusy; old_RecComp <= RecComp; -- Daten merken -- MsgLength_i <= MsgLength_i; ParEna_i <= ParEna_i; Odd_i <= Odd_i; -- Daten übernehmen (beim Einschalten des Receivers) if (EnaRec_old /= RECEIVER_ENABLED) and (EnaRec_i = RECEIVER_ENABLED) then -- Aktuelle Daten übernehmen -- MsgLength_i <= MsgLength; ParEna_i <= ParEna; Odd_i <= Odd; end if; end if; end process CTRL_SYNC; ------------------------------------------------------------------------------- -- Control Logic ------------------------------------------------------------------------------- CTRL_LOGIC: process (EvS, AsA, StartTrans_old, EnaRec_old, TransComp, old_TransComp, RecComp, old_RecComp, RecBusy, old_RecBusy) -- ParEna, Odd, ParEna_i, Odd_i) begin -- process CTRL_LOGIC StartTrans_i <= StartTrans_old; EnaRec_i <= EnaRec_old; event_i <= not EV_OCC; TBR_i <= not TB_READY; RBR_i <= not RB_READY; -- TRANSMITTER -- Transmitter startet (TBR nur 1 clk halten!) if (old_TransComp = TRANS_COMP) and (TransComp /= TRANS_COMP) then TBR_i <= TB_READY; -- Transmission completed elsif (old_TransComp /= TRANS_COMP) and (TransComp = TRANS_COMP) then -- BRG und damit Transmitter ausschalten StartTrans_i <= not BRG_ON; -- Event signalisieren if EvS = EV_TCOMP then event_i <= EV_OCC; if AsA = ASA_STRANS then -- Transmitter starten StartTrans_i <= BRG_ON; elsif AsA = ASA_EREC then -- Receiver einschalten EnaRec_i <= RECEIVER_ENABLED; elsif AsA = ASA_DREC then -- Receiver ausschalten EnaRec_i <= not RECEIVER_ENABLED; end if; end if; end if; -- RECEIVER -- Startbit detected if (old_RecBusy /= REC_BUSY) and (RecBusy = REC_BUSY) then if EvS = EV_SBD then event_i <= EV_OCC; if AsA = ASA_DREC then -- Receiver ausschalten EnaRec_i <= not RECEIVER_ENABLED; elsif AsA = ASA_STRANS then -- Transmitter starten StartTrans_i <= BRG_ON; end if; end if; -- ganze Nachricht empfangen (RBR nur 1 clk halten!) elsif (old_RecComp /= REC_COMPLETE) and (RecComp = REC_COMPLETE) then RBR_i <= RB_READY; if EvS = EV_RCOMP then event_i <= EV_OCC; if AsA = ASA_DREC then -- Receiver ausschalten EnaRec_i <= not RECEIVER_ENABLED; elsif AsA = ASA_STRANS then -- Transmitter starten StartTrans_i <= BRG_ON; end if; end if; end if; -- NOEVENT if EvS = EV_NONE then if AsA = ASA_STRANS then -- Transmitter starten StartTrans_i <= BRG_ON; elsif AsA = ASA_EREC then -- Receiver einschalten EnaRec_i <= RECEIVER_ENABLED; elsif AsA = ASA_DREC then -- Receiver ausschalten EnaRec_i <= not RECEIVER_ENABLED; end if; end if; end process CTRL_LOGIC; ------------------------------------------------------------------------------- -- Parity ------------------------------------------------------------------------------- PARITY_CALC: process (Data_r_i, Odd_i, ParBit_r_i, ParEna_i) -- variable i : integer; variable parity : std_logic; begin -- process PARITY_CALC parity := '0'; -- for i in conv_Integer(unsigned(MsgLength_i)) downto 0 loop for i in 15 downto 0 loop parity := parity xor Data_r_i(i); end loop; -- Odd oder even? if ((parity xor Odd_i) /= ParBit_r_i) and (ParEna_i = PARITY_ENABLE) then ParityErr_i <= PARITY_ERROR; else ParityErr_i <= not PARITY_ERROR; end if; end process PARITY_CALC; end behaviour; ---------------------------------------------------------------------------------- -- LIBRARY ---------------------------------------------------------------------------------- LIBRARY IEEE; USE IEEE.std_logic_1164.all; USE IEEE.std_logic_arith.all; use IEEE.std_logic_UNSIGNED."+"; use work.scarts_core_pkg.all; use work.scarts_pkg.all; ---------------------------------------------------------------------------------- -- ENTITY ---------------------------------------------------------------------------------- entity miniUART_receiver is port ( clk : in std_logic; reset : in std_logic; enable : in std_logic; -- Receiver eingeschaltet? MsgLength : in MsgLength_type; Stop2 : in std_logic; -- Zweites Stopbit? ParEna : in std_logic; -- Parity? rp : in std_logic; -- Receivepulse vom BRG RxD : in std_logic; -- Empfangseingang Data : out Data_type; ParBit : out std_logic; -- Empfangenes Paritybit RecEna : out std_logic; -- Busdriver einschalten StartRecPulse : out std_logic; -- Receivepulse generieren busy : out std_logic; -- Receiving / Startbit detected RecComplete : out std_logic; -- komplettes Frame empfangen FrameErr : out std_logic ); end miniUART_receiver; ---------------------------------------------------------------------------------- -- ARCHITECTURE ---------------------------------------------------------------------------------- architecture behaviour of miniUART_receiver is -- max. 20 empfangene Bits (1+16+1+2); 20d = 10100b constant BITCOUNTERWIDTH : integer := 5; -- Bitnummern der Parity/Stopbits constant PARST1 : std_logic_vector(BITCOUNTERWIDTH-1 downto 0) := "10010"; constant ST1ST2 : std_logic_vector(BITCOUNTERWIDTH-1 downto 0) := "10011"; constant ST2 : std_logic_vector(BITCOUNTERWIDTH-1 downto 0) := "10100"; -- Definition der States type rec_states is (DISABLE_S, STARTBITDETECTION_S, RECEIVE_S); signal Rec_State : rec_states; signal next_Rec_State : rec_states; -- interne Signale zur synchronisation der Ausgänge signal ParBit_i : std_logic; signal ParBit_old : std_logic; signal ParEna_i : std_logic; signal Stop2_i : std_logic; signal RecEna_i : std_logic; signal busy_i : std_logic; signal StartRecPulse_i : std_logic; signal RecComplete_i : std_logic; signal FrameErr1_i : std_logic; signal FrameErr2_i : std_logic; signal FrameErr_int : std_logic; signal Data_i : Data_type; -- signal Data : Data_type; signal Data_nxt : Data_type; -- interne Signale zur Zwischenspeicherung der Eingänge -- signal RxD_i, RxD_i_nxt : std_logic; -- Bitzähler signal Bitcounter : std_logic_vector(BITCOUNTERWIDTH-1 downto 0); signal next_Bitcounter : std_logic_vector(BITCOUNTERWIDTH-1 downto 0); -- Nachrichtenlänge signal Length : std_logic_vector(3 downto 0); signal Length_nxt : std_logic_vector(3 downto 0); -- signal Length : integer; -- alter Empfangswert signal old_RxD : std_logic; -- alter Pulsewert -- signal old_rp : std_logic; begin -- behaviour Data <= Data_i; REC_STATECHANGE: process (clk, reset) begin -- process REC_STATECHANGE -- Receiver ausgeschalten, kommt einem reset gleich if reset = RST_ACT then RecEna <= not BUSDRIVER_ON; StartRecPulse <= not BRG_ON; busy <= not REC_BUSY; RecComplete <= not REC_COMPLETE; Bitcounter <= (others => '0'); Data_i <= (others => '0'); ParBit <= '0'; FrameErr_int <= not FRAME_ERROR; ParBit_old <= '0'; old_RxD <= '1'; Rec_State <= DISABLE_S; Length <= (others => '0'); -- Signale ausgeben, Statechange elsif (clk'event and clk = '1') then Bitcounter <= next_Bitcounter; RecEna <= RecEna_i; StartRecPulse <= StartRecPulse_i; busy <= busy_i; RecComplete <= RecComplete_i; ParBit <= ParBit_i; ParBit_old <= ParBit_i; FrameErr_int <= FrameErr1_i or FrameErr2_i; Data_i <= Data_nxt; -- Empfangszustand merken (um Flanke zu erkennen!) old_RxD <= RxD; Rec_State <= next_Rec_State; Length <= Length_nxt; end if; end process REC_STATECHANGE; REC_STATEMACHINE: process (enable, MsgLength, ParEna, Stop2, ParEna_i, Stop2_i, Length, Rec_State, Bitcounter, RxD, Data_i, ParBit_old, FrameErr_int, old_RxD, rp) begin -- process REC_STATEMACHINE -- Defaultwerte RecEna_i <= not BUSDRIVER_ON; StartRecPulse_i <= not BRG_ON; busy_i <= not REC_BUSY; RecComplete_i <= not REC_COMPLETE; next_Bitcounter <= Bitcounter; ParEna_i <= ParEna; Stop2_i <= Stop2; Data_nxt <= Data_i; ParBit_i <= ParBit_old; FrameErr1_i <= FrameErr_int; FrameErr2_i <= FrameErr_int; Length_nxt <= Length; case Rec_State is when DISABLE_S => Data_nxt <= (others => '0'); ParBit_i <= '0'; FrameErr1_i <= not FRAME_ERROR; FrameErr2_i <= not FRAME_ERROR; next_Rec_State <= DISABLE_S; next_Bitcounter <= (others => '0'); -- Receiver eingeschalten if enable = RECEIVER_ENABLED then Length_nxt <= MsgLength; -- Nachrichtenlänge ParEna_i <= ParEna; Stop2_i <= Stop2; RecEna_i <= BUSDRIVER_ON; next_Rec_State <= STARTBITDETECTION_S; end if; when STARTBITDETECTION_S => Data_nxt <= (others => '0'); ParBit_i <= '0'; FrameErr1_i <= '0'; FrameErr2_i <= '0'; RecEna_i <= BUSDRIVER_ON; -- Bustreiber einschalten next_Rec_State <= STARTBITDETECTION_S; next_Bitcounter <= (others => '0'); if (RxD = '0') and (old_RxD = '1') then -- Startbit empfangen! StartRecPulse_i <= BRG_ON; -- Receivepulse generieren busy_i <= REC_BUSY; -- working next_Bitcounter <= Bitcounter + '1'; next_Rec_State <= RECEIVE_S; end if; when RECEIVE_S => next_Rec_State <= RECEIVE_S; RecEna_i <= BUSDRIVER_ON; -- Bustreiber einschalten StartRecPulse_i <= BRG_ON; -- Receivepulse generieren busy_i <= REC_BUSY; -- Beschäftigt next_Bitcounter <= Bitcounter; if rp = '1' then -- RxD_i_nxt <= RxD; next_Bitcounter <= Bitcounter +1 ; -- end if; - -- next_Bitcounter <= Bitcounter + '1'; case Bitcounter is when "00000" => -- sollte nicht auftreten!!! assert false report "Wait on first Receceive Impuls -> Recieve Startbit" severity NOTE; when "00001" => -- Startbit null; -- Daten when "00010" => -- Bit 0 Data_nxt(0) <= RxD; if Length = "0000" then next_Bitcounter <= PARST1; end if; when "00011" => -- Bit 1 Data_nxt(1) <= RxD; if Length = "0001" then next_Bitcounter <= PARST1; end if; when "00100" => -- Bit 2 Data_nxt(2) <= RxD; if Length = "0010" then next_Bitcounter <= PARST1; end if; when "00101" => -- Bit 3 Data_nxt(3) <= RxD; if Length = "0011" then next_Bitcounter <= PARST1; end if; when "00110" => -- Bit 4 Data_nxt(4) <= RxD; if Length = "0100" then next_Bitcounter <= PARST1; end if; when "00111" => -- Bit 5 Data_nxt(5) <= RxD; if Length = "0101" then next_Bitcounter <= PARST1; end if; when "01000" => -- Bit 6 Data_nxt(6) <= RxD; if Length = "0110" then next_Bitcounter <= PARST1; end if; when "01001" => -- Bit 7 Data_nxt(7) <= RxD; if Length = "0111" then next_Bitcounter <= PARST1; end if; when "01010" => -- Bit 8 Data_nxt(8) <= RxD; if Length = "1000" then next_Bitcounter <= PARST1; end if; when "01011" => -- Bit 9 Data_nxt(9) <= RxD; if Length = "1001" then next_Bitcounter <= PARST1; end if; when "01100" => -- Bit 10 Data_nxt(10) <= RxD; if Length = "1010" then next_Bitcounter <= PARST1; end if; when "01101" => -- Bit 11 Data_nxt(11) <= RxD; if Length = "1011" then next_Bitcounter <= PARST1; end if; when "01110" => -- Bit 12 Data_nxt(12) <= RxD; if Length = "1100" then next_Bitcounter <= PARST1; end if; when "01111" => -- Bit 13 Data_nxt(13) <= RxD; if Length = "1101" then next_Bitcounter <= PARST1; end if; when "10000" => -- Bit 14 Data_nxt(14) <= RxD; if Length = "1110" then next_Bitcounter <= PARST1; end if; when "10001" => -- Bit 15 Data_nxt(15) <= RxD; if Length = "1111" then next_Bitcounter <= PARST1; end if; -- Paritybit when PARST1 => -- Parity oder 1. Stopbit if ParEna_i = PARITY_ENABLE then ParBit_i <= RxD; else FrameErr1_i <= not RxD; if Stop2_i /= SECOND_STOPBIT then next_Rec_State <= DISABLE_S; -- fertig RecComplete_i <= REC_COMPLETE; StartRecPulse_i <= not BRG_ON; next_Bitcounter <= (others => '0'); end if; end if; -- Stopbits when ST1ST2 => -- 1. oder 2. Stopbit FrameErr2_i <= not RxD; if (ParEna_i /= PARITY_ENABLE) or (Stop2_i /= SECOND_STOPBIT) then next_Rec_State <= DISABLE_S; -- fertig RecComplete_i <= REC_COMPLETE; StartRecPulse_i <= not BRG_ON; next_Bitcounter <= (others => '0'); end if; when ST2 => -- 2. Stopbit FrameErr1_i <= not RxD; -- fertig next_Rec_State <= DISABLE_S; -- fertig RecComplete_i <= REC_COMPLETE; StartRecPulse_i <= not BRG_ON; next_Bitcounter <= (others => '0'); when others => -- nicht erreicht! next_Rec_State <= DISABLE_S; RecComplete_i <= REC_COMPLETE; StartRecPulse_i <= not BRG_ON; next_Bitcounter <= (others => '0'); assert false report "Bitcounter overrun (miniUART_receiver.vhd)!!!" severity ERROR; end case; end if; when others => --DISABLE_S next_Rec_State <= DISABLE_S; end case; end process REC_STATEMACHINE; FrameErr <= FrameErr_int; end behaviour; ---------------------------------------------------------------------------------- -- LIBRARY ---------------------------------------------------------------------------------- LIBRARY IEEE; USE IEEE.std_logic_1164.all; USE IEEE.std_logic_arith.all; use IEEE.std_logic_UNSIGNED.all; --use IEEE.std_logic_UNSIGNED."-"; use work.scarts_core_pkg.all; use work.scarts_pkg.all; ---------------------------------------------------------------------------------- -- ENTITY ---------------------------------------------------------------------------------- entity miniUART_transmitter is port ( clk : in std_logic; reset : in std_logic; MsgLength : in MsgLength_type; Stop2 : in std_logic; -- Zweites Stopbit? ParEna : in std_logic; -- Parity? ParBit : in std_logic; -- Vorberechnetes Paritybit Data : in Data_type; tp : in std_logic; -- Transmitpulse vom BRG TransEna : out std_logic; -- Busdriver einschalten TrComp : out std_logic; -- Transmission complete TxD : out std_logic -- Sendeausgang ); end miniUART_transmitter; ---------------------------------------------------------------------------------- -- ARCHITECTURE ---------------------------------------------------------------------------------- architecture behaviour of miniUART_transmitter is -- Definition der States type trans_states is (START_S, DATA_S, PARITY_S, STOP_S); signal Trans_State : trans_states; signal next_Trans_State : trans_states; -- interne Signale zur synchronisation der Ausgänge signal TxD_i : std_logic; signal TransEna_i : std_logic; signal TrComp_i : std_logic; signal TxD_old : std_logic; signal TransEna_old : std_logic; signal TrComp_old : std_logic; -- interne Signale zur Zwischenspeicherung der Eingänge signal MsgLength_i : MsgLength_type; signal MsgLength_i_nxt : MsgLength_type; signal Stop2_i : std_logic; signal Stop2_i_nxt : std_logic; signal ParEna_i : std_logic; signal ParEna_i_nxt : std_logic; signal ParBit_i : std_logic; signal ParBit_i_nxt : std_logic; signal Data_i : Data_type; signal Data_nxt : Data_type; -- Bitzähler signal Bitcounter : MsgLength_type; signal next_Bitcounter : MsgLength_type; -- Stopzähler (00: 1. Stopbit; 01: 2. Stopbit oder Ende; 10: Ende) signal Stopcounter : std_logic_vector(1 downto 0); signal next_Stopcounter : std_logic_vector(1 downto 0); begin -- behaviour TRANS_OUTPUT : process (clk, reset) begin -- process TRANS_OUTPUT -- Reset, setzt alles auf Standardwerte if reset = RST_ACT then TxD <= '1'; TransEna <= not BUSDRIVER_ON; TrComp <= TRANS_COMP; TxD_old <= '1'; TransEna_old <= not BUSDRIVER_ON; TrComp_old <= TRANS_COMP; Data_i <= (others => '1'); MsgLength_i <= (others => '0'); Bitcounter <= (others => '0'); Stopcounter <= (others => '0'); Trans_State <= START_S; Stop2_i <= '0'; ParBit_i <= '0'; ParEna_i <= '0'; elsif (clk'event and clk = '1') then TxD <= TxD_old; TransEna <= TransEna_old; TrComp <= TrComp_old; Data_i <= Data_nxt; MsgLength_i <= MsgLength_i_nxt; Bitcounter <= Bitcounter; Stopcounter <= Stopcounter; Trans_State <= Trans_State; Stop2_i <= Stop2_i_nxt; ParBit_i <= ParBit_i_nxt; ParEna_i <= ParEna_i_nxt; -- Bei Transmitpulse: ausgeben, Zustandswechsel if tp = '1' then TxD <= TxD_i; TransEna <= TransEna_i; TrComp <= TrComp_i; TxD_old <= TxD_i; TransEna_old <= TransEna_i; TrComp_old <= TrComp_i; Bitcounter <= next_Bitcounter; -- Datenbits mitzählen Stopcounter <= next_Stopcounter; -- Stopbits mitzählen Trans_State <= next_Trans_State; -- Zustandswechsel end if; end if; end process TRANS_OUTPUT; TRANS_STATEMACHINE: process (Trans_State, Bitcounter, Stopcounter, MsgLength, MsgLength_i, Data, Data_i, ParEna, ParEna_i, ParBit, ParBit_i, Stop2, Stop2_i) begin -- process TRANS_STATEMACHINE -- Defaultwerte (halten) Data_nxt <= Data_i; MsgLength_i_nxt <= MsgLength_i; ParEna_i_nxt <= ParEna_i; ParBit_i_nxt <= ParBit_i; Stop2_i_nxt <= Stop2_i; case Trans_State is when DATA_S => TrComp_i <= not TRANS_COMP; TransEna_i <= BUSDRIVER_ON; next_Bitcounter <= Bitcounter + '1'; next_Stopcounter <= (others => '0'); -- letztes Bit des Datenwortes if Bitcounter = MsgLength_i then TxD_i <= Data_i(conv_Integer(unsigned(Bitcounter))); if ParEna_i = PARITY_ENABLE then next_Trans_State <= PARITY_S; else next_Trans_State <= STOP_S; end if; -- irgendeine Position im Datenwort else TxD_i <= Data_i(conv_Integer(unsigned(Bitcounter))); next_Trans_State <= DATA_S; end if; when PARITY_S => TxD_i <= ParBit_i; TrComp_i <= not TRANS_COMP; TransEna_i <= BUSDRIVER_ON; next_Bitcounter <= (others => '0'); next_Stopcounter <= (others => '0'); next_Trans_State <= STOP_S; when STOP_S => TxD_i <= '1'; next_Bitcounter <= (others => '0'); next_Stopcounter <= Stopcounter + '1'; case Stopcounter is -- erstes Stopbit when "00" => TrComp_i <= not TRANS_COMP; TransEna_i <= BUSDRIVER_ON; next_Trans_State <= STOP_S; -- zweites Stopbit oder Ende when "01" => if Stop2_i = SECOND_STOPBIT then TrComp_i <= not TRANS_COMP; TransEna_i <= BUSDRIVER_ON; next_Trans_State <= STOP_S; else TrComp_i <= TRANS_COMP; TransEna_i <= not BUSDRIVER_ON; next_Trans_State <= START_S; end if; -- Ende when others => TrComp_i <= TRANS_COMP; TransEna_i <= not BUSDRIVER_ON; next_Trans_State <= START_S; end case; when others => -- START_S TxD_i <= '0'; -- halten, erst nach Datenübernahme freigeben (DATA_S) TrComp_i <= TRANS_COMP; TransEna_i <= BUSDRIVER_ON; -- neue Daten holen Data_nxt <= Data; MsgLength_i_nxt <= MsgLength; ParEna_i_nxt <= ParEna; ParBit_i_nxt <= ParBit; Stop2_i_nxt <= Stop2; next_Bitcounter <= (others => '0'); next_Stopcounter <= (others => '0'); next_Trans_State <= DATA_S; end case; end process TRANS_STATEMACHINE; end behaviour;