---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: -- Design Name: -- Module Name: ASCIIToBin - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -- This code converts the sign_char and 4 ASCII digits into a binary value when -- start_convert is asserted. It saves the values into registers, performs the -- conversion and then asserts convert_done_tick for one clock cycle when completed entity ASCIIToBin is port( clk: in std_logic; reset: in std_logic; ready, convert_done_tick: out std_logic; start_convert: in std_logic; op_binary_val: out std_logic_vector(11 downto 0); dig0, dig1, dig2, dig3: in std_logic_vector(7 downto 0); sign_char : in std_logic_vector(7 downto 0) ); end ASCIIToBin; ARCHITECTURE beh of ASCIIToBin is type state_type is (idle, convert, done); signal state_reg, state_next: state_type; signal A_reg0, A_next0 : std_logic_vector(7 downto 0); signal A_reg1, A_next1 : std_logic_vector(7 downto 0); signal A_reg2, A_next2 : std_logic_vector(7 downto 0); signal A_reg3, A_next3 : std_logic_vector(7 downto 0); -- Need to make this 1-bit larger to prevent large positive numbers -- for example > 2047 from becoming negative and converted to two's -- complement. I'm debugging this so I'm guessing -- the problem I'm -- having could be related to the timing violation and this may work -- just fine with 12 bits, e.g., (11 downto 0). signal binary_reg, binary_next : signed(12 downto 0); signal cnt_reg, cnt_next : unsigned(1 downto 0); signal operand_sign_reg, operand_sign_next : std_logic; begin -- state and register logic process(clk, reset) begin if (reset = '1') then state_reg <= idle; binary_reg <= to_signed(0, 13); cnt_reg <= to_unsigned(0, 2); A_reg0 <= std_logic_vector(to_unsigned(character'pos('#'), 8)); A_reg1 <= std_logic_vector(to_unsigned(character'pos('#'), 8)); A_reg2 <= std_logic_vector(to_unsigned(character'pos('#'), 8)); A_reg3 <= std_logic_vector(to_unsigned(character'pos('#'), 8)); operand_sign_reg <= '0'; elsif (clk'event and clk = '1') then state_reg <= state_next; binary_reg <= binary_next; cnt_reg <= cnt_next; A_reg0 <= A_next0; A_reg1 <= A_next1; A_reg2 <= A_next2; A_reg3 <= A_next3; operand_sign_reg <= operand_sign_next; end if; end process; -- Combo logic for state machine, iteration cnter and shift operations in data path process(state_reg, binary_reg, cnt_reg, A_reg0, A_reg1, A_reg2, A_reg3, start_convert, sign_char, operand_sign_reg, dig0, dig1, dig2, dig3) variable tmp : signed(25 downto 0); begin ready <= '0'; convert_done_tick <= '0'; state_next <= state_reg; binary_next <= binary_reg; cnt_next <= cnt_reg; A_next0 <= A_reg0; A_next1 <= A_reg1; A_next2 <= A_reg2; A_next3 <= A_reg3; operand_sign_next <= operand_sign_reg; case state_reg is when idle => -- set output 'ready' in idle state -- otherwise, we are carrying out a binary number of ASCII translation ready <= '1'; if (start_convert = '1') then -- clear binary register binary_next <= (others => '0'); -- Latch the ascii data on the inputs A_next0 <= dig0; A_next1 <= dig1; A_next2 <= dig2; A_next3 <= dig3; -- set sign flag -- use 1 for negative and 0 for positive if ( sign_char = std_logic_vector(to_unsigned(character'pos('-'), 8)) ) then operand_sign_next <= '1'; else operand_sign_next <= '0'; end if; -- initialize cnter cnt_next <= to_unsigned(0, 2); -- start conversion state_next <= convert; end if; -- Conversion from ASCII to binary is easier than the opposite operation -- just involves multiplication -- dig0 has low order digit and dig3 has high order when convert => cnt_next <= cnt_reg + 1; -- If user hit fewer than 4 characters before hitting enter, skip this byte if ( cnt_reg = 0 and signed(A_reg3) /= 0 ) then binary_next <= "00000" & (signed(A_reg3) - character'pos('0')); end if; -- If user hit fewer than 3 characters before hitting enter, skip this byte if ( cnt_reg = 1 and signed(A_reg2) /= 0 ) then tmp := 10*binary_reg; binary_next <= tmp(12 downto 0) + ("00000" & (signed(A_reg2) - character'pos('0'))); end if; if ( cnt_reg = 2 and signed(A_reg1) /= 0 ) then tmp := 10*binary_reg; binary_next <= tmp(12 downto 0) + ("00000" & (signed(A_reg1) - character'pos('0'))); end if; if ( cnt_reg = 3 and signed(A_reg0) /= 0 ) then tmp := 10*binary_reg; -- Invert the number (2's compliment) if sign bit is 1 (negative number) if ( operand_sign_reg = '1' ) then binary_next <= -(tmp(12 downto 0) + ("00000" & (signed(A_reg0) - character'pos('0')))); else binary_next <= tmp(12 downto 0) + ("00000" & (signed(A_reg0) - character'pos('0'))); end if; state_next <= done; end if; when done => state_next <= idle; convert_done_tick <= '1'; end case; end process; op_binary_val <= std_logic_vector(binary_reg(11 downto 0)); end beh;