Vhdl 从同一语句中指定两个信号

Vhdl 从同一语句中指定两个信号,vhdl,Vhdl,我是VHDL新手,我正在尝试实现一个真值表,在ABEL中,它看起来像: Truth-table ([C2.FB, C1.FB, C0.FB, DISABLE] -> [A, B]) [ X , X , X , 1 ] -> [0, 0]; [ 0 , 0 , 0 , 0 ] -> [0, 3]; [ 0 , 0 , 1 , 0 ] -> [3, 5]; [ 0 , 1 ,

我是VHDL新手,我正在尝试实现一个真值表,在ABEL中,它看起来像:

Truth-table
([C2.FB, C1.FB, C0.FB, DISABLE] -> [A, B])
 [  X  ,  X   ,   X  ,    1   ] -> [0, 0];
 [  0  ,  0   ,   0  ,    0   ] -> [0, 3];
 [  0  ,  0   ,   1  ,    0   ] -> [3, 5];
 [  0  ,  1   ,   0  ,    0   ] -> [5, 6];
 [  0  ,  1   ,   1  ,    0   ] -> [6, 7];
 [  1  ,  0   ,   0  ,    0   ] -> [7, 6];
 [  1  ,  0   ,   1  ,    0   ] -> [6, 5];
 [  1  ,  1   ,   0  ,    0   ] -> [5, 3];
 [  1  ,  1   ,   1  ,    0   ] -> [3, 0];
从我所看到的情况来看,VHDL中并没有对真值表的真正支持,但“with select语句”可能是最接近的了

with C select
A <= std_logic_vector(to_unsigned(0, A'length)) when "000",
     std_logic_vector(to_unsigned(3, A'length)) when "001",
     std_logic_vector(to_unsigned(5, A'length)) when "010",
     std_logic_vector(to_unsigned(6, A'length)) when "011",
          ...
用C选择


A尝试使用case语句:

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

entity truth_table is
end entity;

architecture foo of truth_table is
    signal C0,C1,C2:    std_logic;
    signal DISABLE:     std_logic;

    signal A:           std_logic_vector(2 downto 0);
    signal B:           std_logic_vector(2 downto 0);

begin
TT:
    process(C0,C1,C2,DISABLE)
        variable a_int:  integer range 0 to 7;
        variable b_int:  integer range 0 to 7;
        type ab_pair is array (0 to 1) of integer range 0 to 7;
        variable CD:    std_logic_vector(3 downto 0);

    begin
        CD := (C2 & C1 & C0 & DISABLE);
        case CD  is
            when "0000" => (a_int, b_int) := ab_pair'(0,7);
            when "0010" => (a_int, b_int) := ab_pair'(1,6);
            when "0100" => (a_int, b_int) := ab_pair'(2,5);
            when "0110" => (a_int, b_int) := ab_pair'(3,4);
            when "1000" => (a_int, b_int) := ab_pair'(4,3);
            when "1010" => (a_int, b_int) := ab_pair'(5,2);
            when "1100" => (a_int, b_int) := ab_pair'(6,1);
            when "1110" => (a_int, b_int) := ab_pair'(7,0);
            when others => (a_int, b_int) := ab_pair'(0,0); 
        end case;
       A <= std_logic_vector(to_unsigned(a_int,A'LENGTH));
       B <= std_logic_vector(to_unsigned(b_int,B'LENGTH));

    end process;
end architecture;
ieee库;
使用ieee.std_logic_1164.all;
使用ieee.numeric_std.all;
实体真值表是
终端实体;
真值表的架构是
信号C0、C1、C2:std_逻辑;
信号禁用:标准逻辑;
信号A:标准逻辑向量(2到0);
信号B:标准逻辑向量(2到0);
开始
TT:
过程(C0、C1、C2、禁用)
变量a_int:0到7的整数范围;
变量b_int:0到7的整数范围;
ab_对类型是整数范围为0到7的数组(0到1);
变量CD:std_逻辑_向量(3到0);
开始
CD:=(C2和C1以及C0和禁用);
案例CD是
当“0000”=>(a_int,b_int):=ab_对(0,7);
当“0010”=>(a_int,b_int):=ab_对(1,6);
当“0100”=>(a_int,b_int):=ab_对(2,5);
当“0110”=>(a_int,b_int):=ab_对(3,4);
当“1000”=>(a_int,b_int):=ab_对(4,3);
当“1010”=>(a_int,b_int):=ab_对(5,2);
当“1100”=>(a_int,b_int):=ab_对(6,1);
当“1110”=>(a_int,b_int):=ab_对(7,0);
当其他=>(a_int,b_int):=ab_pair'(0,0);
终例;

如果有预定义的VHDL机制,为什么要使用真值表

B <= "000" when (disable = '1') else A;
C <= "000" when (disable = '1') else not A;
现在您可以将上面的语句写得稍微短一点:

B <= ite((disable = '1'), "000", A);
C <= ite((disable = '1'), "000", not A);
编辑1 计算多个结果的组合过程

process(inA, inB, ...)
begin
  -- default assignments
  outX <= '0';
  outY <= '0';
  outZ <= '0';

  case (inA & inB) is
    when "00" =>
      outY <= '1';
      outZ <= '1';
    when "01" =>
      outX <= '1';
      outY <= '1';
    [...]
    when others =>
      outZ <= '1';
  end case;
end process;
过程(inA、inB等)
开始
--默认分配

outX如果您的合成工具支持VHDL-2008中的
case?
语句(用于 例如Altera Quartus II 13.1版),则可以使用“不在乎”(
“-”
) 在
std_逻辑中编码作为真值表中用作“X”的编码。
代码是:

端口(
c_i:标准逻辑向量(2到0);
禁用_i:在标准_逻辑中;
a_o:输出标准逻辑向量(2到0);
b_o:out标准逻辑向量(2到0);
...
过程(全部)是
类型对是记录
a:std_逻辑_向量(a_o'范围);
b:标准逻辑向量(b_o’范围);
结束记录;
开始
案例c_i&disable_i is

当“--1”=>(a_o,b_o)(a_o,b_o)(a_o,b_o)(a_o,b_o)看到一些好的指导。您试图做的是合法的,但语法有点复杂。还值得注意的是,在您的特定情况下,
a=C
,和
B=not C
启用时,但这并不是您所要求的。不过,偶尔的快捷方式也没什么错……没错:)我只是添加了A和B的值作为示例。在“现实世界”中,它们将是另一回事。请记住,您可以将信号(包括向量片段)连接到新向量中。这允许您使用X select在
构造中拥有所有(且仅)相关位。唯一真正的限制是缺乏对“不在乎”的支持。您可以使用
std\u match
函数绕过这一点(支持std\u逻辑的不在乎
-
),但这仅适用于使用布尔求值的if/elsif或when/else树。您还可以在select中指定一个聚合std_逻辑_向量,并将其拆分为您稍后需要的部分。请参阅,和P1076,它目前因缺少冠军而备受煎熬。您还可以使用条件赋值语句将disable滑入其中,或在VHDL-2008中使用disable将if语句中的赋值包围起来(该语句将所选信号赋值和条件信号赋值作为顺序语句接受)。还有一个很好的旧案例陈述。我意识到我的例子并不完美,因为我设计了真值表,使A=C和B=not C。问题是如何以最佳方式实现真值表,以及是否有可能同时分配两个信号,所以我现在将A和B的值更改为使真值表更合理一点。@Quist好的,所以如果你的函数更复杂,我仍然建议使用ROM,如果必要的话,使用一个函数或一组函数来计算ROMs内容。ROM的优点:a)真值表是ROM;b) ROM映射到LUT中,或者如果需要映射到LUT ROM中,或者如果功能非常大,映射到(只读)块RAM中;c) ROM在arch中有描述。头不会填满身体;d) 通过泛型计算每个函数的ROM是灵活的| case语句的缺点:a)有时需要更多的代码行;b) 请求。过程;c) 不可扩展为泛型函数。关于问题的第二点:返回多个结果:如果多个结果在语义上相互关联,则有可能在一个“访问”中返回所有结果。要做到这一点,您可以使用a)David Koontz和Morten Zimer的基于记录的解决方案,或b)请参阅我的“编辑1”,了解使用案例语句的组合过程。请随意组合几种描述:)感谢您的广泛回复!对于ROM,您是指寻址外部ROM,还是指通过以某种特殊方式编写VHDL代码,在FPGA中创建/分配ROM优化硬件?我是新来的,你知道……是的,ROM是指编写VHDL的特殊情况。那么ROM的本质是什么呢?它是只读的,其数据通过地址/选择信号访问。在大多数情况下,这类代码被映射到只读的LUT或LUT基RAM块(LUT-RAM)。我的例子B谢谢!但是我在Xilinx(ISE)上。有趣的是,Xilinx仍然缺乏对VHDL-2008的支持。似乎伊瑟永远也得不到它。
function ite(condition : boolean; a : std_logic_vector; b : std_logic_vector) return std_logic_vector is
begin
  if (cond = true) then
    return a;
  else
    return b;
  end if;
end function;
B <= ite((disable = '1'), "000", A);
C <= ite((disable = '1'), "000", not A);
B <= (A'range => disable) and A;
C <= (A'range => disable) and not A;
subtype t_uint3 : integer range 0 to 7;
type t_uint3_vector is array (natural range <>) of t_uint3;
constant B_TRUTH_TABLE : t_uint3_vector(7 downto 0) := (0, 1, 2, 3, 4, 5, 6, 7);
constant C_TRUTH_TABLE : t_uint3_vector(7 downto 0) := (7, 6, 5, 4, 3, 2, 1, 0);

B <= B_TRUTH_TABLE(to_integer(unsigned(A)));
C <= C_TRUTH_TABLE(to_integer(unsigned(A)));
function precalc_B_ROM return t_uint3_vector is
  variable result : t_uint3_vector(7 downto 0);
begin
  for i in result'range loop
    result(i) := i;
  end loop;
  return result;
end function;

function precalc_C_ROM return t_uint3_vector is
  variable result : t_uint3_vector(7 downto 0);
begin
  for i in result'range loop
    result(i) := result'high - i;  -- reverse numbers
  end loop;
  return result;
end function;

constant B_TRUTH_TABLE : t_uint3_vector(7 downto 0) := precalc_B_ROM;
constant C_TRUTH_TABLE : t_uint3_vector(7 downto 0) := precalc_C_ROM;
process(inA, inB, ...)
begin
  -- default assignments
  outX <= '0';
  outY <= '0';
  outZ <= '0';

  case (inA & inB) is
    when "00" =>
      outY <= '1';
      outZ <= '1';
    when "01" =>
      outX <= '1';
      outY <= '1';
    [...]
    when others =>
      outZ <= '1';
  end case;
end process;
port(
  c_i       : in  std_logic_vector(2 downto 0);
  disable_i : in std_logic;
  a_o       : out std_logic_vector(2 downto 0);
  b_o       : out std_logic_vector(2 downto 0));
...
process (all) is
  type pair_t is record
    a : std_logic_vector(a_o'range);
    b : std_logic_vector(b_o'range);
  end record;
begin
  case? c_i & disable_i is
    when "---1" => (a_o, b_o) <= pair_t'(3X"0", 3X"0");
    when "0000" => (a_o, b_o) <= pair_t'(3X"0", 3X"7");
    when "0010" => (a_o, b_o) <= pair_t'(3X"1", 3X"6");
    when "0100" => (a_o, b_o) <= pair_t'(3X"2", 3X"5");
    when "0110" => (a_o, b_o) <= pair_t'(3X"3", 3X"4");
    when "1000" => (a_o, b_o) <= pair_t'(3X"4", 3X"3");
    when "1010" => (a_o, b_o) <= pair_t'(3X"5", 3X"2");
    when "1100" => (a_o, b_o) <= pair_t'(3X"6", 3X"1");
    when "1110" => (a_o, b_o) <= pair_t'(3X"7", 3X"0");
    when others => (a_o, b_o) <= pair_t'("XXX", "XXX");
  end case?;
end process;