---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: -- Design Name: -- Module Name: BinToASCII - 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; entity BinToASCII is port( clk:in std_logic; reset:in std_logic; ready, convert_done_tick: out std_logic; start_convert: in std_logic; result_binary_val: in std_logic_vector(11 downto 0); dig0, dig1, dig2, dig3: out std_logic_vector(7 downto 0); sign_char : out std_logic_vector(7 downto 0) ); end BinToASCII; ARCHITECTURE beh of BinToASCII 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); signal binary_reg, binary_next : std_logic_vector(11 downto 0); signal cnt_reg, cnt_next : unsigned(1 downto 0); signal start_div, divider_avail, division_complete : std_logic; signal divisor, dividend : std_logic_vector(11 downto 0); signal quo, rmd : std_logic_vector(11 downto 0); signal rmd_ascii : std_logic_vector(7 downto 0); signal binary_val_pos : std_logic_vector(11 downto 0); signal operand_sign_reg, operand_sign_next : std_logic; begin -- instantiate divider DividerComponent: entity work.Divider(beh) generic map (DIV_WIDTH=>12, ITER_REG_WIDTH=>4) port map (clk=>clk, reset=>reset, start=>start_div, dvsr=>divisor, dvnd=>dividend, ready=>divider_avail, done_tick=>division_complete, quo=>quo, rmd=>rmd); -- state and register logic process(clk, reset) begin if (reset = '1') then state_reg <= idle; binary_reg <= (others => '0'); 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; -- Connect divisor to constant decimal 10 and dividend to binary_reg, which is updated after -- each successive division by 10 divisor <= std_logic_vector(to_unsigned(10, 12)); dividend <= binary_reg; -- Make the number positive if incoming operand has sign bit set -- assume we are in 2's compliment -- Actual sign bit is saved in register in idle state below. binary_val_pos value is actually latched into -- binary_reg below with result_binary_val(11) select binary_val_pos <= result_binary_val when '0', std_logic_vector(unsigned(NOT result_binary_val) + 1) when others; -- Combo logic for state machine, iteration cnter and shift operations in data path process(state_reg, binary_reg, cnt_reg, start_div, divisor, dividend, divider_avail, division_complete, quo, rmd_ascii, A_reg0, A_reg1, A_reg2, A_reg3, start_convert, result_binary_val, binary_val_pos, operand_sign_reg) begin ready <= '0'; convert_done_tick <= '0'; state_next <= state_reg; binary_next <= binary_reg; cnt_next <= cnt_reg; start_div <= '0'; 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 -- latch binary value to convert binary_next <= binary_val_pos; -- Save high order (sign) bit of operand operand_sign_next <= result_binary_val(11); -- initialize cnter cnt_next <= to_unsigned(0, 2); -- start conversion state_next <= convert; end if; when convert => -- divider_avail becomes 1 AFTER the division_complete pulse used below. For one clock cycle, -- make start_div a '1' to start the division state machine if ( divider_avail = '1' ) then start_div <= '1'; end if; -- Wait for the divider to complete it's operation, save results -- this is a one-clk cycle pulse if ( division_complete = '1' ) then cnt_next <= cnt_reg + to_unsigned(1, 2); -- Put quotient into binary register for next iteration binary_next <= quo; -- Load up the ASCII values into the 4 registers if ( cnt_reg = to_unsigned(0, 2) ) then A_next0 <= rmd_ascii; end if; if ( cnt_reg = to_unsigned(1, 2) ) then A_next1 <= rmd_ascii; end if; if ( cnt_reg = to_unsigned(2, 2) ) then A_next2 <= rmd_ascii; end if; -- If we have converted all four bytes, we are done. if ( cnt_reg = to_unsigned(3, 2) ) then A_next3 <= rmd_ascii; state_next <= done; end if; end if; when done => state_next <= idle; convert_done_tick <= '1'; end case; end process; -- Convert remainder into an ascii char by adding 48 (the ASCII value for char '0') rmd_ascii <= std_logic_vector(unsigned(rmd(7 downto 0)) + to_unsigned(character'pos('0'), 8)); with operand_sign_reg select sign_char <= std_logic_vector(to_unsigned(character'pos('+'), 8)) when '0', std_logic_vector(to_unsigned(character'pos('-'), 8)) when others; dig0 <= A_reg0; dig1 <= A_reg1; dig2 <= A_reg2; dig3 <= A_reg3; end beh;