如何将记录写入内存并在 VHDL 中取回? [英] How to write a record to memory and get it back in VHDL?

查看:28
本文介绍了如何将记录写入内存并在 VHDL 中取回?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 VHDL 伪代码中,我想实现的是:

type tTest 是记录A : std_logic_vector(3 downto 0);B : std_logic_vector(7 downto 0);C : std_logic_vector(0 downto 0);结束记录 tTest;...信号 sTestIn : tTest;信号 sMemWrData : std_logic_vector(fRecordLen(tTest)-1 downto 0);信号 sMemRdData : std_logic_vector(fRecordLen(tTest)-1 downto 0);信号 sTestOut : tTest;...sMemWrData <= fRecordToVector(sTestIn);-- 在某些时候 sMemRdData 获取 sMemWrData 中的数据...sTestOut <= fVectorToRecord(sMemRdData);

fRecordLen 是一个虚构的函数,它直接从类型返回记录的聚合长度,希望 fRecordToVector 和 fVectorToRecord 是不言自明的.目标是不产生任何额外逻辑的可综合代码.我发布了我当前的解决方案作为进一步阐明操作的答案.然而,这是非常尴尬的方法,由于样板代码的数量,我不认为它是一个可行的解决方案.

我知道

因此您可以使用串联来组装向量值(或 -2008 年的聚合),并使用聚合作为限定表达式将 sMemRdData 传输到 sTestOut.

如果您没有计划声明 A、B 或 C 子类型的对象,您可以将它们声明为整数子类型:

library ieee;使用 ieee.std_logic_1164.all;包 TestPck 是亚型 A 是自然范围 12 到 9;亚型 B 是自然范围 8 到 1;亚型 C 是自然范围 0 到 0;常数 ABC_len: 自然 := A'left + 1;类型 tTest 是记录A:std_logic_vector(A);B: std_logic_vector (B);C: std_logic_vector (C);结束记录 tTest;tTests 类型是 tTest 的数组(自然范围<>);结束包TestPck;图书馆 IEEE;使用 ieee.std_logic_1164.all;使用 work.TestPck.all;实体 tb 是结束实体 tb;tb 的架构 sim 是信号 sTestIn: tTest;信号 sMemWrData: std_logic_vector(ABC_len - 1 downto 0);信号 sMemRdData: std_logic_vector(ABC_len - 1 downto 0);信号 sTestOut: tTest;常量测试:tTests(0 到 1):=(0 => (x"E", x"A7", "1"), 1 => (x"7", x"AC", "0"));开始sMemWrData <= sTestIn.A &sTestIn.B &sTestIn.C;sMemRdData <= 5 ns 后的 sMemWrData;sTestOut <=tTest'(sMemRdData(A), sMemRdData(B), SMemRdData(C));过程是开始等待 10 ns;sTestIn <= 测试(0);等待 10 ns;sTestIn <= 测试(1);等待 10 ns;等待;结束过程;最终架构模拟;

这可能更容易阅读.它将产生与上面相同的波形.

In VHDL pseudo-code what I would like to achieve is:

type tTest is record
    A : std_logic_vector(3 downto 0);
    B : std_logic_vector(7 downto 0);
    C : std_logic_vector(0 downto 0);
end record tTest;
. . . 
signal sTestIn       : tTest;
signal sMemWrData    : std_logic_vector(fRecordLen(tTest)-1 downto 0);
signal sMemRdData    : std_logic_vector(fRecordLen(tTest)-1 downto 0);
signal sTestOut      : tTest;
. . .
sMemWrData <= fRecordToVector(sTestIn);
-- At some point sMemRdData gets the data in sMemWrData...
sTestOut <= fVectorToRecord(sMemRdData);

fRecordLen is an imaginary function that returns the aggregate length of record directly from the type and fRecordToVector and fVectorToRecord are hopefully self explanatory. The target is synthesizable code that doesn't produce any extra logic. I post my current solution as an answer to further clarify the operation. However this is extremely awkward method and I don't consider it as a feasible solution due to the amount of boiler plate code.

I am aware of record introspection proposal but not holding my breath and even the proposed method seems very cumbersome.

I've given up hope for a fully general solution, so some concessions are more than acceptable. For example, allow only std_logic_vectors in the record and use several function/procedure calls. However, it would be great to avoid any boiler-plate code that must be hand or external script-adjusted per-record basis.

Also, if any Verilog/SystemVerilog wrappers exist that can input/output the record directly and achieve the same, pointers are extremely welcome.

解决方案

One way to translate data from a vector (a linear array) to a record would be through the use of an aggregate.

library ieee;
use ieee.std_logic_1164.all;

package TestPck is
    subtype A is std_logic_vector (12 downto 9);
    subtype B is std_logic_vector  (8 downto 1);
    subtype C is std_logic_vector  (0 downto 0);
    constant ABC_len: natural := A'length + B'length + C'length;
    type tTest is record
        A:  std_logic_vector (A'RANGE);
        B:  std_logic_vector (B'RANGE);
        C:  std_logic_vector (C'RANGE);
    end record tTest;
    type tTests is array (natural range <>) of tTest;
end package TestPck;

library ieee;
use ieee.std_logic_1164.all;
use work.TestPck.all;

entity tb is
end entity tb;

architecture sim of tb is
    signal sTestIn:        tTest;
    signal sMemWrData:     std_logic_vector(ABC_len - 1 downto 0);
    signal sMemRdData:     std_logic_vector(ABC_len - 1 downto 0);
    signal sTestOut:       tTest;
    constant tests:        tTests (0 to 1) :=  
             (0 => (x"E", x"A7", "1"), 1 => (x"7", x"AC", "0"));
begin
    sMemWrData <= sTestIn.A & sTestIn.B & sTestIn.C;
    sMemRdData <= sMemWrData after 5 ns;
    sTestOut <= 
        tTest'(sMemRdData(A'range), sMemRdData(B'range), SMemRdData(C'range));
process is
    begin
        wait for 10 ns;
        sTestIn <= tests(0);
        wait for 10 ns;
        sTestIn <= tests(1);
        wait for 10 ns;
        wait;
    end process;
end architecture sim;

The qualified expression defines the aggregate as a value of tTest record with positional association which is assigned to the record type sTestOut.

And this gives:

So you can use concatenation for assembling a vector value (or an aggregate in -2008) and use an aggregate as a qualified expression to transfer sMemRdData to sTestOut.

If you have no plans to declare an object of an A, B or C subtype you can declare them as integer subtypes:

library ieee;
use ieee.std_logic_1164.all;

package TestPck is
    subtype A is natural range 12 downto 9;
    subtype B is natural range  8 downto 1;
    subtype C is natural range  0 downto 0;
    constant ABC_len: natural := A'left + 1;
    type tTest is record
        A:  std_logic_vector (A);
        B:  std_logic_vector (B);
        C:  std_logic_vector (C);
    end record tTest;
    type tTests is array (natural range <>) of tTest;
end package TestPck;

library ieee;
use ieee.std_logic_1164.all;
use work.TestPck.all;

entity tb is
end entity tb;

architecture sim of tb is
    signal sTestIn:        tTest;
    signal sMemWrData:     std_logic_vector(ABC_len - 1 downto 0);
    signal sMemRdData:     std_logic_vector(ABC_len - 1 downto 0);
    signal sTestOut:       tTest;
    constant tests:        tTests (0 to 1) :=  
             (0 => (x"E", x"A7", "1"), 1 => (x"7", x"AC", "0"));
begin
    sMemWrData <= sTestIn.A & sTestIn.B & sTestIn.C;
    sMemRdData <= sMemWrData after 5 ns;
    sTestOut <= 
        tTest'(sMemRdData(A), sMemRdData(B), SMemRdData(C));
process is
    begin
        wait for 10 ns;
        sTestIn <= tests(0);
        wait for 10 ns;
        sTestIn <= tests(1);
        wait for 10 ns;
        wait;
    end process;
end architecture sim;

This may be a little easier to read. It'll produce the same waveform above.

这篇关于如何将记录写入内存并在 VHDL 中取回?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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