PYNQ: PYTHON PRODUCTIVITY

Overlay using matlab generated ipcore: register_map only available if the .hwh is provided

Hi,

I am using a PYNQ Z2 board. I am currently trying to use the fpga portion to accelerate some calclations. I tried to use the approach in the pynq overlay tutorial 1, but is facing the error of hwh files, even when i already uploaded it. I am currently testing with this simple subsystem of a simple adder and multiplication.

I generated the ip core using matlab’s HDL coder. and obtained the following address file

I used the ip core in vivado to generate .bit stream ![image|690x186]

Then i upload the .bit .tcl and .hwh file into the pynq board

When using the jupyter notebook, I face the following hwh error shown in the image below, when i already uploaded the hwh file. And that the registers remains as 0 no matter what value i writes to it. While the timestamp address 0x8 matches the one that was provided by matlab. Does anyone know how to solve this issue, or if there is a simpler process to accomplish my goal. It would be great if i can use matlab’s generated core as i am not familiar with VIVADO HLS.

Is the .hwh in the same location in as the .bit file, and do the names match? E.g. you have tester.bit, so you should name your HWH tester.hwh

Cathal

1 Like

Hi Cathal
I have named all of it as tester. I tried to name the hwh file as tester.bit like you recommended but it cause error as well.

upon further investigation. The problem seems to be that under address blocks, there is no registers that are avaliable (left image). And it should contain the addresses a, b, c etc ( right image). Any idea how to configure those?

following attached is the simulink test model that i have made. and the vivado block diagram for reference.

Can you show ass reg addr of A and B? If you want to run accelerator you should:
1.Write by axi some data to A, B.
2.Set in ctrl register ap_start. (I think)
3.Reg C should be updated
Vitis HLS also generates driver files, so you could read addresses that way


Maybe this will help

Search for module add_0

so for example if register map doesn’t work read offset values from regA, regB from .hwh

<REGISTER NAME="a">
          <PROPERTY NAME="DESCRIPTION" VALUE="Data signal of a"/>
          <PROPERTY NAME="ADDRESS_OFFSET" VALUE="16"/>

A_offset = 0x16;
A_val = 4;
add_0.write(A_offset, A_val);

<REGISTER NAME="b">
              <PROPERTY NAME="DESCRIPTION" VALUE="Data signal of b"/>
              <PROPERTY NAME="ADDRESS_OFFSET" VALUE="24"/>

B_offset = 0x24;
B_val = 8;
add_0.write(B_offset, B_val);

<REGISTER NAME="c_ctrl">
          <PROPERTY NAME="DESCRIPTION" VALUE="Control signal of c"/>
          <PROPERTY NAME="ADDRESS_OFFSET" VALUE="36"/>

start = 0x01; //ap_start = 1;
add_0.write(ctrl_offset, start);

<REGISTER NAME="c">
          <PROPERTY NAME="DESCRIPTION" VALUE="Data signal of c"/>
          <PROPERTY NAME="ADDRESS_OFFSET" VALUE="32"/>

c_offset = 0x32;
C = add_0.read(c_offset);

1 Like

Sorry, the hwh should still have the correct file extension, the filenames must match. I corrected my earlier post.
It looks like the IP exported from Matlab doesn’t have any register information.
Can you see register offsets for A,B,C in Matlab?

Cathal

2 Likes

This are the register offsets generated by matlab. Comparing with the original post image, 0x8 indeed contains the same time stamp.

Hi thank you for your suggestions.

I have been trying to use
add_ip.write(0x100,2)
add_ip.write(0x104,2)
add_ip.read(0x108)

to try to just write to the 2 input registers, and read directly read from the output register. However if i read 0x100 or 0x104, it remains as 0. It behaves like its is set to read only? however im not sure, and i havent been able to figure out a way to change those to read and write registers.

Could you try to write uint16 (In matlab you have ufix16_en15?) from numpy? Maybe you are trying to write 32bit int from PYNQ perspective?
If this is axi controlled IP you must start it manually by writing β€œ1” to ap_start
I think this is the 0x4 address IPcore_Enable

1 Like

Hi, im not sure what do u mean by writting uint16 from numpy. Do u mean i should change the data type to uint16 from matlab?

I have tried to set 0x4 as 1 as well. but it seem like all those address is read only, and i am not able to even change 0x4 image

Is input data (ufix16_en15) an integer 32bit? could you include .hwh file from this post?

It is 32 bit fixed point data. consisting of 16 word length + 15 fraction length, it can represent decimals as well

I have tried to change settings from the matlab side, but it seems like it is already configured to β€œReadWrite”. So do u guys know if there is any way that i can change the write permission on vivado side? as im quite new to using vivado.

image

Can you post the generated code for your IP?

Cathal

1 Like

This is the main vhdl code that is generated.

Generated by MATLAB 9.5 and HDL Coder 3.13

–


– Rate and Clocking Details


– Model base rate: -1
– Target subsystem base rate: -1



–
– Module: untitled_ip
– Source Path: untitled_ip
– Hierarchy Level: 0


LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;

ENTITY untitled_ip IS
PORT( IPCORE_CLK : IN std_logic; – ufix1
IPCORE_RESETN : IN std_logic; – ufix1
AXI4_Lite_ACLK : IN std_logic; – ufix1
AXI4_Lite_ARESETN : IN std_logic; – ufix1
AXI4_Lite_AWADDR : IN std_logic_vector(15 DOWNTO 0); – ufix16
AXI4_Lite_AWVALID : IN std_logic; – ufix1
AXI4_Lite_WDATA : IN std_logic_vector(31 DOWNTO 0); – ufix32
AXI4_Lite_WSTRB : IN std_logic_vector(3 DOWNTO 0); – ufix4
AXI4_Lite_WVALID : IN std_logic; – ufix1
AXI4_Lite_BREADY : IN std_logic; – ufix1
AXI4_Lite_ARADDR : IN std_logic_vector(15 DOWNTO 0); – ufix16
AXI4_Lite_ARVALID : IN std_logic; – ufix1
AXI4_Lite_RREADY : IN std_logic; – ufix1
AXI4_Lite_AWREADY : OUT std_logic; – ufix1
AXI4_Lite_WREADY : OUT std_logic; – ufix1
AXI4_Lite_BRESP : OUT std_logic_vector(1 DOWNTO 0); – ufix2
AXI4_Lite_BVALID : OUT std_logic; – ufix1
AXI4_Lite_ARREADY : OUT std_logic; – ufix1
AXI4_Lite_RDATA : OUT std_logic_vector(31 DOWNTO 0); – ufix32
AXI4_Lite_RRESP : OUT std_logic_vector(1 DOWNTO 0); – ufix2
AXI4_Lite_RVALID : OUT std_logic – ufix1
);
END untitled_ip;

ARCHITECTURE rtl OF untitled_ip IS

– Component Declarations
COMPONENT untitled_ip_dut
PORT( In1 : IN std_logic_vector(15 DOWNTO 0); – ufix16_En15
In2 : IN std_logic_vector(15 DOWNTO 0); – ufix16_En15
Out1 : OUT std_logic_vector(15 DOWNTO 0) – ufix16_En14
);
END COMPONENT;

COMPONENT untitled_ip_axi_lite
PORT( reset : IN std_logic;
AXI4_Lite_ACLK : IN std_logic; – ufix1
AXI4_Lite_ARESETN : IN std_logic; – ufix1
AXI4_Lite_AWADDR : IN std_logic_vector(15 DOWNTO 0); – ufix16
AXI4_Lite_AWVALID : IN std_logic; – ufix1
AXI4_Lite_WDATA : IN std_logic_vector(31 DOWNTO 0); – ufix32
AXI4_Lite_WSTRB : IN std_logic_vector(3 DOWNTO 0); – ufix4
AXI4_Lite_WVALID : IN std_logic; – ufix1
AXI4_Lite_BREADY : IN std_logic; – ufix1
AXI4_Lite_ARADDR : IN std_logic_vector(15 DOWNTO 0); – ufix16
AXI4_Lite_ARVALID : IN std_logic; – ufix1
AXI4_Lite_RREADY : IN std_logic; – ufix1
read_ip_timestamp : IN std_logic_vector(31 DOWNTO 0); – ufix32
read_Out1 : IN std_logic_vector(15 DOWNTO 0); – ufix16_En14
AXI4_Lite_AWREADY : OUT std_logic; – ufix1
AXI4_Lite_WREADY : OUT std_logic; – ufix1
AXI4_Lite_BRESP : OUT std_logic_vector(1 DOWNTO 0); – ufix2
AXI4_Lite_BVALID : OUT std_logic; – ufix1
AXI4_Lite_ARREADY : OUT std_logic; – ufix1
AXI4_Lite_RDATA : OUT std_logic_vector(31 DOWNTO 0); – ufix32
AXI4_Lite_RRESP : OUT std_logic_vector(1 DOWNTO 0); – ufix2
AXI4_Lite_RVALID : OUT std_logic; – ufix1
write_In1 : OUT std_logic_vector(15 DOWNTO 0); – ufix16_En15
write_In2 : OUT std_logic_vector(15 DOWNTO 0); – ufix16_En15
reset_internal : OUT std_logic – ufix1
);
END COMPONENT;

– Component Configuration Statements
FOR ALL : untitled_ip_dut
USE ENTITY work.untitled_ip_dut(rtl);

FOR ALL : untitled_ip_axi_lite
USE ENTITY work.untitled_ip_axi_lite(rtl);

– Signals
SIGNAL reset : std_logic;
SIGNAL ip_timestamp : unsigned(31 DOWNTO 0); – ufix32
SIGNAL reset_cm : std_logic; – ufix1
SIGNAL reset_internal : std_logic; – ufix1
SIGNAL write_In1 : std_logic_vector(15 DOWNTO 0); – ufix16
SIGNAL write_In2 : std_logic_vector(15 DOWNTO 0); – ufix16
SIGNAL Out1_sig : std_logic_vector(15 DOWNTO 0); – ufix16
SIGNAL AXI4_Lite_BRESP_tmp : std_logic_vector(1 DOWNTO 0); – ufix2
SIGNAL AXI4_Lite_RDATA_tmp : std_logic_vector(31 DOWNTO 0); – ufix32
SIGNAL AXI4_Lite_RRESP_tmp : std_logic_vector(1 DOWNTO 0); – ufix2

BEGIN
u_untitled_ip_dut_inst : untitled_ip_dut
PORT MAP( In1 => write_In1, – ufix16_En15
In2 => write_In2, – ufix16_En15
Out1 => Out1_sig – ufix16_En14
);

u_untitled_ip_axi_lite_inst : untitled_ip_axi_lite
PORT MAP( reset => reset,
AXI4_Lite_ACLK => AXI4_Lite_ACLK, – ufix1
AXI4_Lite_ARESETN => AXI4_Lite_ARESETN, – ufix1
AXI4_Lite_AWADDR => AXI4_Lite_AWADDR, – ufix16
AXI4_Lite_AWVALID => AXI4_Lite_AWVALID, – ufix1
AXI4_Lite_WDATA => AXI4_Lite_WDATA, – ufix32
AXI4_Lite_WSTRB => AXI4_Lite_WSTRB, – ufix4
AXI4_Lite_WVALID => AXI4_Lite_WVALID, – ufix1
AXI4_Lite_BREADY => AXI4_Lite_BREADY, – ufix1
AXI4_Lite_ARADDR => AXI4_Lite_ARADDR, – ufix16
AXI4_Lite_ARVALID => AXI4_Lite_ARVALID, – ufix1
AXI4_Lite_RREADY => AXI4_Lite_RREADY, – ufix1
read_ip_timestamp => std_logic_vector(ip_timestamp), – ufix32
read_Out1 => Out1_sig, – ufix16_En14
AXI4_Lite_AWREADY => AXI4_Lite_AWREADY, – ufix1
AXI4_Lite_WREADY => AXI4_Lite_WREADY, – ufix1
AXI4_Lite_BRESP => AXI4_Lite_BRESP_tmp, – ufix2
AXI4_Lite_BVALID => AXI4_Lite_BVALID, – ufix1
AXI4_Lite_ARREADY => AXI4_Lite_ARREADY, – ufix1
AXI4_Lite_RDATA => AXI4_Lite_RDATA_tmp, – ufix32
AXI4_Lite_RRESP => AXI4_Lite_RRESP_tmp, – ufix2
AXI4_Lite_RVALID => AXI4_Lite_RVALID, – ufix1
write_In1 => write_In1, – ufix16_En15
write_In2 => write_In2, – ufix16_En15
reset_internal => reset_internal – ufix1
);

ip_timestamp <= to_unsigned(2103081659, 32);

reset_cm <= NOT IPCORE_RESETN;

reset <= reset_cm OR reset_internal;

AXI4_Lite_BRESP <= AXI4_Lite_BRESP_tmp;

AXI4_Lite_RDATA <= AXI4_Lite_RDATA_tmp;

AXI4_Lite_RRESP <= AXI4_Lite_RRESP_tmp;

END rtl;

The folder below contains the entire folder of the generated ip core. When i add the ip core to vivado, i selected this folder.
untitled_ip_v1_0.zip (190.0 KB)

This is 16 bit vector… but anyway PYNQ should read some garbage after IP start.
Could you please also include generated .hwh file from Vivado?

Maybe just maybe if you are writing in PYNQ β€œ1” = 0x0001 = 32’b0000000000000000000000000001
and IP reads only the whole number, ignoring fraction β†’ 16’b0000000000000000?

Thank you for the suggestion, i think i understand what u mean. I will try it first thing tmr and share all the files.

I have tried to change the data type to uint16 from matlab. AND IT WORKED, so i guess its right that the fraction is getting ignored.

. However since i changed it to uint. It wont allow non integer values. I will continue to work on it.

Thanks Bartokon and Cathal for the support.

image