【问题标题】:VHDL: Std_Logic input stored in integer issueVHDL:存储在整数问题中的 Std_Logic 输入
【发布时间】:2013-09-26 20:25:51
【问题描述】:

我有以下问题:

我有一台 PC,它为我的 SPARTAN 3AN FPGA 提供输入,我希望获取这些输入,将它们放入 std_logic_vector,然后将它们转换为整数。指令被分成“n”条指令,每条指令有 32 位。我需要将前三位放在一个整数中,接下来的 28 位放在另一个整数中,最后一个是“最后一条指令标志”。所以,我有两个包含 100 个整数的数组,我将在其中放置指令(100 是限制)。如果“最后一条指令标志”为 1,则整个操作应该停止。

程序没有正确合成,所以我做了一个模拟。我发现了问题,但我不知道如何解决,所以我需要你的帮助。这是代码和模拟输出:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.all;


entity BinaryDecimalConv is
end BinaryDecimalConv;

architecture Behavioral of BinaryDecimalConv is

    type int_array is array (100 downto 0) of integer;

    signal clkcnt: integer :=0;
    signal fbaud: integer;
    signal lastnumflag: std_logic:='0';
    signal clk: std_logic;
    signal PLCinput: std_logic;
    signal init: std_logic;
    signal BusyIN: std_logic;
    signal BusyOutSignal: std_logic;
    signal InnerBusyOut: std_logic;
    signal cnt: integer :=0;
    signal fbaut: integer :=0;
    signal pre_int: std_logic_vector (31 downto 0) := (others => '0');
    signal pre_spec_num: int_array := (others =>0);
    signal cylinder: int_array := (others => 0);
    signal InnerNumLength: integer:=0;
    signal num_length: integer:=0;

begin

CLOCKK: Process is
begin
    clk<='0';
    wait for 10 ns;
    clk<='1';
    wait for 10 ns;
end process CLOCKK;

fbaud <=5208;
BusyIN <='0';
init <='0';

PLC: Process is
    variable PrePLC: std_logic_vector(159 downto 0):="1010101010101010101010101001010010101010101010101010101010010100101010101010101010101010100101001010101010101010101010101001010010101010101010101010101010010101"; -- 1 with 100, 5 with 200, 5 2ith 200, 3 with 300, 4 with 750
begin
    PLCinput<=PrePLC(159);
    PrePLC:= PrePLC(158 downto 1) & '0';
    wait for 104166 ns;
end process;    


LastNum: process (LastNumFlag) is
    begin
    if LastNumFlag = '1' then
        BusyOutSignal <='1';
        InnerBusyOut <='1';
    else
        BusyOutSignal <='0';
        InnerBusyOut <='0';
    end if;
    end process LastNum;

DecoderAndAcquirer: process (PLCinput, BusyIN, InnerBusyOut,clk) is
begin

    if (clk'event and clk='1') then                                                         -- If rising edge on clock
        if ((BusyIN='0') and (InnerBusyOut='0') and (init='0')) then                        -- Check if FPGA and PLC are ready to exchange information and if init is done
            if (clkcnt = fbaud/2)                    then                                   --  If clkcnt is equal to half of the duration of the input bit then
                pre_int(31) <= PLCinput;                                                    -- Initialize the last digit of pre_int
                cnt <= cnt+1;                                                               -- Incrementing cnt => going towards bit 2
                clkcnt <=clkcnt+1;                                                          -- Incrementing clkcnt so you can exit this block
                if (cnt<32) then                                                            -- Checking if not last bit
                    pre_int <= '0' & pre_int(31 downto 1);                                  -- If not last bit, shift number to right
                else                                                                        -- else
                    cnt <=0;                                                                -- reset cnt to start with next instruction
                    if (pre_int(0)='1') then                                                -- Check if last digit is one
                        LastNumFlag <= '1';                                                 -- If last digit is one, stop acquiring instructions
                    else
                        LastNumFlag <='0';
                    end if;
                    pre_spec_num(InnerNumLength) <= to_integer(unsigned(pre_int(28 downto 1))); -- Conversion from binary to decimal for instruction
                    cylinder(InnerNumLength) <= to_integer(unsigned(pre_int(31 downto 29)));    -- Conversion from binary to decimal for the number of cylinder
                    InnerNumLength <= InnerNumLength +1;                                            -- Incrementing the number of instructions
                    num_length <= InnerNumLength;
                end if;
            elsif (clkcnt = fbaud) then                                                     -- If clkcnt has reached the entire length of the input bit
                clkcnt <= 0;                                                                -- set clkcnt to zero so the process can start from beginning.
            else                                                                            -- If clkcnt is less than or more than half of the entire duration, but surely
                clkcnt <= clkcnt +1;                                                        -- less than the entire duration, then increment the value of the clkcnt.
            end if;
        end if;
    end if;
end process DecoderAndAcquirer;

end Behavioral;

问题是,如图所示,当 cnt 改变时,指令的第 31 位没有任何反应。任何想法为什么?

谢谢, 博扬

【问题讨论】:

    标签: events vector integer vhdl bit


    【解决方案1】:

    第一个 PrePLC := PrePLC(158 downto 1) &amp; '0'; 长度不匹配,所以我假设 这是PrePLC := PrePLC(158 downto 0) &amp; '0';,因此可以作为 移位寄存器。

    在代码的DecoderAndAcquirer进程中有:

    ...
    pre_int(31) <= PLCinput;
    ...
    if (cnt<32) then
      pre_int <= '0' & pre_int(31 downto 1);
    ...
    

    所以即使分配了pre_int(31),它也会在稍后被覆盖 pre_int &lt;= '0' &amp; pre_int(31 downto 1);(cnt&lt;32),由此 pre_int(31) 还不能变高。

    模拟较长时间时,cnt 变为 32,然后在 pre_int(31) 处显示一个 '1' 值;见下图。

    编辑:下面是pre_int的临时变量版本,只是为了展示原理;操作未验证。

    DecoderAndAcquirer: process (PLCinput, BusyIN, InnerBusyOut,clk) is
      variable pre_int_v : std_logic_vector(pre_int'range);
    begin
    
        if (clk'event and clk='1') then                                                         -- If rising edge on clock
            pre_int_v := pre_int;  -- Variable update from signal
            if ((BusyIN='0') and (InnerBusyOut='0') and (init='0')) then                        -- Check if FPGA and PLC are ready to exchange information and if init is done
                if (clkcnt = fbaud/2)                    then                                   --  If clkcnt is equal to half of the duration of the input bit then
                    pre_int_v(31) := PLCinput;                                                    -- Initialize the last digit of pre_int
                    cnt <= cnt+1;                                                               -- Incrementing cnt => going towards bit 2
                    clkcnt <=clkcnt+1;                                                          -- Incrementing clkcnt so you can exit this block
                    if (cnt<32) then                                                            -- Checking if not last bit
                        pre_int_v := '0' & pre_int_v(31 downto 1);                                  -- If not last bit, shift number to right
                    else                                                                        -- else
                        cnt <=0;                                                                -- reset cnt to start with next instruction
                        if (pre_int_v(0)='1') then                                                -- Check if last digit is one
                            LastNumFlag <= '1';                                                 -- If last digit is one, stop acquiring instructions
                        else
                            LastNumFlag <='0';
                        end if;
                        pre_spec_num(InnerNumLength) <= to_integer(unsigned(pre_int_v(28 downto 1))); -- Conversion from binary to decimal for instruction
                        cylinder(InnerNumLength) <= to_integer(unsigned(pre_int_v(31 downto 29)));    -- Conversion from binary to decimal for the number of cylinder
                        InnerNumLength <= InnerNumLength +1;                                            -- Incrementing the number of instructions
                        num_length <= InnerNumLength;
                    end if;
                elsif (clkcnt = fbaud) then                                                     -- If clkcnt has reached the entire length of the input bit
                    clkcnt <= 0;                                                                -- set clkcnt to zero so the process can start from beginning.
                else                                                                            -- If clkcnt is less than or more than half of the entire duration, but surely
                    clkcnt <= clkcnt +1;                                                        -- less than the entire duration, then increment the value of the clkcnt.
                end if;
            end if;
            pre_int <= pre_int_v;  -- Signals update from variable
        end if;
    end process DecoderAndAcquirer;
    

    波形图如下所示。

    【讨论】:

    • 是的,对于第一个,你是对的。我错过了一点(不过,它怎么会模拟它呢?)。对于第二个:我确实希望覆盖它。因为,PLCinputs 将每 104166 ns 到达,我希望它们向右移动,所以即使它在获取值时没有显示它的值,它应该显示 preint(30) 为 1,因为当我将它向右移动时,我实际上做了 pre_int(30)
    • 当我使用 pre_int
    • 第一个:ModelSim由于长度不匹配报错,所以听起来你的模拟器不够挑剔。对于第二个:我添加了在较长时间模拟后将 pre_int(31) 显示为“1”的图,因此 cnt 达到 32。最后评论:不,第一个 pre_int(31) &lt;= PLCinput; 没有任何效果,因为信号分配&lt;= 不会在下一个仿真周期之前改变信号值,因此后续的pre_int &lt;= '0' &amp; pre_int(31 downto 1) 将使用 pre_int 的当前值,导致全 0。
    • 第二个:我的模拟器在 32 次迭代后也显示了一个,但这不是我愿意得到的行为。一旦 PLCinput 获得新值,我需要它立即更改。在原始项目(不是模拟项目)中,我为此使用变量,只是因为信号在增量周期后改变了值。我在这里使用信号是因为我的模拟器不允许我模拟变量,但是在编写模拟项目时,我完全忘记了信号及其分配。但是,我的意思是,即使使用变量,我也尝试过。它仍然在退出时给出了一些奇怪的数字
    • "所以即使通过 pre_int(31) 被赋值,它后来在 pre_int
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多