如何使用32位无符号/有符号位数组中的8位

时间:2014-05-06 15:51:12

标签: vhdl

我已经定义了一个数组

type stream_pix_rx is array(59 downto 0) of signed(31 downto 0);
signal pix_32_width : stream_pix_rx := (others => "00000000000000000000000000000000");

我在pix_32_width每个时钟接收32位。

我想分别使用8位的所有四个插槽。我有另一个8位数组:

type pix_rx is array(239 downto 0) of signed(8 downto 0);
signal pix_8_width : pix_rx := (others => "00000000");

I want to put pix_8_width(i) <= pix_32_width(j(first 8 bits));
then pix_8_width(i+1) <= pix_32_width(j(next 8 bits));

等等。

Edit_ADD: 我在每个时钟周期或事件处串行接收32位流,所以每当我收到32位(在一个事件之后),我想把它放在pix_8_width(0到3)中。当我收到下一个32位流时,我想把它放在pix_8_width(4到7)中,依此类推。 当我的第60个32位完成时,我希望在第一个32位流中接收它们并将其放入pix_8_width(0到3)等等...... 我该怎么办?

这种事情会很简单吗?

pix_32_width(i) <= unsigned(S_AXIS_TDATA);
pix_8_width(4*i to 4*i+3) <= pix_32_width(i);
i <= i + 1;

要了解我想要实现的事情的大局: 我问过一个问题 https://electronics.stackexchange.com/questions/109359/where-is-the-pixel-data-in-xilinx-axi-video-dma-ip-to-apply-a-sobel-filter-on 这有更多细节。

2 个答案:

答案 0 :(得分:1)

由于您正在从一个数组表示转换为另一个数组表示而没有中间逻辑,因此您可以将其实现为转换函数:

function conv_32_to_8(p32: stream_pix_rx) return pix_rx is
  variable p8 : pix_rx;
begin
  for i in p32'range loop
    for j in 0 to 3 loop
      p8(i*4 + j) := p32(i)((j+1)*8 - 1 downto j*8);
    end loop;
  end loop;

  return p8;
end function;

此函数以little-endian顺序隔离字节。要将其连接到big-endian,请将p8(i*4 + j)替换为p8(i*4 + (3 - j))

要使用此功能,您可以实施连续分配,以便在pix_8_width上发生事件时更新pix_32_width

pix_8_width <= conv_32_to_8(pix_32_width);

如果您想控制转换何时完成,也可以在流程中调用它。

最后。您可以使用(others => (others => '0'))简化阵列初始化。这样可以省去尝试为内部数组输入正确数量的零的麻烦。

答案 1 :(得分:1)

您的Edit_ADD意味着单个数组类型:

  

我在每个时钟周期或者串行接收32位流   事件,所以每当我收到一个32位(在一个事件之后)我想放   它在pix_8_width(0到3)。当我收到下一个32位流   我想把它放在pix_8_width(4到7)中,依此类推。而当我的第60个32   比特完成我想在第一个32比特流接收它们并把它   在pix_8_width(0到3)等等...... 我该怎么做

强调添加

听起来像是一个环形缓冲区。

对于内存,您永远不必同时从写入侧或读取侧访问完整阵列。存储器阵列可以是一种类型或另一种类型。你不需要两者之间的联合。您可以在输入侧或输出侧进行转换。

此示例显示可以在pixel_rx数组类型中组织内存:

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

entity pix_ringbuff is
    port (
        clk:            in      std_logic;
        reset_n:        in      std_logic;
        pixel32w:       in      signed (31 downto 0);
        wrptr:          in      unsigned(5 downto 0);
        wr_en:          in      std_logic;
        rdptr:          in      unsigned(7 downto 0);
        pixel8w:        out     signed (7 downto 0)
    );
end entity;

architecture fum of pix_ringbuff is

    -- The memory array:

    type pix_rx is array(239 downto 0) of signed(7 downto 0);
    signal pix_8_width : pix_rx := (others => (others => '0'));

begin

WRITE:
    process(clk, reset_n)
        variable wrt_ptr:  natural range 0 to 239;
    begin

        if reset_n = '0' then
            pix_8_width <= (others => (others => '0'));
        elsif rising_edge(clk) and wr_en ='1' then
            wrt_ptr := to_integer(wrptr) * 4;
            pix_8_width(wrt_ptr)     <= pixel32w(31 downto 24);
            pix_8_width(wrt_ptr + 1) <= pixel32w(23 downto 16);
            pix_8_width(wrt_ptr + 2) <= pixel32w(15 downto 8);
            pix_8_width(wrt_ptr + 3) <= pixel32w(7 downto 0);
        end if;
    end process;

READ:
    process (rdptr, pix_8_width)
    begin
        pixel8w <= pix_8_width(to_integer(rdptr));
    end process;

end architecture;

缺少的是用于发出即将发生的翻转,空状态,高水位或低水位标记的信号。这些内容与指针(计数器)一样在内存中,指针显示为无符号,看到你使用了签名的像素数据。

注意所有4个像素都写在一个时钟中。字节Endian顺序与您所需的分配匹配:

pix_8_width(4*i to 4*i+3) <= pix_32_width(i);

这不起作用,因为一边是pix_rx,另一边是stream_pix_rx。

使用目标聚合:

        (pix_8_width(i*4),   pix_8_width(i*4+1),
         pix_8_width(i*4+2), pix_8_width(i*4+3)) <= 
                    pixel32'(
                        pixel32w(31 downto 24), 
                        pixel32w(23 downto 16),
                        pixel32w(15 downto 8),  
                        pixel32w(7 downto 0)
                    );

不应该起作用,目标聚合元素不是静态的。 IEEE Std 1076-1993 8.4信号分配声明(-2008,10.5 / 10.5.2.1):

  

如果信号赋值语句的目标是a的形式   聚合,那么聚合的类型必须是可以确定的   上下文,不包括聚合本身,但包括事实   聚合的类型必须是复合类型。基本类型   波形产生的每个事务的值组件   右侧的元素必须与基本类型相同   总计。此外, 中的表达式与每个元素关联   聚合必须是一个表示信号的本地静态名称 。   这种形式的信号分配指定了切片或子元素   与命名信号关联的驱动程序的右侧值   作为聚合的相应切片或子元素。

强调添加

包含i声明为变量的表达式或指定切片范围的信号不是局部静态的,这意味着在分析时进行评估。

您可以使用聚合将一种数组类型分配给另一种。它必须列出每个元素,并且会在聚合本地静态时占用大量源代码。

您的原始作业附近有一些内容:

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

entity footest is
end entity;

architecture foo of footest is

    type stream_pix_rx is array(0 to 59) of signed(31 downto 0);
    signal pix_32_width : stream_pix_rx := 
                           (X"FEEDFACE",X"DEADBEEF",
                            X"00010203",X"04050607",others => (others => '0'));

    type pix_rx is array(0 to 239) of signed(7 downto 0);
    signal pix_8_width : pix_rx := (others => (others => '0'));

    signal i:  natural range 0 to 59 := 42;
begin
    pix_8_width (i*4 to i*4+3) <= 
            ( 
                pix_32_width(i)(31 downto 24),
                pix_32_width(i)(23 downto 16),
                pix_32_width(i)(15 downto 8),
                pix_32_width(i)(7 downto 0)
            );

STIM:
    process
    begin
        for j in stream_pix_rx'range loop
            if j = 59 then
                wait;
            else
                wait for 10 ns;
            end if;
            i <= j;
        end loop;
    end process;

end architecture;

给出了:

right hand side aggregate

左侧不是聚合体,不需要是静态的。请注意,阵列类型范围已从降序转换为升序,以使左侧切片与建议的信号分配相匹配。