Jump to content
  • 0

Create an IP that can Partly be Controlled with Vivado SDK and Partly be Controlled by a Physical Switch that Does Not Rely on Vivado SDK


electronicsdevices

Question

So far, I've been relying on this video if I want to make custom IP and control it with just the SDK

 

It's gotten me through many things so far, but now I want to implement a design like this:

 

5980d043bf5a1_Screenshotfrom2017-08-0114-01-55.png.3ca52dacb209356e931844d6994e2262.png

Previously, I had hardcoded the matrix entries for matrices A and B. What I want to do is to use Vivado SDK to write what the matrix entries of matrices A and B are. Then, I want to flip a physical switch on the BASYS 3 board and use the Verilog logic I have already got working on the Verilog-only implementation of this model to multiply matrices A and B together and store the contents in matrix Z. The results of the multiplication can be viewed by flipping another physical switch, at which point they will be displayed on the four 7-segment displays (for simplicity, the matrix entries are between 1 and 2, so the largest possible resultant entry is 8).

The matrix A, B, and Z entries I know how to read and write with Vivado SDK. The way I usually do this is to create an IP with an AXI4 interface. However, the twist is that I want to control a few switches and an LED WITHOUT using Vivado SDK. I know that I could use the LED and Switch IP's by drag-and-dropping them onto a block design, but I only know how to control them with Vivado SDK. How can I create an IP where during runtime, I can have the FPGA (not Vivado SDK) monitor whether a switch has been pushed while still being able to change the contents of matrices A and B with Vivado SDK. Also, what do I need to do to be able to implement the a,b,c,d,e,f,g,and dp parts of the 7-segment display in the design?

In other words, in the video, he has a simple interface, no physical LEDs or switches used:

 

module myAdder8bit(

input CLK,

input A,

input B,

output S

);

and in the AXI4 wrapper, the user logic was something like this:

myAdder8bit UIP ( .CLK(S_AXI_ACLK),  .A(slv_reg0[7:0], .B(slv_reg0[15:8], .S(adder_out   )  ;

all the parameters he needed, he found or made in the AXI4 wrapper verilog file.

 

If he amended the interface as follows:

module myAdder8bit(

input CLK,

input A,

input B,

input physicalSwitchOnTheBoard,

output S

);

and in the AXI4 wrapper, the user logic was something like this:

myAdder8bit UIP ( .CLK(S_AXI_ACLK),  .A(slv_reg0[7:0], .B(slv_reg0[15:8],  .physicalSwitchOnTheBoard( IDONTKNOWWHATTOPUTINHERE    )   ,  .S(adder_out   )  ;

 

what would I substitute in for "IDONTKNOWWHATTOPUTINHERE"?

 

Link to comment
Share on other sites

Recommended Posts

@D@n

Thank you for the link to Verilator. I was looking for something like this.

I will look the rest of you points at a later time, but you should know that my intention wasn't to leave Vivado SDK, but rather, build an IP that has a switch that uses the logic on-board the FPGA to multiply two matrices independently of Vivado SDK. Since it requires an AXI4 interface, I will still need to use VIvado SDK because I will be using it to change the values of the matrices during runtime. However, I also want to multiply the contents of A and B by flipping a switch and this is the part of the design that should not rely on Vivado SDK. Unfortunately, I know of no way to combine the two requirements, which is why I am asking for help.

Link to comment
Share on other sites

@D@n It doesn't even have to be on one IP. I just need to figure out a block design to where the FPGA has an AXI4 interface where a user can use VIvado SDK to change values, but the matrix multiplication itself is triggered by flipping a switch, and preferably the switch is not being monitored by Vivado SDK. I'm interested in minimizing the time it takes for the user to hit a switch to start the multiplication and if I have Vivado SDK monitor the switch, then that adds extra time.

Link to comment
Share on other sites

@electronicsdevices

Adding additional ports to an AXI IP goes something like this:

[LINE 16]
// Users to add ports here
input switch,
// User ports ends
// Do not modify the ports beyond this line

...

[LINE 73 ish]
// Add user logic here
mymodule module (
.clk(s_axi_aclk),
.axi_port(slv_reg0),
.sw_port(switch)
.out_port(out_bus)
);
// User logic ends

note that when adding ports, you need to make sure that you modify both AXI wrapper files.

Hope this helps,

Arthur

Link to comment
Share on other sites

@artvvb

Here is my first attempt at implementing your suggestion. After putting this IP in a block design however, it does not prompt me to select pins for switches and LEDs. You had mentioned I need to edit both AXI files. I usually only edit the myipname_v1_0_S00_AXI.v. I tried to  copy and paste my changes from this AXI file to myiptest.v, but I get an error because myiptest.v does not have the slave registers I need, so I left that entire section blank. Where do I go from here?

MMultAXI4v

myiptest_v1_0_S00_AXI.v

myiptest.v

Link to comment
Share on other sites

@electronicsdevices

You need to map the new ports you have created in myiptest_v1_0_S00_AXI when you instantiate it in myiptest. Just like when you instantiate your MMultAXI4 module, you need to make sure that you map all of the different ports available. Take a look around line 64-84 of myiptest.v to see what I am talking about.

At a glance, this looks close.

Hope this helps,

Arthur

Link to comment
Share on other sites

@artvvb

Second attempt. I added signals to the already existing myiptest_v1_0_S00_AXI_inst and changed some names in myiptest of ports I got working in my original verilog design. The IP will synthesize, but I'm still not getting anything that is saying I need to specify a switch in the implementation phase. It is complaining about diff_clock_rtl_p not being implemented though.  MMultAXI4v remains unchanged.

myiptest_v1_0_S00_AXI.v

myiptest_v1_0.v

Link to comment
Share on other sites

@artvvb

All I really did is put mytestip and Microblaze on it. 59836781b3ddc_Screenshotfrom2017-08-0313-09-36.thumb.png.cd59680564271307f42a24f1f9764a4a.png

I'm wondering why it isn't complaining that I haven't assigned a switch to A,B,Z, and MMult_AB.

That's kinda what I don't get about it. I'm making a hybrid model of sorts. If instead I write it with just verilog, then when I go to implement the device, it asks me what switch I want to use (I didn't specify an .xdc file intentionally). In the past, if I wanted to use a switch, I could do that by adding the switch IP to the block design. I'm not really sure what to do if I want to combine the approaches.

Link to comment
Share on other sites

@electronicsdevices,

Gosh, look what your simulation just revealed ... (I reviewed MMultAB.v only, not MMultAB_tb.v)

  1. Your design (MMultAB.v) takes no time at all, since none of the transitions take place on the positive edge of any clock.
  2. The synthesizer did all your logic for you, and only programmed the result into the resulting registers.  No operations actually took place.  A simple set of 4-input LUTs (A, B, C, and MultAB) can be used to select among four apriori known answers.  It's a memory lookup to the answer, rather than any computations taking place.

So, let me ask, are you sure your design actually does what you want it to?  And, since you hadn't simulated your design, you really only had a false sense of what your design was doing up until now.

So, yeah, I am a big fan of simulation.  This is a wonderful example of why.

Were I to redo this, I'd rebuild the module so that the FPGA inputs could be set externally.  That would keep the synthesizer from optimizing away your logic.  It would also fail timing, forcing you to put the clocks back in that you need.  As for setting it externally, may I recommend using a debugging bus?  I like to use that to read/write an FPGA's data from software.  I consider the debugging bus interface to be more reliable than buttons and switches, but you may need to read the next several blog posts to know why.  (Or read the wikipedia paragraph on contact bouncing, and take a look at what buttons can do that you aren't expecting here)

Dan

Link to comment
Share on other sites

@electronicsdevices

And look at what your block design revealed, your ip should have additional ports for the inputs and outputs in your "Stuff I Added" section of myiptest_v1_0.

Have you merged file changes into the IP packager and re-packaged your IP since you added these ports? After doing so you will need to Refresh your IP repo and Upgrade the myiptest IP. "Refresh" should show up in a pop-up after you re-package, and you can do the Upgrade by doing Tools -> Reports -> Report IP Status, and then clicking Upgrade All.

Link to comment
Share on other sites

@D@n

So for whatever reason, the matrix multiplication from the prior version would return the zero matrix in simulation. So I decided to scrap the design and start over.

I started off with the most basic part (the matrix multiplication) and got that working. I didn't hardcode the values like I did before. I put them in the testbench instead.

When I ran the simulation, I get the correct result, but again, no delay.

5988e9f0a579b_Screenshotfrom2017-08-0717-23-47.thumb.png.f6d22c8ed010c4317ae3d5417bdb58aa.png

 

Is it even possible to get some sort of delay in a simulation without using physical parts? You mentioned clocks. I tried that with a prior simulation, but I still got no delay

5988e99d3e44f_Screenshotfrom2017-08-0314-27-10.thumb.png.f7f4ed4bc66ee4f33eccac851f4d40ec.png

 

I also tried your debugging bus and ran into some issues as I followed your tutorial:

http://zipcpu.com/blog/2017/06/29/sw-dbg-interface.html

The big one is that there is no makefile in ~/filepath/dbgbus. I ended up compiling each individual makefile and got it to work, but still, what you say in the tutorial doesn't work when you try it.

5988eb8fa3525_Screenshotfrom2017-08-0716-56-45.thumb.png.1ec782a0a2f7de913be6554c24f2cd4e.png

 

I also tried writing to the BRAM named "MEM," but that register wasn't recognized. I think it's because earlier on in the tutorial there was source code I need to have written prior to testing it.

5988ebd535455_Screenshotfrom2017-08-0717-13-52.thumb.png.52bc25e3133809b60285787a8107e37f.png

 

How do I build a design where I can get some sort of delay that would be comparable to real life? The issue seems to be the compiler makes it so the design doesn't need to do the calculation, so you mentioned externally feeding the FPGA values, but how is that possible in a simulation? I can do it with Vivado SDK easily, but that's in realtime. The simulation is important, but how can I get reasonable data if the compiler is preventing the very behavior I want to examine?

Verilog files are attached.

 

 

Mult_AB_tb.v

Mult_AB.v

Link to comment
Share on other sites

@electronicsdevices,

Your design takes no time at all, because that was what you told it to do.

If you want logic to take place "instantaneously" in a simulator, use an "assign" statement, or use an always statement that doesn't depend upon a clock.  "always @(posedge clk)" will require that the logic take a clock to take place.  Further, your test bench file itself will need to "create" the clock.  A little google turned up this article which discusses how to make a clock within your testbench. 

The simulator, though, doesn't match reality and in reality all logic takes time.  Your goal as a designer is to make sure that the time required by your logic is a touch less than the time between clock ticks.  Multiplies and adds take time.  I'm going to wager that "a0*b0+a1*b2" takes 2 DSP's and 20ns to do.  (It could be as fast as 10ns ... might be worth measuring.) 

Thank you for pointing out the issues with the debugging bus.  I think I've now fixed all of them.  Try going into the debugging bus directory, running "git pull" and then "make" from the main directory.  There's now a makefile there.  I also fixed the oversight of not having a register named "MEM" in regdefs.cpp.  That's now been fixed.

As for a design with a delay that would be comparable to real life ... I've only ever managed to do that by working back and forth with Vivado to implement my design.  Once my design implements, I know the delays within it are close to real life.  Use the clock, though ... Vivado is going to measure your design against the constraint that logic created on one clock must be completed before the next clock.  Vivado can only make that measurement when your logic starts on one clock and has to complete by the next.

Is it possible to externally feed an FPGA values in a simulation?  Yes.  I do it all the time.  The dbgbus simulation is doing that with the UART (it's just a C++ program ...).  However, that simulation isn't connected to the amount of time an operation requires.  To get that, I both simulate and build my design.  When building it, I check that it meets any timing requirements, etc.

Dan

Link to comment
Share on other sites

Creating an AXI wrapper for a module is the (xilinx suggested) way to communicate from PS to PL.

You can also connect ports of modules you have added to your block design to GPIO controllers, though this is hacky (I occasionally use it to prototype an AXI IP).

 

If you are having trouble putting what you want to do in words, an MS Paint drawing of the block design you want to create might help...

Link to comment
Share on other sites

What I want is to create a design where the matrix multiplication is implemented in verilog code (i.e. the FPGA itself does the calculation), but the values of the matrices can be read/written from/to a register (e.g. the register I named "usb_uart) in realtime (i.e. after the bitstream has been written to the FPGA) with some sort of software.

Link to comment
Share on other sites

I was hoping that the port called "usb_uart" could somehow tie into the register in the verilog code I want to read from. So I named it "usb_uart" wiith the hope that the two would somehow communicate. I would like to read and write values to this register I named "usb_uart" using software on my PC. I just don't know what interface I can use to accomplish this. Vivado SDK and @D@n's debug bus seem to be two ways to do it.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...