Why won't a VHDL "inout" signal be assigned a value when used as an output

Viewed 713

I have a VHDL description for a bridge, and the bidirectional signal "mem_data_port0" is not getting assigned any value regardless of what I write to it. The pins on the FPGA are assigned accordingly, but no output.

I have the code below (its for an FPGA going into a larger system, so comments will reflect other system components that are not the FPGA)

FYI: The FPGA is a Lattice LCMXO2-7000HC

Any tips on assigning "mem_data_port0"?

library ieee;
use ieee.std_logic_1164.all; 
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
--use ieee.std_logic_signed.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;


library machxo2;
use machxo2.all;

entity SinglePhasePowerAnalyzerBridge is
    port(
    output0 : out std_logic; -- dummy, unassigned outputs
    output1 : out std_logic;
    output2 : out std_logic;
    output3 : out std_logic;
    output4 : out std_logic;
    output5 : out std_logic;
    output6 : out std_logic;
    output7 : out std_logic;

    accq_data_in : in std_logic_vector (15 downto 0); -- accquisition data in
    accq_clk : in std_logic; -- accquisition clock in
    accq_data_ready : in std_logic; -- data ready in 0: sending voltage/current data, 1: sending frequency data
    accq_reset : in std_logic; -- accquisition reset (active low)
    accq_voltage_current : in std_logic; -- accquisition select for voltage and current 0: voltage, 1: current

    buffer_data_port0 : out std_logic_vector (15 downto 0); -- buffer data
    buffer_address_port0 : in std_logic_vector(12 downto 0); -- buffer address low bits
    buffer_address_high_port0 : in std_logic_vector(2 downto 0); -- buffer address high bits
    buffer_high_byte_en_port0 : in std_logic; -- high byte enable
    buffer_low_byte_en_port0 : in std_logic; -- low byte enable
    buffer_write_en_port0 : in std_logic; -- write enable
    buffer_output_en_port0 : in std_logic; -- output enable
    buffer_memory_en_port0 : in std_logic; -- memory enable

    buffer_interrupt_out : out std_logic; 

    -- pins going to external SRAM memory
    mem_data_port0 : inout std_logic_vector (15 downto 0);
    mem_address_port0 : out std_logic_vector(12 downto 0);
    mem_address_high_port0 : out std_logic_vector (3 downto 0);
    mem_memory_en_port0 : out std_logic := '1';
    mem_output_en_port0 : out std_logic := '1';
    mem_write_en_port0 : out std_logic := '1';
    mem_high_byte_en_port0 : out std_logic := '0';
    mem_low_byte_en_port0 : out std_logic := '0';

    debug_out : out std_logic -- debug output

    );

end SinglePhasePowerAnalyzerBridge;

architecture rtl of SinglePhasePowerAnalyzerBridge is

signal frequency_storage_buffer : std_logic_vector (15 downto 0); -- frequency buffer

signal voltage_storage_pointer : integer range 0 to 8191;
signal current_storage_pointer : integer range 0 to 8191;

signal signal_accq_data_in : std_logic_vector (15 downto 0);
signal signal_accq_clk : std_logic;
signal signal_inverse_accq_clk : std_logic;
signal signal_accq_data_ready : std_logic;
signal signal_accq_reset : std_logic;
signal signal_accq_voltage_current : std_logic;

signal signal_delayed_inverse_accq_clk : std_logic;

signal signal_buffer_data_port0 : std_logic_vector (15 downto 0);
signal signal_buffer_address_port0 : std_logic_vector(12 downto 0);
signal signal_buffer_address_high_port0 : std_logic_vector(2 downto 0);
signal signal_buffer_high_byte_en_port0 : std_logic;
signal signal_buffer_low_byte_en_port0 : std_logic;
signal signal_buffer_write_en_port0 : std_logic;
signal signal_buffer_output_en_port0 : std_logic;
signal signal_buffer_memory_en_port0 : std_logic;

begin

    signal_accq_data_in <= accq_data_in; -- connect all the pins to internal signals
    signal_accq_clk <= accq_clk;
    signal_accq_data_ready <= accq_data_ready;
    signal_accq_reset <= accq_reset;
    signal_accq_voltage_current <= accq_voltage_current;

    signal_inverse_accq_clk <= not signal_accq_clk;

    --debug_out <= signal_delayed_inverse_accq_clk;

    signal_buffer_address_port0 <= buffer_address_port0;
    signal_buffer_address_high_port0 <= buffer_address_high_port0;
    signal_buffer_high_byte_en_port0 <= buffer_high_byte_en_port0;
    signal_buffer_low_byte_en_port0 <= buffer_low_byte_en_port0;
    signal_buffer_write_en_port0 <= buffer_write_en_port0;
    signal_buffer_output_en_port0 <= buffer_output_en_port0;
    signal_buffer_memory_en_port0 <= buffer_memory_en_port0;

    buffer_interrupt_out <= not signal_accq_data_ready;

    output2 <= signal_accq_data_ready; -- dummy outputs, so the input pins are not left uncommected
    output3 <= signal_accq_clk;
    output4 <= signal_accq_reset;
    output5 <= signal_accq_voltage_current;


    general_event : process(signal_accq_clk, signal_accq_data_ready, signal_accq_data_in, signal_accq_voltage_current, signal_accq_reset, 
    signal_buffer_memory_en_port0, signal_buffer_output_en_port0, signal_buffer_write_en_port0, signal_buffer_address_high_port0, signal_buffer_address_port0, 
    signal_buffer_data_port0, frequency_storage_buffer, signal_accq_reset, signal_accq_data_ready, voltage_storage_pointer, current_storage_pointer)
    begin
        if(signal_accq_data_ready = '0') then -- when data from the acquisition controller comes in
            mem_output_en_port0 <= '1'; -- disable memory output
            mem_memory_en_port0 <= '0'; -- enable memory
            mem_write_en_port0 <= signal_inverse_accq_clk; -- send the acquisition clock to the memory write enable pin
            if(signal_accq_reset = '1') then -- if reset is not activated...
                accq_clk_edge : if(rising_edge(signal_accq_clk)) then -- process on clock rising edge
                    if(signal_accq_voltage_current = '1') then -- if sending current data
                        mem_data_port0 <= signal_accq_data_in; -- store the data in the current buffer
                        mem_address_port0 <= std_logic_vector(to_unsigned(current_storage_pointer, 13));
                        mem_address_high_port0 <= "0001"; -- sending current data to memory
                    current_storage_pointer <= (current_storage_pointer + 1); -- increment the counter
                    elsif (signal_accq_voltage_current = '0') then -- do the same if sending voltage data
                        --mem_data_port0 <= signal_accq_data_in; -- store the data in the voltage buffer
                        mem_data_port0 <= "1111111111111111";
                        mem_address_port0 <= std_logic_vector(to_unsigned(voltage_storage_pointer, 13));
                        mem_address_high_port0 <= "0000"; -- sending voltage data to memory
                        voltage_storage_pointer <= (voltage_storage_pointer + 1); -- increment the counter
                    end if;
                end if accq_clk_edge;
            else -- if reset is activated...
                voltage_storage_pointer <= 0; -- reset everything to 0
                current_storage_pointer <= 0; -- reset everything to 0
            end if;
        --end process accq_event;
        elsif (signal_accq_data_ready = '1') then -- if data ready is high, the buffer is in read mode
            mem_data_port0 <= "ZZZZZZZZZZZZZZZZ"; -- set memory data lines to input, or read mode
            mem_write_en_port0 <= '1'; -- disable writing to the memory
            mem_output_en_port0 <= '0'; -- enable memory output
            mem_address_port0 <= signal_buffer_address_port0; -- select the appropriate addreess
            mem_address_high_port0 (2 downto 0) <= signal_buffer_address_high_port0; -- do the same with the high bits

            if(rising_edge(signal_accq_clk) and signal_accq_reset = '1') then -- if the accquisition MCU is writing with the data ready pin high
                frequency_storage_buffer <= signal_accq_data_in; -- store the frequency value that it's sending
            end if;
            if(signal_accq_reset = '0') then -- reset as before if reset is enabled
                voltage_storage_pointer <= 0; -- reset everything to 0
                current_storage_pointer <= 0; -- reset everything to 0
            end if;

            if(signal_buffer_memory_en_port0 = '0' and signal_buffer_write_en_port0 = '1' and signal_accq_data_ready = '1' and signal_accq_reset = '1') then -- memory enabled and write enable high...
                case signal_buffer_address_high_port0 is
                    when "000" => signal_buffer_data_port0 <= mem_data_port0; -- output data to downstream MCUs as needed
                    when "001" => signal_buffer_data_port0 <= mem_data_port0;
                    when "010" => signal_buffer_data_port0 <= frequency_storage_buffer;
                    when "011" => signal_buffer_data_port0 <= std_logic_vector(to_unsigned(voltage_storage_pointer, 16));
                    when "100" => signal_buffer_data_port0 <= std_logic_vector(to_unsigned(current_storage_pointer, 16));
                    when "111" => signal_buffer_data_port0 <= "1010000001010110"; -- 0xA056
                    when others=>

                end case;
            end if; 
            if(signal_buffer_output_en_port0 = '0') then
                --buffer_data_port0(7 downto 0) <= signal_buffer_data_port0 (15 downto 8);
                --buffer_data_port0(15 downto 8) <= signal_buffer_data_port0 (7 downto 0);
                buffer_data_port0 <= signal_buffer_data_port0;
            else
                buffer_data_port0 <= "ZZZZZZZZZZZZZZZZ";
            end if;
        end if;
    end process general_event;

    output6 <= signal_buffer_high_byte_en_port0;
    output7 <= signal_buffer_low_byte_en_port0;



end rtl; 
1 Answers

I've tried your code on Modelsim. Although I can't comment on the correctness of mem_data_port0's behavior, it does get assigned values depending on the other relevant signals, so for the out direction it works.

VHDL Modelsim simulation

If you're talking about the fact that you cannot assign values to it from outside, all I could think of is that you forgot to assign it the high impedance in input mode, but you do, so that's out.

An explanation could be that your entity is not the top level entity, which would render inout ports unusable (inout has no meaning inside the FPGA, only at the design's top level).

Related