Untitled

 avatar
unknown
plain_text
18 days ago
16 kB
2
Indexable
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.common_pack.all;

entity cmdProc is
    port (
        clk            : in  std_logic;
        reset          : in  std_logic;
        rxnow          : in  std_logic;
        rxData         : in  std_logic_vector (7 downto 0);
        txData         : out std_logic_vector (7 downto 0);
        rxdone         : out std_logic;
        ovErr          : in  std_logic;
        framErr        : in  std_logic;
        txnow          : out std_logic;
        txdone         : in  std_logic;
        start          : out std_logic;
        numWords_bcd   : out BCD_ARRAY_TYPE(2 downto 0);
        dataReady      : in  std_logic;
        byte           : in  std_logic_vector(7 downto 0);
        maxIndex       : in  BCD_ARRAY_TYPE(2 downto 0);
        dataResults    : in  CHAR_ARRAY_TYPE(0 to RESULT_BYTE_NUM-1);
        seqDone        : in  std_logic
    );
end cmdProc;

architecture arch of cmdProc is
    
--    constant A: std_logic_vector(7 downto 0) := X"";

    
    -- Convert hexadecimal to ascii
    function hexConvert(nibble: std_logic_vector(3 downto 0)) return std_logic_vector is
    begin
        case nibble is
            when "0000" => return "00110000"; -- '0'
            when "0001" => return "00110001"; -- '1'
            when "0010" => return "00110010"; -- '2'
            when "0011" => return "00110011"; -- '3'
            when "0100" => return "00110100"; -- '4'
            when "0101" => return "00110101"; -- '5'
            when "0110" => return "00110110"; -- '6'
            when "0111" => return "00110111"; -- '7'
            when "1000" => return "00111000"; -- '8'
            when "1001" => return "00111001"; -- '9'
            when "1010" => return "01100001"; -- 'a'
            when "1011" => return "01100010"; -- 'b'
            when "1100" => return "01100011"; -- 'c'
            when "1101" => return "01100100"; -- 'd'
            when "1110" => return "01100101"; -- 'e'
            when others => return "01100110"; -- 'f'
        end case;
    end function;
   
   type state_type is (IDLE, cmdA_proc, START_TRANSMIT, TRANSMIT_DATA, sendByte1, sendByte2,
                       sendSpaceA, wait1, wait2, cmdA_proc_wait, waitP1, waitP2, waitP3, waitP4, 
                       waitP5, sendPByte1, sendPByte2, sendSpaceP, printPDecimal, sendByteL1, 
                       waitL1, sendByteL2, waitL2, sendSpaceL, waitL3, cmdA_Wait, checkSeqDone, 
                       waitSpaceA, zeroCheck);

    signal curState, nextState          : state_type;
    signal numWords_reg                 : BCD_ARRAY_TYPE(2 downto 0) := (others => (others => '0'));
    signal counter                      : integer range 0 to 7 := 0; -- Index to loop through dataresults for L command
    signal txData_reg                   : std_logic_vector(7 downto 0) := (others => '0'); -- Latches used to alter the value in combinatorial logic
    signal numWordsDigit                : integer range 0 to 2 := 2; -- Index for inputting numWords_bcd values
    signal numWordsDigit_state          : std_logic := '0'; -- Decrease numWordsDigit by 1
    signal isNumber                     : std_logic := '0'; -- Goes high when recieved rx byte is a valid digit
    signal numWordsDigit_reset          : std_logic := '0';
    signal byte_reg                     : std_logic_vector(7 downto 0);
    signal dataResults_reg              : CHAR_ARRAY_TYPE(0 to RESULT_BYTE_NUM-1) := (others => (others => '1'));
    signal maxIndex_reg                 : BCD_ARRAY_TYPE(2 downto 0);
    signal counter_reset                : std_logic; -- resets counter for command l
    signal counter_state                : std_logic; -- increases counter for command l by 1
    signal seqDone_reg                  : std_logic := '0';
    signal reset_seqDone_reg            : std_logic := '0';
    signal pCounter                     : integer range 0 to 2 := 2; -- counter acting as index for p digit printing
    signal pCounter_reset               : std_logic; -- counter
    signal pCounter_dec               : std_logic; -- decrease the pCounter

begin


    -- Process for capturing seqDone, dataResults, maxIndex from the data proc
process(clk, reset)
begin
    if reset='1' then
        seqDone_reg <= '0';
    elsif rising_edge(clk) then
        if reset_seqDone_reg = '1' then
            seqDone_reg <= '0';
        elsif seqDone = '1' then
            dataResults_reg <= dataResults;
            maxIndex_reg <= maxIndex;
            seqDone_reg <= '1';
        end if;
    end if;
end process;

-- Main transition logic on rising edge of clock
process(clk, reset)
begin
    if reset = '1' then
        curState      <= IDLE;
    elsif rising_edge(clk) then
        curState      <= nextState;
    end if;
end process;

-- Processing of the indexing for numWords_reg input
process(clk, reset)
begin
    if reset = '1' then
        numWordsDigit  <= 2;
    elsif rising_edge(clk) then
        if numWordsDigit_reset = '1' then
            numWordsDigit <= 2;
        elsif numWordsDigit_state = '1' then
            numWordsDigit <= numWordsDigit - 1;
        end if;   
    end if; 
end process;

-- Handling of decimal print counter for p command
process(clk, reset)
begin
    if reset = '1' then
        pCounter  <= 2;
    elsif rising_edge(clk) then
        if pCounter_reset = '1' then
            pCounter <= 2;
        elsif pCounter_dec = '1' then
            pCounter <= pCounter - 1;
        end if;   
    end if; 
end process;

-- processing for counter of L command
process(clk, reset)
begin
    if reset = '1' then
        counter  <= 0;
    elsif rising_edge(clk) then
        if counter_reset = '1' then
            counter <= 0;
        elsif counter_state = '1' then
            counter <= counter + 1;
        end if;   
    end if;
end process;

-- Capture byte form data proc when data is available
process(clk)
begin
    if rising_edge(clk) then
        if dataReady = '1' then
            byte_reg <= byte;
        end if;
    end if;
end process;
    
-- Sequential process for storing the incoming digit from rx into numWords_reg    
process(clk, reset)
begin
    if reset = '1' then
        numWords_reg <= (others => (others => '0')); -- reset to default value
    elsif rising_edge(clk) then
        if curState = TRANSMIT_DATA and txDone = '1' and txData_reg(7 downto 4) = "0011" and isNumber = '1' then
            numWords_reg(numWordsDigit) <= txData_reg(3 downto 0);
        end if;
    end if;
end process;

-- Handling of check for the number, sequential
process(clk, reset)
begin
    if reset = '1' then
        isNumber <= '0';  -- Reset to default value
    elsif rising_edge(clk) then
        -- Default value (maintain previous unless explicitly changed)
        if curState = TRANSMIT_DATA and txDone = '1' then
            if txData_reg = "01000001" or txData_reg = "01100001" then  -- A or a
                isNumber <= '1';
            elsif txData_reg(7 downto 4) /= "0011" then  -- Not a digit
                isNumber <= '0';
            end if;
        end if;
    end if;
end process;

    process (seqDone_reg, dataReady, txdone, rxnow, curState, rxData, txData_reg, isNumber, numWordsDigit, -- sensitivity list
             byte, byte_reg, dataResults_reg, maxIndex_reg, pCounter, counter, isNumber)
    begin

        -- default values
        txnow               <= '0';
        rxdone              <= '0';
        start               <= '0';
        numWordsDigit_state <= '0';
        numWordsDigit_reset <= '0';
        counter_state         <= '0';
        counter_reset         <= '0';
        reset_seqDone_reg     <= '0';
        pCounter_dec <= '0';
        pCounter_reset <= '0';
        --

        case curState is
        
-------------------------------------------------------------------- Initial Phase (data echo and command pattern recogniser)
			when IDLE =>
                if rxNow = '1' then
                    nextState <= START_TRANSMIT;
                  else 
                    nextState <= IDLE;
                  end if;  


            when START_TRANSMIT =>
                txData_reg <= rxData;
                txNow <= '1';
                rxDone <= '1';
                nextState <= TRANSMIT_DATA;

            -- Detect command
            when TRANSMIT_DATA =>
            if txDone = '1' then -- check if byte have been printed
                if txData_reg = "01000001" or txData_reg = "01100001" then -- CMD ANNN or aNNN
                    numWordsDigit_reset <= '1';
                    nextState <= IDLE;
                elsif (seqDone_reg = '1' and (txData_reg = "01010000" or txData_reg = "01110000")) then -- CMD P or p
                    pCounter_reset <= '1';
                    nextState <= sendPByte1; -- start p command processing
                elsif (seqDone_reg = '1' and (txData_reg = "01001100" or txData_reg = "01101100")) then -- CMD L or l
                    counter_reset <= '1';
                    nextState <= sendByteL1; -- start l command processing
                elsif txData_reg(7 downto 4) = "0011" and isNumber = '1' then
                    if numWordsDigit = 0 then
                        reset_seqDone_reg <= '1';
                        nextState <= cmdA_wait;
                    else
                        numWordsDigit_state <= '1';
                        nextState <= IDLE;
                    end if;
                else
                    nextState <= IDLE;
                end if;
            else
                nextState <= TRANSMIT_DATA;
            end if;
-------------------------------------------------------------------- Command A
            when cmdA_wait => -- send start to data proc
                start <= '1';
                nextState <= cmdA_proc;

            when cmdA_proc => -- wait for having the data ready
                if dataReady = '1' then
                    nextState <= sendByte1;
                else 
                    nextState <= cmdA_proc;
                end if;

            when sendByte1 => -- send first nibble of the byte captured from the data proc
                txData_reg <= hexConvert(byte_reg(7 downto 4));
                txNow <= '1';
                nextState <= wait1;

            when wait1 => -- wait for tx to finish printing
                if txDone = '1' then
                    nextState <= sendByte2;
                else
                    nextState <= wait1;
                end if;
                    
            when sendByte2 => -- send the second nibble
                txData_reg <= hexConvert(byte_reg(3 downto 0));
                txNow <= '1';
                nextState <= wait2;
            
            when wait2 => -- wait for tx stop printing
                if txDone = '1' then
                    nextState <= sendSpaceA;
                else
                    nextState <= wait2;
                end if;
                 
            when sendSpaceA =>  -- send space into the putty terminal to make the incoming bytes readable
                txData_reg <= "00100000";
                txNow <= '1';
                nextState <= waitSpaceA;

            when waitSpaceA => -- wait until the space is sent
                if txDone = '1' then
                    nextState <= checkSeqDone;
                else
                    nextState <= waitSpaceA;
                end if;
                
            when checkSeqDone => -- check if data has processed all requested bytes as defined in numWords_reg, if yes then echo the last byte and move back to initial step,
                                 -- if not, continue capturing and outputting the bytes from data proc
                 if seqDone_reg = '1' then
                    nextState <= IDLE;
                else
                    nextState <= cmdA_wait;
                end if;
-------------------------------------------------------------------- Command p

            when sendPByte1 => -- send the first nibble of peak value as ascii into the terminal
                txData_reg <= hexConvert(dataResults_reg(3)(7 downto 4));
                txNow <= '1';
                nextState <= waitP1;

            when waitP1 =>
                if txDone = '1' then
                    nextState <= sendPByte2;
                else
                    nextState <= waitP1;
                end if;
                    
            when sendPByte2 => -- send the second nibble of peak value as ascii into the terminal
                txData_reg <= hexConvert(dataResults_reg(3)(3 downto 0));
                txNow <= '1';
                nextState <= waitP2;
            
            when waitP2 =>
                if txDone = '1' then
                    nextState <= sendSpaceP;
                else
                    nextState <= waitP2;
                end if;
                 
            when sendSpaceP =>
                txData_reg <= "00100000";
                txNow <= '1';
                nextState <= waitP3;
            
            when waitP3 =>
                if txDone = '1' then
                    nextState <= printPDecimal;
                else
                    nextState <= waitP3;
                end if;
                
            when printPDecimal => -- loop printing the 3 decimals (maxIndex), representing the index value of the peak
                txData_reg <= hexConvert(maxIndex_reg(pCounter));
                txNow <= '1';
                if pCounter = 0 then
                    nextState <= waitP5;
                else
                    pCounter_dec <= '1';
                    nextState <= waitP4;
                end if;
            
            when waitP4 =>
                if txDone = '1' then
                    nextState <= printPDecimal;
                else
                    nextState <= waitP4;
                end if;
             
            when waitP5 =>
                if txDone = '1' then
                    nextState <= IDLE;
                else
                    nextState <= waitP5;
                end if;
-------------------------------------------------------------------- Command L     

            when sendByteL1 => -- print the first nibble of the current byte in dataResults reg
                txData_reg <= hexConvert(dataResults_reg(counter)(7 downto 4));
                txNow <= '1';
                nextState <= waitL1;

            when waitL1 =>
                if txDone = '1' then
                    nextState <= sendByteL2;
                else
                    nextState <= waitL1;
                end if;
                    
            when sendByteL2 => -- print second nibble
                txData_reg <= hexConvert(dataResults_reg(counter)(3 downto 0));
                txNow <= '1';
                nextState <= waitL2;
            
            when waitL2 =>
                if txDone = '1' then
                    nextState <= sendSpaceL;
                else
                    nextState <= waitL2;
                end if;
                 
            when sendSpaceL =>
                txData_reg <= "00100000";
                txNow <= '1';
                counter_state <= '1';
                nextState <= waitL3;
                
            when waitL3 => -- loop the process until all of dataResults has been printed
                if txDone = '1' then
                    if counter = 7 then
                        nextState <= IDLE;
                    else
                        nextState <= sendByteL1;
                    end if;
                else
                    nextState <= waitL3;
                end if;   
                
            when others =>
                nextState <= IDLE;
                
        end case;
    end process;
    
    -- direct assingments to ensure crisp and accurate assingment and timing
    numWords_bcd <= numWords_reg;
    txData <= txData_reg;
end arch;


Editor is loading...
Leave a Comment