1
\$\begingroup\$

I'm trying to connect between two components: my TOP_LEVEL component's outputs two my BIN2BCD component which converts binary to BCD. the problem is that the BIN2BCD uses std_logic_vector, and my TOP_LEVEL component uses (mainly) integers, and either of the component's types cant be changed. there is the code:

the problem is on the mapping block of BIN2BCD in the architecture. it gives me some errors that i dont know how to handle (im new to VHDL).

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity logic is
    generic(
        LOGIC_WAVE_SPEED_G                      :   integer := 34300;       -- in cm/sec
        LOGIC_CLK_FREQ_G                        :   integer := 50000000;    -- in 1/sec
        LOGIC_DELAY_TIME_BETWEEN_MEASURES_G     :   integer := 1000000
    );

    port(
        LOGIC_RST               : in std_logic;
        LOGIC_SYS_CLK           : in std_logic;
        LOGIC_START_MEASURE     : in std_logic;
        LOGIC_DATA_IN           : in integer;
        LOGIC_DATA_IN_VLD       : in std_logic;

        LOGIC_SEND_TRIG         : out std_logic;
        LOGIC_ONES              : out integer range 9 downto 0;
        LOGIC_TENS              : out integer range 9 downto 0;
        LOGIC_HUNDS             : out integer range 9 downto 0
    );
end entity;

architecture behave of logic is

    constant pulses_per_distance_unit   :   integer := (1/LOGIC_WAVE_SPEED_G)*(2*LOGIC_CLK_FREQ_G);

    type state_machine is (waiting_to_start_measuring, send_pulse_to_sensor, convert_pulses_to_cm);

    component bin2bcd_12bit_sync is
        port(
            BIN2BCD_binIN       : in    STD_LOGIC_VECTOR (11 downto 0);     -- this is the binary number
            BIN2BCD_CLK         : in    STD_LOGIC;                           -- clock input
            BIN2BCD_ONES        : out   STD_LOGIC_VECTOR (3 downto 0);      -- this is the unity digit
            BIN2BCD_TENTHS      : out   STD_LOGIC_VECTOR (3 downto 0);      -- this is the tens digit
            BIN2BCD_HUNDERDTHS  : out   STD_LOGIC_VECTOR (3 downto 0);      -- this is the hundreds digit
            BIN2BCD_THOUSANDS   : out   STD_LOGIC_VECTOR (3 downto 0)      -- 
        );
    end component;

    component derivative is
        port(
            DERIVATIVE_RST      : in    std_logic;
            DERIVATIVE_CLK      : in    std_logic;
            DERIVATIVE_D_IN     : in    std_logic;
            DERIVATIVE_STROBE   : out   std_logic
        );
    end component;

    component synchronizer
        port
        (
            SYNC_RST        : in std_logic;
            SYNC_CLK        : in std_logic;
            SYNC_D_IN       : in std_logic;
            SYNC_D_OUT      : out std_logic
        );
    end component;

    signal count_distance                       : integer range 350 downto 0 := 0;
    signal count_delay                          : integer range LOGIC_DELAY_TIME_BETWEEN_MEASURES_G downto 0;
    signal count_pulses_per_distance            : integer := 0;
    signal ones, tens, hunds                    : integer range 9 downto 0 := 0;
    signal start_measure_sync                   : std_logic;
    signal start_measure_strobe                 : std_logic;
    signal data_in_vld_strobe                   : std_logic;
    signal present_state                        : state_machine := waiting_to_start_measuring;

begin

    bin_to_BCD_converter:       bin2bcd_12bit_sync
    port map(
            BIN2BCD_binIN                                   =>  std_logic_vector(to_unsigned(count_distance, BIN2BCD_binIN'length)),
            BIN2BCD_CLK                                     =>  LOGIC_SYS_CLK,  
            to_integer(unsigned(BIN2BCD_ONES))              =>  LOGIC_ONES,     
            to_integer(unsigned(BIN2BCD_TENTHS))            =>  LOGIC_TENS,     
            to_integer(unsigned(BIN2BCD_HUNDERDTHS))        =>  LOGIC_HUNDS     
        );          

    synch_start_measure_button:     synchronizer
    port map(
        SYNC_RST        =>  LOGIC_RST,
        SYNC_CLK        =>  LOGIC_SYS_CLK, 
        SYNC_D_IN       =>  LOGIC_START_MEASURE,
        SYNC_D_OUT      =>  start_measure_sync
    );

    derivative_for_start_measure_button:    derivative
    port map(
        DERIVATIVE_CLK      => LOGIC_SYS_CLK,
        DERIVATIVE_RST      => LOGIC_RST,
        DERIVATIVE_D_IN     => start_measure_sync,
        DERIVATIVE_STROBE   => start_measure_strobe
    );


main:   
        process(LOGIC_RST, LOGIC_SYS_CLK) -- NO OTHER SIGNALS IN SENSITIVITY LIST, ONLY CLK AND RESET
        begin
            if LOGIC_RST = '1' then
                present_state               <= waiting_to_start_measuring;
                count_delay                 <= 0;
                count_distance              <= 0;
                count_pulses_per_distance   <= 0;
            elsif LOGIC_SYS_CLK'event and LOGIC_SYS_CLK = '1' then
                case present_state is
                    when waiting_to_start_measuring =>  if start_measure_strobe = '1' then
                                                            count_distance <= 0;
                                                            count_pulses_per_distance <= 0;
                                                            LOGIC_SEND_TRIG <= '1';
                                                            present_state <= send_pulse_to_sensor;
                                                        else
                                                            present_state <= waiting_to_start_measuring;
                                                        end if;
                    when send_pulse_to_sensor       =>  LOGIC_SEND_TRIG <= '0';
                                                        if LOGIC_DATA_IN_VLD = '1' then
                                                            present_state <= convert_pulses_to_cm;
                                                        else
                                                            present_state <= send_pulse_to_sensor;
                                                        end if;
                    when convert_pulses_to_cm       =>  if count_pulses_per_distance < LOGIC_DATA_IN then
                                                            count_pulses_per_distance <= count_pulses_per_distance + pulses_per_distance_unit;
                                                            count_distance <= count_distance + 1;
                                                        end if;
                                                        if count_delay < LOGIC_DELAY_TIME_BETWEEN_MEASURES_G then
                                                            count_delay <= count_delay + 1;
                                                        else
                                                            count_delay <= 0;
                                                            present_state <= waiting_to_start_measuring;
                                                        end if;
                end case;
            end if;
        end process;
end architecture;```
\$\endgroup\$
1
  • \$\begingroup\$ BIN2BCD_binIN isn't visible directly or by selection. See IEEE Std 1076-2008 12.2 Scope of declarations "The scope of a declaration, except for an architecture body, extends from the beginning of the declaration to the end of the immediately closing declarative region; ...", 12.1 Declarative region para 1 f) a component declaration is a separate declarative region. logic.bin2bcd_12bit_sync.BIN2BCD_binIN doesn't work here either, component names are excluded from prefixes of expanded names see 8.3 Selected names, para 8. \$\endgroup\$
    – user8352
    May 7, 2020 at 22:06

1 Answer 1

0
\$\begingroup\$

The problem appears to be in BIN2BCD_binIN'length)), where BIN2BCD_binIN is a port on the component you are trying to connect to, which is not an immediately visible object in the architecture body, so you cannot take its length.

As the length is no secret, being openly displayed in the component name bin2bcd_12bit_sync, this is a long-winded expression for 12 and could be replaced by the same.

I would use a named constant

constant bin2bcd_length : natural := 12;

and refer to it throughout the architecture (it is not exposed in the entity, which is good encapsulation) as follows:

BIN2BCD_binIN : in STD_LOGIC_VECTOR (bin2bcd_length - 1 downto 0);  
...  
port map (
    BIN2BCD_binIN => std_logic_vector(to_unsigned(count_distance, bin2bcd_length)),

Actually, that's not true.

When I see so many type conversions in close proximity, my nose wrinkles; this is a code smell. It makes me question if the component's ports are declared with the correct type in the first place.

Ranged integers are perfectly reasonable port types (even for synthesis) much of the time; so are signed/unsigned if you need to access bits. There's an argument for keeping std_logic_vector at the top level (FPGA pins) but even there, it had better be in your coding standard rules if you want me to agree to it.

Anyway, get the design right, and most of the conversion functions drop away leaving simple, clear code.

\$\endgroup\$
3
  • \$\begingroup\$ Your suggestion of adding the constant worked, but I have 2 questions: 1. How would u implement it if the length was hidden and not open? 2. I'm getting some more errors on the code (vcom-1022) which I dont understand to. "Error: logic.vhd(79): (vcom-1022) Formal part (type conversion (to ieee.NUMERIC_STD.UNSIGNED)) does not depict an interface object." \$\endgroup\$ May 7, 2020 at 21:20
  • \$\begingroup\$ Anyway, get the design right, and most of the conversion functions drop away leaving simple, clear code. The problem is that the BIN2BCD component isnt mine, and to be honest I dont realy know how to create new one using only integers. (This component implements the double dabble algorithem) \$\endgroup\$ May 7, 2020 at 21:27
  • \$\begingroup\$ 1) If it's hidden, you have bigger problems (not knowing how many output ports there are, for one). 2) You may need an intermediate signal of type UNSIGNED (or even std_logic_vector; some tools have trouble handling type conversions in port maps) instead of to_integer(unsigned(BIN2BCD_ONES)) => LOGIC_ONES, . Re: other people's components; yes, you sometimes have to live with that. \$\endgroup\$ May 7, 2020 at 21:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.