Modelsim Altera VHDL MEMORY ROM

时间:2016-03-10 08:33:37

标签: vhdl counter fsm rom

我很困惑为什么我的VHDL设计不起作用。我将创建一个top.vhd文件,该文件将编程FPGA板以显示地址0到15以及每个地址的相应值。当我模拟我的设计时,所有时钟和重置都有效。我遇到的问题是我的FSM流程和地址流程。我知道这里有很多事情,所以如果你需要澄清我可以回答你的问题。

library IEEE;
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.all;

entity top is

    port(Clock : in std_logic;
          Reset : in std_logic;
          SW    : in  std_logic_vector (1 downto 0);
          HEX2, HEX4: out std_logic_vector ( 6 downto 0);
          KEY0: in std_logic);

end entity;

architecture top_arch of top is

    component char_decoder is
        port(BIN_IN  : in  std_logic_vector (3 downto 0);
          HEX_OUT : out std_logic_vector (6 downto 0));
    end component;

    component rom_16x4_sync is
        port (clock:   in std_logic;
            address: in std_logic_vector (3 downto 0);
            rom_en:  in std_logic;
            data_out: out std_logic_vector(3 downto 0));
    end component;

    type state_type is (start,  read_rom, clear_addr, done);
    signal current_state, next_state : state_type;
    signal Rom_en, addr_count_clr, addr_count_en : std_logic;
    signal address_counter : integer range 0 to 15;
    signal address_uns : unsigned (3 downto 0);
    signal clock_slow : std_logic;
    signal rom_out : std_logic_vector (3 downto 0);

    begin

    char : char_decoder port map (BIN_IN => rom_out, HEX_OUT => HEX2);
    char1 : char_decoder port map (BIN_IN => std_logic_vector(address_uns), HEX_OUT => HEX4);
    clock_slow <= Clock;
    rom : rom_16x4_sync port map (clock => clock_slow, address => std_logic_vector(address_uns), rom_en => Rom_en, data_out => rom_out);



        State_Memory : process (clock_slow, Reset)
            begin
                if (Reset = '0') then
                    current_state <= start;
                elsif (clock_slow'event and clock_slow = '1') then
                            current_state <= next_state;
                end if;
            end process;

        NEXT_STATE_LOGIC : process (current_state)
                begin
                    case (current_state) is
                        when start => if (KEY0 = '0') then
                                            next_state <= read_rom;
                                        else next_state <= start;
                                                                              end if;
                                                when read_rom => if (address_counter = 15) then
                                                next_state <= clear_addr;
                                                else
                                                    address_counter <= address_counter + 1;
                                                end if;
                        when clear_addr => next_state <= done;
                                                 address_counter <= 0;
                        when done => next_state <= done;
                        end case;
                end process;

        OUTPUT_LOGIC : process (current_state)
            begin
                case (current_state) is
                    when start => Rom_en <= '0';
                                            addr_count_en <= '0';
                                            addr_count_clr <= '0';
                    when read_rom => Rom_en <= '1';
                                          addr_count_en <= '1';
                                          addr_count_clr <= '0';
                    when clear_addr => Rom_en <= '0';
                                            addr_count_en <= '1';
                                            addr_count_clr <= '1';
                    when done => Rom_en <= '0';
                                            addr_count_en <= '0';
                                            addr_count_clr <= '0';
                    end case;
            end process;



            Address_Count : process (addr_count_en, addr_count_clr, clock_slow)
                begin
                if (clock_slow'event and clock_slow = '1') then
                    if (addr_count_en = '1') then
                        if (addr_count_clr = '1') then
                            address_uns <= "0000";
                        else
                            address_uns <= address_uns + 1;
                        end if;
                    end if;
                end if;
            end process;
              address_uns <= to_unsigned(address_counter,4);



end architecture;

1 个答案:

答案 0 :(得分:0)

我评论了我的代码错误:

address_counter没有时钟并且是多余的。在过程address_uns中删除分配并将比较更改为NEXT_STATE_LOGIC(也应该进入敏感性列表)。在进程Address_Counter之后删除对address_uns的并发信号分配。如果进程Address_CountOUTPUT_LOGIC以及rom_16x4_sync是正确的,那么你应该有一些有用的东西。

好吧,我把大部分的点点滴滴从其他问题围绕着一个完整的MCVE,一点点努力,主要是复制和粘贴,这给了:

top_tb.png

正如您所看到的那样无效,原因是address_uns需要重置(它的默认值都是'U')。

添加重置可以:

top_tb_address_us_reset

因此,要点是你的状态机几乎是正确的,它在灵敏度列表中缺少地址计数器并且有两个地址计数器。将其限制为一个并重置它,这样您就不会在所有'U'中添加1表示您的状态机正在运行。

包含所有修复的代码:

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

entity char_decoder is
    port (
        bin_in:   in  std_logic_vector (3 downto 0);
        hex_out:  out std_logic_vector (6 downto 0)
    );
end entity;

architecture dummy of char_decoder is
    --  seven segment display
    --  
    --        a
    --     f      b
    --        g
    --     e      c
    --        d
    --
    --  SEGMENT is defined (g downto a)
    --
    type segment7 is array (integer range 0 to 15) of 
                                std_logic_vector (6 downto 0);

    constant hex_to_segment: segment7 := (
                 "1000000", -- 0
                 "1111001", -- 1
                 "0100100", -- 2
                 "0110000", -- 3
                 "0011001", -- 4
                 "0010010", -- 5
                 "0000010", -- 6
                 "1111000", -- 7
                 "0000000", -- 8
                 "0011000", -- 9
                 "0001000", -- A
                 "0000011", -- b
                 "0111001", -- C
                 "0100001", -- d
                 "0000110", -- E
                 "0001110"  -- F
             );
begin
    process (bin_in)
        variable seg7_val: integer range 0 to 15;
    begin
        seg7_val := to_integer(unsigned(bin_in));

        hex_out <= hex_to_segment(seg7_val);
    end process;
end architecture;

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

entity rom_16x4_sync is
    port (
        clock:    in  std_logic;
        address:  in  std_logic_vector (3 downto 0);
        rom_en:   in  std_logic;
        data_out: out std_logic_vector(3 downto 0)
    );
end entity;

architecture dummy of rom_16x4_sync is
    type rom_array is array (0 to 15) of std_logic_vector(3 downto 0);

    function fill_rom return rom_array is 
        variable ret_val:   rom_array;
    begin
        for i in rom_array'reverse_range loop  -- backward to i
            ret_val(i) := std_logic_vector(to_unsigned(i,4)); 
        end loop;
        return ret_val;
    end function;
    constant rom:   rom_array := fill_rom;
begin
    process (clock)
    begin
        if rising_edge(clock) and rom_en = '1' then  -- NO RESET
            data_out <= rom(to_integer(unsigned(address)));
        end if;
    end process;
end architecture;

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

entity top is
    port (
        clock:      in  std_logic;
        reset:      in  std_logic;
        sw:         in  std_logic_vector (1 downto 0);  -- not used?
        hex2, hex4: out std_logic_vector ( 6 downto 0);
        key0:       in  std_logic
    );
end entity;

architecture top_arch of top is

    component char_decoder is
        port (
            bin_in:   in  std_logic_vector (3 downto 0);
            hex_out:  out std_logic_vector (6 downto 0)
        );
    end component;

    component rom_16x4_sync is
        port (
            clock:    in  std_logic;
            address:  in  std_logic_vector (3 downto 0);
            rom_en:   in  std_logic;
            data_out: out std_logic_vector(3 downto 0)
        );
    end component;

    type state_type is (start,  read_rom, clear_addr, done);
    signal current_state, 
           next_state:          state_type;
    signal rom_en, 
           addr_count_clr, 
           addr_count_en:       std_logic;
    -- signal address_counter:     integer range 0 to 15;
    signal address_uns:         unsigned (3 downto 0);
    signal clock_slow:          std_logic;
    signal rom_out:             std_logic_vector (3 downto 0);

    begin

char:  
    char_decoder 
        port map (
            bin_in => rom_out, 
            hex_out => hex2
        );
char1:  
    char_decoder 
        port map (
            bin_in => std_logic_vector(address_uns), 
            hex_out => hex4
        );

    clock_slow <= clock;

rom:  
    rom_16x4_sync 
        port map (
            clock => clock_slow, 
            address => std_logic_vector(address_uns), 
            rom_en => rom_en, data_out => rom_out
        );

state_memory:  
    process (clock_slow, reset)
    begin
        if reset = '0' then
            current_state <= start;
        elsif clock_slow'event and clock_slow = '1' then
            current_state <= next_state;
        end if;
    end process;

next_state_logic:  
    -- process (current_state)
    process (current_state, address_uns)
    begin
        case (current_state) is
            when start => 
                if key0 = '0' then
                    next_state <= read_rom;
                else 
                    next_state <= start;
                end if;
            when read_rom => 
                if address_uns = 15 then
                    next_state <= clear_addr;
                -- else
                --    address_counter <= address_counter + 1;
                end if;
            when clear_addr =>   -- not a defined sequential logic inference
                next_state <= done;
                -- address_counter <= 0;
            when done => 
                next_state <= done;
        end case;
    end process;

output_logic:  
    process (current_state)
        begin
            case (current_state) is
                when start => 
                    rom_en <= '0';
                    addr_count_en <= '0';
                    addr_count_clr <= '0';
                when read_rom => 
                    rom_en <= '1';
                    addr_count_en <= '1';
                    addr_count_clr <= '0';
                when clear_addr => 
                    rom_en <= '0';
                    addr_count_en <= '1';
                    addr_count_clr <= '1';
                when done => 
                    rom_en <= '0';
                    addr_count_en <= '0';
                    addr_count_clr <= '0';
                end case;
        end process;

address_count:  
    process (addr_count_en, addr_count_clr, clock_slow)
    begin
        if reset = '0' then                   -- added reset
            address_uns <= (others =>'0');
        elsif clock_slow'event and clock_slow = '1' then
            if addr_count_en = '1' then
                if addr_count_clr = '1' then
                    address_uns <= "0000";
                else
                    address_uns <= address_uns + 1;
                end if;
            end if;
        end if;
    end process;

    -- address_uns <= to_unsigned(address_counter, 4);

end architecture;

library ieee;
use ieee.std_logic_1164.all;

entity top_tb is
end entity;

architecture foo of top_tb is
    signal clock:      std_logic := '0';
    signal reset:      std_logic := '1';
    signal sw:         std_logic_vector (1 downto 0) := "00";
    signal hex2, hex4: std_logic_vector ( 6 downto 0);
    signal key0:       std_logic := '0';
begin
DUT:
    entity work.top
        port map (
            clock => clock,
            reset => reset,
            sw => sw,
            hex2 => hex2,
            hex4 => hex4,
            key0 => key0
        );
CLK:
    process
    begin
        wait for 5 ns;    
        clock <= not clock;
        if now > 200 ns then
            wait;
        end if;    
    end process;

STIMULIS:
    process
    begin
        wait for 1 ns;
        reset <= '0';
        wait for 10 ns;
        reset <= '1';
        wait for 10 ns;
        wait;
    end process;
end architecture;

我使用的char_decoder应该是完全正常的。 ROM内容简直就是傻瓜了。