正在处理端口映射的替代方法? [英] Alternate way for port map in process?
问题描述
就我在 vhdl 中的理解而言,不可能将端口映射到进程内的组件.我很好奇是否有其他方法可以处理条件场景.
As far as my understanding in vhdl, it is not possible to have port mappings to components within a process. and i was curious whether there is an alternative way to approach a conditional scenario.
这是我目前正在处理的计算器 vhdl 代码示例:
here's an example of my calculator vhdl code that I am currently working on:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-- OP CODE TABLE --
-- 00 : LOAD --
-- 01 : ADD/SUB --
-- 10 : Print--
-- 11 : BEQ --
-- li - RS Values --
-- 00 : R0 --
-- 01 : R1 --
-- 10 : R2 --
-- 11 : R3 --
-- // add | op, rs, rd, rt //
-- // sub | op, rs, rd, rt //
-- // li | op, rs, immediate //
-- // beq | op, rs, rd, zero //
-- // print | op, rs, zero, one //
-- Current Problems --
-- need variables?
-- dont know what to do with numInst
entity Calculator is
port (
Clock : in std_logic;
numInst : in std_logic_vector (7 downto 0);
--Max Value of PC? 8 bits
Instruction : in std_logic_vector (7 downto 0);
--8 bit instruction
PC : out std_logic_vector (7 downto 0);
--8 bit output, used to retrieve next instruction
PRINTER : out std_logic_vector (7 downto 0);
--8 bit output is set to value of register when instruction display is executed
ENABLE : in std_logic;
--when high, instruction execute, when low, hold-no instruction executed
RESET : in std_logic
--on rising edge, reset register value to 0, restart excution of calculator
);
end Calculator;
architecture Behavorial of Calculator is
component ADD is
port (
A : in std_logic_vector(7 downto 0);
B : in std_logic_vector(7 downto 0);
Carry : out std_logic;
Sum : out std_logic_vector(7 downto 0)
);
end component;
component decode is
port (
instr : in std_logic_vector (7 downto 0);
op : in std_logic_vector (1 downto 0);
rs : in std_logic_vector (1 downto 0);
rd : out std_logic_vector (1 downto 0);
rt : out std_logic_vector (1 downto 0)
);
end component;
--need variable or signal to store opcode
--maybe need variable to store values identifier of rs, rt, rd
--random comment for something else...idk
--maybe we dont need a separate register vhdl file, make variable?
signal op, rs, rt, rd: std_logic_vector(1 downto 0):=(others=>'0');
signal immediate, AddOut: std_logic_vector(7 downto 0):=(others=>'0');
signal carrybit: std_logic;
--make register signals? R0, R1, R2, R3
signal R0, R1, R2, R3: std_logic_vector (7 downto 0) := "00000000";
begin
--portmap
decode port map (Instruction, op, rs, rd, rt);
calc: process (Clock, ENABLE, RESET)
-- use variables opcode, rs, rt, rd to break up Instruction
begin
if (ENABLE = '0') then
--nothing, calculator is disabled
else --ENABLE at 1
if (rising_edge(RESET)) then
PC <= "00000000"; -- restart execution
op <= "00";
rs <= "00";
rt <= "00";
rd <= "00";
--registers go to 0
elsif (rising_edge(Clock)) then
--
elsif (Clock = '1') then
if (op = "00") then
--maybe can be used to load values into registers
if(rd(1)='1') then
immediate(7 downto 4):='1';
immediate(3 downto 2)<= rd;
immediate(1 downto 0)<= rt;
else
immediate(7 downto 4):='0';
immediate(3 downto 2)<= rd;
immediate(1 downto 0)<= rt;
end if;
--PC = PC + 1
elsif (op = "01") then --add
if(rs = "00") then
if(rt = "00") then
addi00: ADD port map(R0,R0,carrybit,AddOut);
elsif(rt = "01") then
addi01: ADD port map(R0,R1,carrybit,AddOut);
elsif(rt = "10") then
addi02: ADD port map(R0,R2,carrybit,AddOut);
else
addi03: ADD port map(R0,R3,carrybit,AddOut);
end if;
elsif(rs = "01") then
if(rt = "00") then
addi10: ADD port map(R1,R0,carrybit,AddOut);
elsif(rt = "01") then
addi11: ADD port map(R1,R1,carrybit,AddOut);
elsif(rt = "10") then
addi12: ADD port map(R1,R2,carrybit,AddOut);
else
addi13: ADD port map(R1,R3,carrybit,AddOut);
end if;
elsif(rs = "10") then
if(rt = "00") then
addi20: ADD port map(R2,R0,carrybit,AddOut);
elsif(rt = "01") then
addi21: ADD port map(R2,R1,carrybit,AddOut);
elsif(rt = "10") then
addi22: ADD port map(R2,R2,carrybit,AddOut);
else
addi23: ADD port map(R2,R3,carrybit,AddOut);
end if;
else
if(rt = "00") then
addi30: ADD port map(R3,R0,carrybit,AddOut);
elsif(rt = "01") then
addi31: ADD port map(R3,R1,carrybit,AddOut);
elsif(rt = "10") then
addi32: ADD port map(R3,R2,carrybit,AddOut);
else
addi33: ADD port map(R3,R3,carrybit,AddOut);
end if;
end if;
--use component of adder vhdl file?
--PC = PC + 1 ?
--use adder (subtractor) component
--PC = PC + 1 ?
elsif (op = "10") then
-- need rs, rt, rd, variable?
if (rs = "00") then
PRINTER <= R0;
--insert print code here
--PC = PC + 1 -- to continue to next instruction
elsif (rs = "01") then
PRINTER <= R1;
--insert print code here
--PC = PC + 1 -- to continue to next instruction
elsif (rs = "10") then
PRINTER <= R2;
--insert print code here
--PC = PC + 1 -- to continue to next instruction
else --(rs = "11") then
PRINTER <= R3;
--insert print code here
--PC = PC + 1 -- to continue to next instruction
end if;
elsif (op = "11") then --beq
--if (register1 != register2) then
--PC <= PC + 1;
--else
--PC <= PC + 2;
--end if;
end if;
end if;
elsif (falling_edge(Clock)) then
if (op = "00") then
if (rs = "00") then
R0 <= immediate;
elsif (rs = "01") then
R1 <= immediate;
elsif (rs = "10") then
R2 <= immediate;
else --rs = "11"
R3 <= immediate;
end if;
elsif (op = "01") then
if (rd = "00") then
R0 <= AddOut;--output of adder;
elsif (rd = "01") then
R1 <= AddOut;--output of adder;
elsif (rd = "10") then
R2 <= AddOut;--output of adder;
else --rd = 11
R3 <= Addout;--output of adder;
end if;
end if;
end if;
end if;
end process calc;
end architecture Behavorial;
我无法真正解决的主要问题是如何在某些情况下(if/else 条件)使用我的加法器组件.
the main problem that i can't really wrap my mind around is how to use my adder component under certain circumstances (the if/else conditions).
推荐答案
正如@BrianDrummond 所说,你不能让硬件神奇地随意出现和消失.您无法根据硬件的某些输入来确定是否存在一组硬件.因此,您需要将硬件实例化一次,然后控制输入到它的内容:
As @BrianDrummond says, you can't make hardware magically appear and disappear at will. You cannot decide whether a lump of hardware exists and doesn't exist based on some inputs to the hardware. So, instead, you need to instantiate the hardware once and then control what is being input to it:
signal L, R : std_logic_vector (7 downto 0);
-- snip
addi: ADD port map(L,R,carrybit,AddOut); -- here is the ADD instance
calc: process (Clock, ENABLE, RESET)
-- snip
--PC = PC + 1
elsif (op = "01") then --add
if(rs = "00") then
if(rt = "00") then
L <= R0; R <= R0;
elsif(rt = "01") then
L <= R0; R <= R1;
elsif(rt = "10") then
L <= R0; R <= R2;
else
L <= R0; R <= R3;
end if;
elsif(rs = "01") then
if(rt = "00") then
L <= R0; R <= R0;
elsif(rt = "01") then
L <= R1; R <= R1;
elsif(rt = "10") then
L <= R1 R <= R2;
else
L <= R1; R <= R3;
end if;
elsif(rs = "10") then
if(rt = "00") then
L <= R2; R <= R0;
elsif(rt = "01") then
L <= R2; R <= R1;
elsif(rt = "10") then
L <= R2; R <= R2;
else
L <= R3; R <= R3;
end if;
else
if(rt = "00") then
L <= R3; R <= R0;
elsif(rt = "01") then
L <= R3; R <= R1;
elsif(rt = "10") then
L <= R3; R <= R2;
else
L <= R3; R <= R3;
end if;
end if;
--use component of adder vhdl file?
因此,您可以看到我声明了两个新信号 L
和 R
,并且我正在使用您的流程来控制驱动它们的原因.ADD
块将添加一些 R0
、R1
、R2
和 R3
的组合>.
So, you can see I have declared two new signals L
and R
and I am using your process to control what is driving them. The ADD
block will then add some combination of R0
, R1
, R2
and R3
.
我已经在下面回答了您的问题,但我在您的代码中看到了许多其他问题,尽管问题很多而且我只是快速浏览了一下.按照它们出现的顺序,而不是按严重程度:
I have answered you question below, but I see many other problems in your code, even though there's quite a lot of it and I only gave it a quick glance. In order they appear, not in order of seriousness:
i) 信号 R0, R1, R2, R3: std_logic_vector (7 downto 0) :="00000000";
仔细思考为什么要初始化这些信号.这可能适用于 FPGA,但(来自 IC 设计背景)依赖初始化信号似乎很危险.
Think very carefully why you are initialising these signals. This might work in an FPGA, but (coming from an IC design background) it seems dangerous to rely on initialising signals.
ii) 您缺少解码器的实例名称(严格来说是标签):
ii) You are missing the instance name (strictly a label) for your decoder:
decode port map (Instruction, op, rs, rd, rt);
应该是这样的:
deci : decode port map (Instruction, op, rs, rd, rt);
iii) 你真的应该在你的端口映射中使用命名关联.而不是:
iii) You really ought to use named assoication in your port maps. Instead of:
deci : decode port map (Instruction, op, rs, rd, rt);
做:
deci : decode port map (instr => Instruction, op => op, rs => rs, rd = rd, rt => rt);
iv) 您的流程不适合可合成顺序流程的任何模板:
iv) Your process doesn't fit any template for a synthesisable sequential process:
calc: process (Clock, ENABLE, RESET)
begin
if (ENABLE = '0') then
else --ENABLE at 1
if (rising_edge(RESET)) then
elsif (rising_edge(Clock)) then
elsif (Clock = '1') then
这是一个带有异步复位的顺序过程的模板:
Here is a template for a sequential process with an asynchronous reset:
process(clock, async_reset) -- nothing else should go in the sensitivity list
begin
-- never put anything here
if async_reset ='1' then -- or '0' for an active low reset
-- set/reset the flip-flops here
-- ie drive the signals to their initial values
elsif rising_edge(clock) then -- or falling_edge(clock)
-- put the synchronous stuff here
-- ie the stuff that happens on the rising or falling edge of the clock
end if;
-- never put anything here
end process;
因此,ENABLE
不应出现在您的敏感列表中;您流程的第一行应该是:
So, ENABLE
should not be in your sensitivity list; the first line of your process should be:
calc: process (Clock, RESET)
您应该在测试rising_edge(Clock)
后测试ENABLE
信号:
You should test the ENABLE
signal after the test for rising_edge(Clock)
:
elsif (rising_edge(Clock)) then
if (ENABLE = '0') then
您应该测试复位的绝对值,而不是寻找上升沿.而且您不需要所有这些括号.即不是这个:
You should test the absolute value of reset, not look for a rising edge. And you don't need all those parentheses. ie Not this:
if (rising_edge(RESET)) then
这个:
if RESET = '1' then
这一行是多余的:
elsif (Clock = '1') then
v) 您不应该测试时钟的两个边沿.这不是同步设计.您不能在一个过程中测试两个边缘.那甚至是不可合成的.这需要去:
v) You should not be testing both edges of the clock. This is not synchronous design. You cannot test both edges in a single process. That is not even synthesisable. This needs to go:
elsif (falling_edge(Clock)) then
vi) 我担心您在流程中较早地将 R0
驱动到 R3
,然后在稍后使用它们的值.很难准确地看到您的设计意图,但我怀疑这行不通:
vi) I am concerned that you are driving R0
to R3
earlier in the process and then using their values later. It is difficult to see your design intent exactly, but I suspect this will not work:
在 VHDL 中,信号在进程暂停之前不会更新.如果您尝试使用进程中较早分配的信号,您将获得先前分配的值.
In VHDL signals are not updated until a process suspends. If you try to use a signal assigned earlier in a process, you will get the previously assigned value.
一般
我建议你将你的设计分解成许多更小的过程.清楚地了解您对每种硬件的期望.让每个人执行特定的功能,例如多路复用ADD 块
的输入.例如,考虑:
I suggest you break your design into many smaller processes. Have a clear idea for each what kind of hardware you expect for each. Have each perform a specific function, eg multiplexing the inputs to the ADD block
. For example, consider:
流程是顺序逻辑还是组合逻辑?
Is the process sequential or combinational logic?
复位是异步的还是同步的?
is the reset asynchronous or synchronous?
输入是什么?
输出是什么?
然后选择合适的模板.我已经给出了一个带有异步复位的顺序过程.这是一个没有异步复位的顺序过程:
And then pick the appropriate template. I have given one for a sequential process with an asynchronous reset. Here is one for a sequential process without an asynchronous reset:
process(clock) -- nothing else should go in the sensitivity list
begin
-- never put anything here
if rising_edge(clock) then -- or falling_edge(clock)
-- put the synchronous stuff here
-- ie the stuff that happens on the rising or falling edge of the clock
end if;
-- never put anything here
end process;
这篇关于正在处理端口映射的替代方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!