PiotrZierhoffer on prjxray-absl-fix
bit/prjxray-tools: Fix abseil c… (compare)
github-actions[bot] on gh-pages
update 35146221d927fc0c050c599d… (compare)
github-actions[bot] on gh-pages
update 6225e33427fc69ecc6118a86… (compare)
github-actions[bot] on gh-pages
update 63774452ba5f81aab4fa37d3… (compare)
PiotrZierhoffer on ql-yosys-plugins
syn/quicklogic-yosys-plugins: F… (compare)
PiotrZierhoffer on ql-yosys-plugins
syn/quicklogic-yosys-plugins: F… (compare)
umarcor on tmp
umarcor on main
test/xyce: run Xyce -v debian-bullseye/xyce: add missi… (compare)
umarcor on tmp
test/xyce: run Xyce -v debian-bullseye/xyce: add missi… TEST ci disable (compare)
Does it exist? If not, I guess I can use Surelog/Verible (not sure which I need to use when) for Verilog and something from the GHDL side (@umarcor) to create my own.
@rodrigomelo9 see https://github.com/vhdl/pyVHDLModel and https://github.com/edaa-org/pySVModel (edaa-org/pySVModel#11).
https://umarcor.github.io/osvb/apis/project/OSVDE.html shows how to get the generics and ports from pyGHDL.dom.
flatten_generator.vhd
to get my record-type ports wrapped as individual std_logic/std_logic_vector ports, just what I needed. It doesn't handle multiple levels of record types, does it? I'll try it out more on Monday, and find out how generics are handled. Thanks for sharing!
flatten_generator.py
of course@mbuechl:matrix.org I have something similar to what you're looking to do that is pure VHDL. I can't find my original reference, but I believe it was adapted from the discussion and links at https://stackoverflow.com/questions/3985694/serialize-vhdl-record. There was a serialize/deserialize repo on GitHub, but I can't find it now.
Essentially, I use a state record to keep track of indexes and use pack
/unpack
procedures for each standard type to build the to_slv
/to_<record type>
functions. Below is a simple version for to
range:
procedure pack(
variable state : inout pack_state_t;
variable target : inout std_ulogic_vector;
constant push_data : in std_ulogic_vector
) is
constant length : integer := push_data'length;
begin
target(state.idx to state.idx + length-1) := push_data;
state.idx := state.idx + length;
end procedure;
procedure unpack(
variable state : inout pack_state_t;
constant source : in std_ulogic_vector;
variable pop_data : out std_ulogic_vector
) is
constant length : integer := pop_data'length;
begin
pop_data := source(state.idx to state.idx + length-1);
state.idx := state.idx + length;
end procedure;
Then, you can do something like this for your record:
type ex_t is record
sl : std_ulogic;
slv8 : std_ulogic_vector(7 downto 0);
sint16 : signed(15 downto 0);
end record;
constant SIZE : integer := 25;
-- this packs an SLV where 'left (MSW) is `sl` record element
function to_slv (arg : ex_t) return std_ulogic_vector is
variable v_ret : std_ulogic_vector(SIZE-1 downto 0);
variable state : pack_state_t := init_pack_state(target=>v_ret);
begin
pack(state, v_ret, arg.sl);
pack(state, v_ret, arg.slv8);
pack(state, v_ret, arg.sint16);
return v_ret;
end function;
My state record is slightly more complicated to handle the range, how sub-words are packed, etc. However, the idx
just keeps track of the starting index such that I can change the record declaration without having to remember to modify the to_slv
function.
The downside with this is there is no way in VHDL (at least with <=2008) to determine a record's size, so I update SIZE
when updating the record def. You could probably do something like SIZE = 1+ex_t.slv8'length+...
as well to keep it a bit more fool-proof and understandable