-- Literatur: EDS4 Uebungsbeispiel von Markus Pfaff, Martina Zeinzinger, -- Friedrich Seebacher (FH-Hagenberg) --IfRs232Tx-p.vhd library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.global.all; package IfRs232Tx is type acRs232Tx is record DataBitWidth : natural; end record; constant cRs232Tx : acRs232Tx := ( DataBitWidth => 8 ); type aiRs232Tx is record ----------------------------------------------------------- -- Control inputs ----------------------------------------------------------- -- Transmit if activated and stop transmission if not -- activated, but finish transmission of the current data. Transmit : std_ulogic; -- Is data available which can be read with the next rising -- edge of the clk and sent from then on? DataAvailable : std_ulogic; -- The baud rate for the bits which are sent out is -- determined by an external unit called a baud rate -- generator or simply strobe generator. The strobe we get -- from this unit is input by the port BitStrobe : std_ulogic; ----------------------------------------------------------- -- Data inputs ----------------------------------------------------------- Data : std_ulogic_vector(cRs232Tx.DataBitWidth-1 downto 0); end record; type aoRs232Tx is record ----------------------------------------------------------- -- Status outputs ----------------------------------------------------------- -- Clock egdge 1 -- The source of parallel data (e.g. a FIFO) feeding this -- transmitter will offer a data word at its data output and -- flag data validity at the same time via activation of a -- control output (named DataValid or similar). -- Clock edge 2 -- The transmitter reacts on the validity of the input data -- by reading the data into an internal register flagging -- that the data was read. -- Clock edge 3 -- The transmitter deactivates the "data was read" flag -- again. The data source may provide new valid data keeping -- DataValid active or may run out of valid data for the -- moment, thus deactivating DataValid. DataWasRead : std_ulogic; ----------------------------------------------------------- -- Result outputs ----------------------------------------------------------- -- The serial data line carying the Tx signal. Tx : std_ulogic; end record; end IfRs232Tx; -- Rs232Tx-e.vhd library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use work.Global.all; use work.IfRs232Tx.all; entity Rs232Tx is port ( inResetAsync : in std_ulogic; iClk : in std_ulogic; iRs232Tx : in aiRs232Tx; oRs232Tx : out aoRs232Tx ); end Rs232Tx; -- Rs232Tx-Rtl-a.vhd architecture Rtl of Rs232Tx is constant cTxLineStartBitVal : std_ulogic := '0'; constant cTxLineStopBitAndIdleVal : std_ulogic := '1'; type aDataInputState is (CanAcceptNewData, FreshDataArrived, DataBufferBusy); type aRegion is (StartBit, DataBits, ParityBit, StopBit, StopBitAndIdle); -- Register structure of design type aRegSet is record DataInputState : aDataInputState; Region : aRegion; BitIdx : natural range 0 to cRs232Tx.DataBitWidth-1; DataWasRead : std_ulogic; Data : std_ulogic_vector(cRs232Tx.DataBitWidth-1 downto 0); parity : std_ulogic; Tx : std_ulogic; end record; constant cInitValR : aRegSet := ( DataInputState => CanAcceptNewData, Region => StopBitAndIdle, --Idle, BitIdx => 0, DataWasRead => cInactivated, Data => (others => '0'), parity => cInactivated, Tx => cTxLineStopBitAndIdleVal ); -- All registers in design signal R, NextR : aRegSet; begin Comb : process (R, iRs232Tx) begin -- Set the defaults. NextR <= R; -- Parallel data input part of transmitter . NextR.DataWasRead <= cInactivated ; case R.DataInputState is when CanAcceptNewData => -- We are waiting for data to be transmitted . if (( iRs232Tx.Transmit = cActivated ) and ( iRs232Tx.DataAvailable = cActivated )) then NextR.Data <= iRs232Tx.Data ; NextR.DataInputState <= FreshDataArrived ; NextR.DataWasRead <= cActivated ; end if; when FreshDataArrived => -- We have loaded new data into the send register . if ( R.Region = StartBit ) then NextR.DataInputState <= DataBufferBusy ; end if; when DataBufferBusy => -- The send register is still occupied . if (R.Region = StopBitAndIdle ) then NextR.DataInputState <= CanAcceptNewData ; end if; end case ; -- Serial output part of transmitter . case R.Region is when StartBit => NextR.Tx <= cTxLineStartBitVal ; if iRs232Tx.BitStrobe = cActivated then NextR.Region <= DataBits ; NextR.BitIdx <= 0; end if; when DataBits => NextR.Tx <= R.Data (R.BitIdx ); if iRs232Tx.BitStrobe = cActivated then if R.BitIdx = 0 then NextR.parity <= R.Data (R.BitIdx); else NextR.parity <= R.parity xor R.Data (R.BitIdx); end if; if R.BitIdx = cRs232Tx.DataBitWidth -1 then -- All bits sent . NextR.Region <= ParityBit ; else -- Send next bit . NextR.BitIdx <= R.BitIdx + 1; end if; end if; when ParityBit => -- gerade Parität NextR.Tx <= R.parity ; if iRs232Tx.BitStrobe = cActivated then NextR.Region <= StopBit ; end if; when StopBit => NextR.Tx <= cTxLineStopBitAndIdleVal ; if iRs232Tx.BitStrobe = cActivated then NextR.Region <= StopBitAndIdle ; end if; when StopBitAndIdle => NextR.Tx <= cTxLineStopBitAndIdleVal ; if iRs232Tx.BitStrobe = cActivated then if R.DataInputState = FreshDataArrived then NextR.Region <= StartBit ; end if; end if; end case; end process Comb; ---------------------- -- Update register values ---------------------- Registering : process(iClk, inResetAsync) begin if (inResetAsync = cnActivated) then R <= cInitValR; elsif ((iClk'event) and (iClk = '1')) then R <= NextR; end if; end process; ----------------------------- -- Connect registers to ports ----------------------------- oRs232Tx.DataWasRead <= R.DataWasRead; oRs232Tx.Tx <= R.Tx; end Rtl;