1

我有一个实体,它查看五对开关并根据这些开关的状态(Hfor 00Efor 01Lfor10Ofor 11)在 7 段显示器上设置字母。

我在这个文件的体系结构中有一个进程,它有一个 case 语句,它查看开关的值并将正确的字母写入相应的显示。

现在,我还有三个开关,它们将根据它们的状态将字母移动到相邻的 7 段显示器(如旋转)。我最初在同一架构内的另一个进程中拥有此功能,但由于我在两个不同的地方使用输出(7 段显示器)而出现编译错误。

我对 VHDL 完全陌生,所以这看起来很简单,但是我如何分离这两个功能呢?他们需要在不同的文件中吗?如何让它们“同时”运行?

4

3 回答 3

1

像这样的东西(警告它没有被调试,它分析和阐述)。

这表明存在用于显示数字的寄存器,并且旋转功能在这些寄存器的输出和驱动的显示数字端口之间运行。

rot_select 当然可以与写指针分开。

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

entity rot_digits is
    port (
    -- the 8 7-segment display with defaults for simulation visibility.
        dp0:    out std_logic_vector (6 downto 0) := "0000001"; -- 0
        dp1:    out std_logic_vector (6 downto 0) := "1001111"; -- 1
        dp2:    out std_logic_vector (6 downto 0) := "0010010"; -- 2
        dp3:    out std_logic_vector (6 downto 0) := "0000110"; -- 3
        dp4:    out std_logic_vector (6 downto 0) := "1001100"; -- 4
        dp5:    out std_logic_vector (6 downto 0) := "0100100"; -- 5
        dp6:    out std_logic_vector (6 downto 0) := "0100000"; -- 6
        dp7:    out std_logic_vector (6 downto 0) := "0001111"; -- 7
  -- rotation select, also used for write pointer
        rot_select: in  std_logic_vector(2 downto 0);
        wr_enab:    in  std_logic;
        reset:      in  std_logic;
        switch:     in  std_logic_vector(1 downto 0)  
    );
    type display8 is array (integer range 0 to 7) of 
            std_logic_vector(6 downto 0);

    constant H:         std_logic_vector (6 downto 0) := "1001000"; -- H
    constant E:         std_logic_vector (6 downto 0) := "0110000"; -- E
    constant L:         std_logic_vector (6 downto 0) := "1110001"; -- L
    constant O:         std_logic_vector (6 downto 0) := "0000001"; -- O (0)
    constant ERR:       std_logic_vector (6 downto 0) := "0110110"; -- error
    constant BLANK:     std_logic_vector (6 downto 0) := "1111111";       

end entity;

architecture foo of rot_digits is

    -- digit is (a,b,c,d,e,f,g)  6 downto 0, '0' for ON (sink)
    --    a
    --   f  b
    --    g
    --   e  c
    --    d

    -- (d0,d1,d2,d3,d4,d5,d6,d7) are register values for stored digits
    signal d0:          std_logic_vector (6 downto 0);
    signal d1:          std_logic_vector (6 downto 0);
    signal d2:          std_logic_vector (6 downto 0);
    signal d3:          std_logic_vector (6 downto 0);
    signal d4:          std_logic_vector (6 downto 0);
    signal d5:          std_logic_vector (6 downto 0);  
    signal d6:          std_logic_vector (6 downto 0);
    signal d7:          std_logic_vector (6 downto 0);

    function "ror" (l: display8; r: std_logic_vector(2 downto 0))  
        return display8 is
        variable rot: integer range 0 to 7;
    begin
        if IS_X(TO_X01(r)) then   -- unknown defaults to 0 rotation
            rot := 0;
        else
            rot := to_integer(unsigned(r));
        end if;

        case rot is
            when 0 => return l;
            when 1 => return 
                display8'(l(0),l(7),l(6),l(5),L(4),l(3),l(2),l(1));
            when 2 => return 
                display8'(l(1),l(0),l(7),l(6),l(5),L(4),l(3),l(2));            
            when 3 => return 
                display8'(l(2),l(1),l(0),l(7),l(6),l(5),L(4),l(3));  
            when 4 => return 
                display8'(l(3),l(2),l(1),l(0),l(7),l(6),l(5),L(4));    
            when 5 => return 
                display8'(l(4),l(3),l(2),l(1),l(0),l(7),l(6),l(5)); 
            when 6 => return 
                display8'(l(5),l(4),l(3),l(2),l(1),l(0),l(7),l(6));   
            when 7 => return 
                display8'(l(6),l(5),l(4),l(3),l(2),l(1),l(0),l(7));
        end case;
    end function;

    signal selected:   std_logic_vector (6 downto 0);

begin

SEL:
    selected <= H    when switch = "00" else
                E    when switch = "01" else
                L    when switch = "10" else
                O    when switch = "11" else
                ERR;

ROTATE:
    (dp0,dp1,dp2,dp3,dp4,dp5,dp6,dp7) 
            <= display8'(d0,d1,d2,d3,d4,d5,d6,d7) ror rot_select;

Display_Registers:
    process (wr_enab,reset, switch)
    begin
        if (reset = '1') then
            (d0,d1,d2,d3,d4,d5,d6,d7) <= display8'(others => BLANK);
        elsif (wr_enab = '1') then
            case rot_select  is
                when "000" => d0 <= selected;
                when "001" => d1 <= selected;
                when "010" => d2 <= selected;
                when "011" => d3 <= selected;
                when "100" => d4 <= selected;
                when "101" => d5 <= selected;
                when "110" => d6 <= selected;
                when "111" => d7 <= selected;
                when others =>
                    (d0,d1,d2,d3,d4,d5,d6,d7) <= display8'(others => ERR);
             end case;  


        end if;
    end process;

end architecture;

ERR 分配将显示 rot_select 或 switch 向量中存在“0”或“1”以外的值。应该是三个单杠。

根据定义,将并发信号分配给显示数字输出端口有一个等效的过程。您也可以让该过程在没有新声明的“ror”移位运算符的情况下执行旋转。

于 2013-09-18T01:55:14.647 回答
1

如果你从两个不同的进程驱动一个信号,这两个驱动程序就会“竞争”。

对于bitandstd_ulogic类型,编译器会抱怨你不允许在一个信号上有两个驱动程序。如果您使用std_logic类型,那么有一个“分辨率函数”,它决定当您将两个不同的值驱动到信号上时结果值是什么。例如,如果您驾驶 a0和 a 1,您将得到定义未知的结果X

可以将Z(高阻抗)驱动到一个信号上以允许另一个信号覆盖它,但是,如果您想合成它,您需要检查您的工具将如何处理它,因为如今很少有芯片可以真正拥有其内部信号的高阻抗模式。

实现您想要的一种可移植、整洁、可综合的方法是将逻辑1视为不如逻辑强0。然后,您可以将两个单独的信号与 AND 门组合:

process1: process 
begin
   sig1 <= '1'; -- not driving 
   -- some statemachine eventually does
     sig1 <= '0';
   -- and then 
     sig1 <= '1'; -- when it's finished
end process;

process2: process
begin
    sig2 <= '1'; -- not driving
       --- similarly...
       sig2 <= '0'; -- at some point
end process;

actual_sig <= sig1 and sig2;

如果将 a0设置为“空闲”状态对您的目的更有意义,则使用“或”代替将信号合并在一起。

于 2013-09-18T11:06:56.723 回答
1

我将尝试更多地专注于解决您的问题,而不是回答您的原始问题。有关您的问题的良好答案,请参阅 Martin (@martin-thompson) 的帖子。

所提出的解决方案的关键是生成一个中间信号,它将保存“旋转”的字母。简而言之:

  • 信号 #1 <= 字母数组,无需旋转,直接从您的开关对中选择
  • 信号 #2 <= 旋转字母数组;旋转量来自你的“旋转”开关

这样,我们可以有一个进程生成信号#1,而另一个进程生成信号#2。通常最好构造您的解决方案,以便从单个进程中分配每个信号。

下面的代码应该可以解决您的问题:

entity switches_to_7seg is
    port (
        -- each switch pair selects one letter from 'H', 'E', 'L', 'O'
        switch_pair_0: in bit_vector(1 downto 0);
        switch_pair_1: in bit_vector(1 downto 0);
        switch_pair_2: in bit_vector(1 downto 0);
        switch_pair_3: in bit_vector(1 downto 0);
        switch_pair_4: in bit_vector(1 downto 0);
        -- the rotation switches select the amount of rotation from 0 to 4
        rotate_switches: in bit_vector(2 downto 0);
        -- the outputs are five 7-segment displays
        lcd_display_0: out bit_vector(6 downto 0);
        lcd_display_1: out bit_vector(6 downto 0);
        lcd_display_2: out bit_vector(6 downto 0);
        lcd_display_3: out bit_vector(6 downto 0);
        lcd_display_4: out bit_vector(6 downto 0)
    );
end;

architecture dataflow of switches_to_7seg is

    -- declare an enumerated type to make it easier working with the output letters
    type output_letter_type is ('H', 'E', 'L', 'O');
    type output_letter_vector_type is array (natural range <>) of output_letter_type;

    -- this comes directly from the switches
    signal switch_selected_letters: output_letter_vector_type(0 to 4);
    -- this is an intermediary signal, with the letters rotated
    signal rotated_letters: output_letter_vector_type(0 to 4);

    -- return a letter corresponding to the state of a pair of switches
    function output_letter_from_bit_vector(bits: bit_vector) return output_letter_type is
    begin
        case bits is
        when "00" => return 'H';
        when "01" => return 'E';
        when "10" => return 'L';
        when "11" => return 'O';
        end case;
    end;

    -- return a value for driving a 7-segment display to show the corresponding letter
    function seven_seg_from_output_letter(letter: output_letter_type) return bit_vector is
    begin
        case letter is
        when 'H' => return "0110111";
        when 'E' => return "1001111";
        when 'L' => return "0001110";
        when 'O' => return "1111110";
        end case;
    end;

begin

    -- this first part reads the input switches and convert them to letters
    switch_selected_letters(0) <= output_letter_from_bit_vector(switch_pair_0);
    switch_selected_letters(1) <= output_letter_from_bit_vector(switch_pair_1);
    switch_selected_letters(2) <= output_letter_from_bit_vector(switch_pair_2);
    switch_selected_letters(3) <= output_letter_from_bit_vector(switch_pair_3);
    switch_selected_letters(4) <= output_letter_from_bit_vector(switch_pair_4);

    -- this first process generates the intermediary signal 'rotated_letters'
    rotate_letters: process (all) begin
        case rotate_switches is
        when "000" =>
            rotated_letters <= switch_selected_letters;
        when "001" =>
            rotated_letters <= switch_selected_letters(1 to 4) & switch_selected_letters(0);
        when "010" =>
            rotated_letters <= switch_selected_letters(2 to 4) & switch_selected_letters(0 to 1);
        when "011" =>
            rotated_letters <= switch_selected_letters(3 to 4) & switch_selected_letters(0 to 2);
        when "100" =>
            rotated_letters <= switch_selected_letters(4) & switch_selected_letters(0 to 3);
        when others =>
            rotated_letters <= switch_selected_letters;
        end case;
    end process;

    -- this second process outputs the rotated letters to the displays
    output_letters: process (all) begin
        lcd_display_0 <= seven_seg_from_output_letter( rotated_letters(0) );
        lcd_display_1 <= seven_seg_from_output_letter( rotated_letters(1) );
        lcd_display_2 <= seven_seg_from_output_letter( rotated_letters(2) );
        lcd_display_3 <= seven_seg_from_output_letter( rotated_letters(3) );
        lcd_display_4 <= seven_seg_from_output_letter( rotated_letters(4) );
    end process;

end;
于 2013-09-18T20:27:26.003 回答