【问题标题】:Modelsim Altera VHDL MEMORY ROMModelsim Altera VHDL 存储器 ROM
【发布时间】:2016-06-24 23:44:09
【问题描述】:

我对为什么我的 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;

【问题讨论】:

  • 请同时发布您的测试平台。你遇到的具体问题是什么?我怀疑,你的时钟太快了,无法区分十六进制输出。
  • 请创建一个Minimal, Complete, and Verifiable example,因为这将极大地帮助您找到有用的答案,而且您在此过程中甚至可能自己找到答案。
  • Some questions are still off-topic... 1. 寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定问题或错误以及在问题本身。没有明确问题陈述的问题对其他读者没有用处。请参阅:How to create a Minimal, Complete, and Verifiable example
  • 如果没有明确的问题陈述或 mcve,只能发表评论。 address_counter 没有时钟并且是多余的。在进程NEXT_STATE_LOGIC 中删除分配并将比较更改为address_uns(也应该进入敏感列表)。在处理Address_Counter 之后,删除对address_uns 的并发信号分配。如果进程Address_CountOUTPUT_LOGIC 以及rom_16x4_sync 都是正确的,那么你应该有一些可以工作的东西。 (如果没有 mcve,第二方无法确定)。

标签: vhdl counter fsm rom


【解决方案1】:

我评论了我认为您的代码有什么问题:

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

嗯,我把其他问题的大部分零碎放在一边,通过复制和粘贴几乎不费力气地生成一个完整的 MCVE,结果:

如您所见,这不起作用,原因是需要重置address_uns(它的默认值都是'U')。

添加重置会给出:

所以这个要点是你的状态机几乎是正确的,它在它的敏感列表中缺少地址计数器并且有两个地址计数器。将其限制为 1 并重置它,这样您就不会将 1 添加到所有 'U' 表明您的状态机正在工作。

以及所有修复的代码:

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 的内容只是简单地虚拟化了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    相关资源
    最近更新 更多