You are here

VHDL - FSMD

-- 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;