正在处理端口映射的替代方法? [英] Alternate way for port map in process?

查看:26
本文介绍了正在处理端口映射的替代方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

就我在 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?

因此,您可以看到我声明了两个新信号 LR,并且我正在使用您的流程来控制驱动它们的原因.ADD 块将添加一些 R0R1R2R3 的组合>.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆