我通过论坛搜索找到了一个关闭的错误example,所以我会尝试做一个更好的,对任何有相同问题的人都有用。
我是VHDL的新手。到目前为止,我只使用XILINX System Generator来编程FPGA,这非常简单,但实际上并不适合我的编码习惯。我使用dS5203 FPGA板(随意搜索数据表,堆栈溢出不会让我链接它..)。我所有关于VHDL的信息都是在自学中学习的,所以请随时纠正我所犯的任何基本错误。我会尽可能多地更新这个问题,以便从中创建一个有用的问题。
请在回答我的任何问题之前阅读全文,因为我有些错误是为了从中得到具体答案而添加的。
我的任务是转换所以如果否则代码从C到VHDL。我可以简单地这样做,如果我没有错,代码的部分应该是这样的:
V1 : process
begin -- code will be marked in the Graph's as:
if (a<=b) then -- seq1
var1 <= nr1;
var2 <= nr2;
elsif (c<=d) then -- seq2
var1 <= nr3;
var2 <= nr4;
var3 <= nr5;
elsif (d<=f) then -- seq3
var2 <= nr6;
var3 <= nr7;
else -- seq4
var3 <= nr8;
end if;
end if;
end if;
end process V1;
所有变量(var 1-x,nr1-x是相同的类型) : 如果我没有完全错,那么生成的硬件应该看起来像这样 click
结果是每个“if .. then”有一个延迟(实际函数包含超过15个,如果那么命令)。
第一个“子问题”:
1:“单个if ... then”中的“多个语句”是否有效?由于我认为我知道多路复用器是如何工作的,所以我认为不可能通过一个命令打多个命令。
2:“忽略”某些变量(seq1,即忽略var3)是否会产生“锁存行为”?我希望将旧值保留在该变量中,我认为这应该发生。
为了消除延迟我想到以下尝试将其转换为案例......是:
variable sel : std_logic_vector (2 downto 0); --selector variable to steer mux behavior
S1: process(a,b)
begin
if a <= b then
sel(2) <= 1;
else
sel(0) <= 0;
endif;
end process S1;
S2: process(c,d)
begin
if c <= d then
sel(1) <= 1;
else
sel(1) <= 0;
endif;
end process S2;
S3: process(e,f)
begin
if e <= f then
sel(2) <= 1;
else
sel(2) <= 0;
endif;
end process S3;
C1 : process (sel)
begin
case sel is
when "000"
var3 <= nr8;
when "001"
var2 <= nr6;
var3 <= nr7;
when "010" | "011"
var1 <= nr3;
var2 <= nr4;
var3 <= nr5;
when "100" | "101" | "111" | "110"
var1 <= nr1;
var2 <= nr2;
end case;
end process C1;
同样,结果应该看起来像这样: click
这样,无论我添加多少if / else标准,我总是会有2的延迟。它只会向sel变量添加位。 (并创建了很多代码,但我更喜欢性能/更低的延迟)
更多“子问题”:
3:有没有办法直接使用&lt; =?因为它被用作“写入”命令,我试图通过“if then else”来解决。有更简单的方法吗?
4:我是否需要添加一种延迟?由于第一阶段是&lt; =运算符,因此将创建1的延迟
这些都是我迟早能够自己回答的问题。随意回答或给出提示;)真正的问题是我在这里买了:
如何通过该巨型多路复用器的单个通道推送多个语句?(基本上)同样的问题,如问题号。 1)。正如在代码中所评论的那样,我希望每个推送多个不同的变量/信号..然后。但由于存在不同数量的声明,因此总线信号不会起作用。 我无法想象这会以某种方式工作,并且不知道如何解决这个问题。我是否以错误的方式思考?
作为一名新手我很高兴看到你的答案! 来自德国的问候。
编辑:下面再次使用user1155120的包含代码的相同功能
---------------------------------------------------------------------------------------------------------------------------------------------------------
-- a giant THANK YOU! to user1155120
---------------------------------------------------------------------------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ifcase is -- ports
port (
in1: in std_logic_vector (15 downto 0); -- 16 bit to get precise real type values
in2: in std_logic_vector (15 downto 0);
in3: in std_logic_vector (15 downto 0);
in4: in std_logic_vector (15 downto 0);
in5: in std_logic_vector (15 downto 0);
in6: in std_logic_vector (15 downto 0);
in7: in std_logic_vector (15 downto 0);
in8: in std_logic_vector (15 downto 0);
a: in unsigned (7 downto 0); -- arbitrary 8 bit size
b: in unsigned (7 downto 0);
c: in unsigned (7 downto 0);
d: in unsigned (7 downto 0);
e: in unsigned (7 downto 0);
f: in unsigned (7 downto 0);
out1: out std_logic_vector (15 downto 0); -- DS5203 needs std_logic or std_logic vector
out2: out std_logic_vector (15 downto 0);
out3: out std_logic_vector (15 downto 0);
);
end entity;
architecture foo of ifcase is
variable nr1: real (15 downto 0); -- not shure if I have or have not to add the (15 downto 0) for real values.
variable nr2: real (15 downto 0);
variable nr3: real (15 downto 0);
variable nr4: real (15 downto 0);
variable nr5: real (15 downto 0);
variable nr6: real (15 downto 0);
variable nr7: real (15 downto 0);
variable nr8: real (15 downto 0);
signal var1: real (15 downto 0);
signal var2: real (15 downto 0);
signal var3: real (15 downto 0);
function to_string (inp: std_logic_vector) return string is
variable image_str: string (1 to inp'length);
alias input_str: std_logic_vector (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
end loop;
return image_str;
end function;
begin
typecon_fwd:
process (in1, in2, in3, in4, in5, in6, in7, in8)
begin
nr1 <= REAL(CONV_INTEGER(UNSIGNED(in1)))/65535.0; -- x/(2^16 -1) = x/(65535) represents 16 bit real type number between 1 and 0(if i'm not wrong)
nr2 <= REAL(CONV_INTEGER(UNSIGNED(in2)))/65535.0; -- should this happen lice this or in architecture?
nr3 <= REAL(CONV_INTEGER(UNSIGNED(in3)))/65535.0;
nr4 <= REAL(CONV_INTEGER(UNSIGNED(in4)))/65535.0;
nr5 <= REAL(CONV_INTEGER(UNSIGNED(in5)))/65535.0;
nr6 <= REAL(CONV_INTEGER(UNSIGNED(in6)))/65535.0;
nr7 <= REAL(CONV_INTEGER(UNSIGNED(in7)))/65535.0;
nr8 <= REAL(CONV_INTEGER(UNSIGNED(in8)))/65535.0;
end process;
ifstatement: -- definetly the shortest and easiest to understand coding way, thank you user1155120, THIS HERE WAS MADE THE WRONG WAY TO SHOW MY PROBLEM :)
process (nr1, nr2, nr3, nr4, nr5, nr6, nr7, nr8, a, b, c, d, e, f)
begin
if a <= b then
var1 <= nr1;
var2 <= nr2;
elsif c <= d then
var1 <= nr3;
var2 <= nr4;
var3 <= nr5;
elsif e <= f then
var2 <= nr6;
var3 <= nr7;
else
var3 <= nr8;
end if;
end process;
MONITOR_IF:
process (if_result)
begin
report "if_result1 = " & to_string(var1);
report "if_result2 = " & to_string(var2);
report "if_result3 = " & to_string(var3);
end process;
out1 <= var1;
out1 <= var1;
out1 <= var1;
end architecture;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ifcase_tb is -- the testbench
end entity;
architecture foo of ifcase_tb is
--default in values: random numbers, just to show
signal in1: std_logic_vector (15 downto 0) := "0000000000000001";
signal in2: std_logic_vector (15 downto 0) := "0000000000000100";
signal in3: std_logic_vector (15 downto 0) := "0000000000010000";
signal in4: std_logic_vector (15 downto 0) := "0000000010000000";
signal in5: std_logic_vector (15 downto 0) := "0000000100000000";
signal in6: std_logic_vector (15 downto 0) := "0000100000000000";
signal in7: std_logic_vector (15 downto 0) := "0001000000000000";
signal in8: std_logic_vector (15 downto 0) := "1000000000000000";
-- I don't get this one, why all bits to 1 or 0?
signal a: unsigned (7 downto 0) := (others => '1');
signal b: unsigned (7 downto 0) := (others => '0');
signal c: unsigned (7 downto 0) := (others => '1');
signal d: unsigned (7 downto 0) := (others => '0');
signal e: unsigned (7 downto 0) := (others => '1');
signal f: unsigned (7 downto 0) := (others => '0');
signal out1: std_logic_vector (15 downto 0);
signal out2: std_logic_vector (15 downto 0);
signal out3: std_logic_vector (15 downto 0);
function to_string (inp: std_logic_vector) return string is
variable image_str: string (1 to inp'length);
alias input_str: std_logic_vector (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
end loop;
return image_str;
end function;
begin
DUT:
entity work.ifcase
port map (
in1 => in1,
in2 => in2,
in3 => in3,
in4 => in4,
in5 => in5,
in6 => in6,
in7 => in7,
in8 => in8,
a => a,
b => b,
c => c,
d => d,
e => e,
f => f,
result => result
);
STIMULIS:
process -- is this made to synchronize the signals or just to show delay functionality?
begin
wait for 10 ns;
a <= (others => '0'); -- now equal gives seq1
wait for 10 ns;
a <= (others => '1'); -- undo
c <= (others => '0'); -- now equal gives seq2
wait for 10 ns;
c <= (others => '1'); -- undo
e <= (others => '0'); -- now equal gives seq3
wait for 10 ns;
e <= (others => '1'); -- undo
wait for 10 ns; -- displays seq4 again
wait;
end process;
MONTIOR:
process (result)
begin
report "result = " & to_string(result);
end process;
end architecture;
答案 0 :(得分:1)
您的if语句流程V1与您的第一张图片不匹配:
在这两种情况下,您的VHDL代码都不是很有效。案例陈述接近第二张图片:
case语句可以用if then-else if then -else语句结构表示,但有几点需要注意。只执行一个选项(elsif),并且所有被评估的值都属于同一个子类型,您可以在其中使用SEL作为计算表达式。
可以编写if语句以匹配第一个图像,并使用case语句匹配第二个图像:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ifcase is
port (
seq1: in std_logic_vector (3 downto 0); -- a token size
seq2: in std_logic_vector (3 downto 0);
seq3: in std_logic_vector (3 downto 0);
seq4: in std_logic_vector (3 downto 0);
a: in unsigned (7 downto 0); -- also arbitrary size
b: in unsigned (7 downto 0);
c: in unsigned (7 downto 0);
d: in unsigned (7 downto 0);
e: in unsigned (7 downto 0);
f: in unsigned (7 downto 0);
result: out std_logic_vector (3 downto 0)
);
end entity;
architecture foo of ifcase is
signal if_result: std_logic_vector (3 downto 0);
signal case_result: std_logic_vector (3 downto 0);
signal case2_result: std_logic_vector (3 downto 0);
signal a_lteq_b: bit;
signal c_lteq_d: bit;
signal e_lteq_f: bit;
function to_string (inp: std_logic_vector) return string is
variable image_str: string (1 to inp'length);
alias input_str: std_logic_vector (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
end loop;
return image_str;
end function;
begin
ifstatement: -- This matchs your image block diagram
process (seq1, seq2, seq3, seq4, a, b, c, d, e, f)
begin
if a <= b then
if_result <= seq1;
elsif c <= d then
if_result <= seq2;
elsif e <= f then
if_result <= seq3;
else
if_result <= seq4;
end if;
end process;
casestatement: -- This should match the above if statement
process (seq1, seq2, seq3, seq4, a, b, c, d, e, f)
variable sel: bit_vector (1 downto 0); -- no others choice
begin
if a <= b then -- notice this matches ifstatement
sel := "00";
elsif c <= d then
sel := "01";
elsif e <= f then
sel := "10";
else
sel := "11";
end if;
case sel is
when "00" =>
case_result <= seq1;
when "01" =>
case_result <= seq2;
when "10" =>
case_result <= seq3;
when "11" =>
case_result <= seq4; -- all bit values of sel shown
end case; -- no others choice required
end process;
a_lteq_b <= '1' when a <= b else
'0';
c_lteq_d <= '1' when c <= d else
'0';
e_lteq_f <= '1' when e <= f else
'0';
case2statement: -- This should matches the second image
process (seq1, seq2, seq3, seq4, a_lteq_b, c_lteq_d, e_lteq_f)
variable sel: bit_vector (2 downto 0);
begin
sel := a_lteq_b & c_lteq_d & e_lteq_f;
case sel is
when "100" | "101" | "110" | "111" =>
case2_result <= seq1;
when "010" | "011" =>
case2_result <= seq2;
when "001" =>
case2_result <= seq3;
when "000" =>
case2_result <= seq4;
end case;
end process;
MONITOR_IF:
process (if_result)
begin
report "if_result = " & to_string(if_result);
end process;
MONITOR_CASE:
process (case_result)
begin
report "case_result = " & to_string(case_result);
end process;
MONITOR_CASE2:
process (case2_result)
begin
report "case2_result = " & to_string(case2_result);
end process;
result <= if_result; -- pick one
end architecture;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ifcase_tb is -- the testbench
end entity;
architecture foo of ifcase_tb is
signal seq1: std_logic_vector (3 downto 0) := "0001";
signal seq2: std_logic_vector (3 downto 0) := "0010";
signal seq3: std_logic_vector (3 downto 0) := "0011";
signal seq4: std_logic_vector (3 downto 0) := "0100";
signal a: unsigned (7 downto 0) := (others => '1');
signal b: unsigned (7 downto 0) := (others => '0');
signal c: unsigned (7 downto 0) := (others => '1');
signal d: unsigned (7 downto 0) := (others => '0');
signal e: unsigned (7 downto 0) := (others => '1');
signal f: unsigned (7 downto 0) := (others => '0');
-- for default a,b,c,d,e,f the default result should be seq4
signal result: std_logic_vector (3 downto 0);
function to_string (inp: std_logic_vector) return string is
variable image_str: string (1 to inp'length);
alias input_str: std_logic_vector (1 to inp'length) is inp;
begin
for i in input_str'range loop
image_str(i) := character'VALUE(std_ulogic'IMAGE(input_str(i)));
end loop;
return image_str;
end function;
begin
DUT:
entity work.ifcase
port map (
seq1 => seq1,
seq2 => seq2,
seq3 => seq3,
seq4 => seq4,
a => a,
b => b,
c => c,
d => d,
e => e,
f => f,
result => result
);
STIMULIS:
process
begin
wait for 10 ns;
a <= (others => '0'); -- now equal gives seq1
wait for 10 ns;
a <= (others => '1'); -- undo
c <= (others => '0'); -- now equal gives seq2
wait for 10 ns;
c <= (others => '1'); -- undo
e <= (others => '0'); -- now equal gives seq3
wait for 10 ns;
e <= (others => '1'); -- undo
wait for 10 ns; -- displays seq4 again
wait;
end process;
MONTIOR:
process (result)
begin
report "result = " & to_string(result);
end process;
end architecture;
测试平台给出:
ifcase.vhdl:108:9:@ 0ms :(报告单):if_result = UUUU
ifcase.vhdl:114:9:@ 0ms :(报告单):case_result = UUUU
ifcase.vhdl:120:9:@ 0ms :(报告单):case2_result = UUUU
ifcase.vhdl:196:6:@ 0ms :(报告说明):结果= UUUU
ifcase.vhdl:120:9:@ 0ms :(报告说明):case2_result = 0100
ifcase.vhdl:114:9:@ 0ms :(报告说明):case_result = 0100
ifcase.vhdl:108:9:@ 0ms :(报告说明):if_result = 0100
ifcase.vhdl:196:6:@ 0ms :(报告说明):result = 0100
ifcase.vhdl:108:9:@ 10ns :(报告说明):if_result = 0001
ifcase.vhdl:114:9:@ 10ns :(报告说明):case_result = 0001
ifcase.vhdl:120:9:@ 10ns :(报告说明):case2_result = 0001
ifcase.vhdl:196:6:@ 10ns :(报告说明):result = 0001
ifcase.vhdl:108:9:@ 20ns :(报告说明):if_result = 0010
ifcase.vhdl:114:9:@ 20ns :(报告说明):case_result = 0010
ifcase.vhdl:196:6:@ 20ns :(报告说明):结果= 0010
ifcase.vhdl:120:9:@ 20ns :(报告说明):case2_result = 0010
ifcase.vhdl:108:9:@ 30ns :(报告说明):if_result = 0011
ifcase.vhdl:114:9:@ 30ns :(报告单):case_result = 0011
ifcase.vhdl:196:6:@ 30ns :(报告说明):结果= 0011
ifcase.vhdl:120:9:@ 30ns :(报告说明):case2_result = 0011
ifcase.vhdl:108:9:@ 40ns :(报告说明):if_result = 0100
ifcase.vhdl:114:9:@ 40ns :(报告单):case_result = 0100
ifcase.vhdl:120:9:@ 40ns :(报告说明):case2_result = 0100
ifcase.vhdl:196:6:@ 40ns :(报告说明):result = 0100
注意前八个是在模拟时间0(默认报告单位是ms)。四个与&#34; UUUU&#34;是if_result,case_result,case2_result和result的初始事件。一旦来自测试平台的初始值传播通过模型,输出就会转到&#34; 0100&#34;这是seq4(所有四个都有不同的默认值)。这是因为a-f上的值产生了&lt; = b,c&lt; = d,e&lt; = f。
的所有错误比较。所以测试台首先进行一次比较,然后是另一次比较,然后是最后一次为真,然后返回所有假。并且按顺序给出(因为在测试台STIMULIS过程中使用等待语句引入的延迟)seq1,seq2,seq3然后再次seq4。
您可以看到报告语句的顺序在前四个之后发生变化,这是由于不同的delta周期数。无论如何,在VHDL中不保证并发进程的执行顺序。
注意我在中间放了一个小的case语句,显示了两位SEL。
ifcase中的所有三个过程都产生了相同的结果,并且在合成时应该提供相同的结果。哪一个更容易阅读?
还有一个等效的条件信号赋值语句,当用作并发语句时,会生成处理if_statement的等效进程:
if_result <= seq1 when a <= b else
seq2 when c <= d else
seq3 when e <= f else
seq4;
这更难搞乱,不需要灵敏度列表(尽管2008年的标准修订版引入了all
来表示信号分配右侧出现的所有信号。)
你的问题: 1:多重声明是否有效?因为我觉得我知道多普勒&#39;我想知道,是否有可能通过一个命令打出多个命令。
原始How to convert multiple if else in SWITCH case [closed]显示带有elseif的if语句。
if if elsif是优先级编码器。如果声明不一致,那就是独立的。
2:&#34;忽略&#34;一些变量(seq1,即忽略var3)创建&#34;锁存行为&#34;?我希望将旧值保留在该变量中,我认为这应该发生。
是的,它会创建锁存器。它们通常是不合需要的FPGA供应商将发布如何通过RTL结构推断锁存器的指南,这些结构源自IEEE Std 1076.6-2004(现已撤回)。
您的&#34;子问题&#34;:
1:有没有办法直接使用&lt; =?因为它被用作&#34;写入&#34;命令我试图通过&#34;如果那么其他&#34;解决方法。有更简单的方法吗?
注意在我写的代码中的两个案例过程中有信号和一些变量。变量使用可以克服等待信号更新(在当前模拟周期中不会发生,但可能在当前模拟时间发生 - 对于增量循环)。
你也可以把东西分成小块。注意三个信号a_lteq_b,c_lteq_d和e_lteq_f的分配。
2:我是否需要添加一种延迟?由于第一阶段是&lt; =运算符,因此将创建1的延迟
没有。您可以但是可以编写VHDL,因此您不必这样做。秘密不是依赖于分配它的同一模拟周期(过程的相同遍历)中的信号值。有时(如图所示)你可以通过使用变量来做到这一点,它们的价值立即可用。
VHDL语句不是命令,无论是顺序(按顺序执行)还是并发(并行执行,顺序不保证)。每个并发语句都被详细描述为可能包含在表示层次结构的块语句中的一个或多个进程。子程序是功能或程序。函数调用是表达式(包含在语句中),而过程调用是语句。
进程是一个独立的语句序列,它通过遇到显式或隐式等待语句而暂停,并在依赖于敏感信号的条件变为真时恢复(例如,灵敏度列表中的信号事件,也请参见IEEE Std 1076-2008 10.2等待声明)。
答案 1 :(得分:0)
您的V1
进程不正确:
then
else
和if
写入同一行来模拟。然后 else,如果关键字是elsif
。所以这是固定的V1
进程:
V1 : process
begin
if (a<=b) then -- seq1
var1 <= nr1;
var2 <= nr2;
elsif (c<=d) then -- seq2
var1 <= nr3;
var2 <= nr4;
var3 <= nr5;
elsif (d<=f) then -- seq3
var2 <= nr6;
var3 <= nr7;
else -- seq4
var3 <= nr8;
end if;
end process V1;
问题2:
是的,它会推断一个闩锁。除非你真的知道自己在做什么,否则这不是一个好的设计选择!
保存状态应由寄存器完成。
您的第二个示例代码会在sel
上生成多个驱动程序。这就像创造短路一样!
问题4:
除非您指定显式延迟,否则信号分配没有延迟:
y <= transport x after 10 ns;
像sel
这样的变量不能在进程外声明,除非它是共享变量。共享变量的经验法则与锁存器一样:只有在知道自己在做什么时才使用它;)。