Technical Forum Moderator
  • Content count

  • Joined

  • Last visited

  • Days Won


artvvb last won the day on August 10

artvvb had the most liked content!

1 Follower

About artvvb

  • Rank
    Prolific Poster

Profile Information

  • Gender
  1. Ah, okay, that makes sense, this is the type of project that the line "Skip this step if your project doesn't support SDK." was intended for, you can just move on to step 5. That line could probably be a little bit more clear, apologies.
  2. @stewart Does this mean you do not have the "include bitstream" box checked? As for no IP handoff files, try navigating to the Sources/IP Sources tab in the Project Manager, right clicking on each IP and selecting Generate Output Products. Not sure if this is your problem, but it's worth a try. Thanks, Arthur Edit: noticed you provided the version of vivado, thanks!
  3. counter should be declared as a signal and std_logic_vector. Signals are the standard type for "variables" inside of a VHDL module. Likely you will need to define the PWM# signals as std_logic instead of bit, VHDL has very strict typing, and things just work more smoothly if you can make the types of signals on the left and right side of an assignment match. I don't believe that the constant keyword is required for PWM_COUNTER_MAX, generics are already evaluated when the design is synthesized, rather than when it is run. I formatted my previous response in the way I did for a reason, one of the best ways to quickly get something to work is to learn from others, in this case, I'd recommend reading the template code that surrounds your code, if you can read and understand what is going on in that, you will find yourself well prepared to write your own.
  4. @gutielo A project I am currently working on has a Zybo running SPI over a PMOD port with a 5MHz spi clock (in practice the full cycle is 16 bit samples at ~80KSPS, but there is a lot of wasted time in there), this is totally reasonable and seems to work pretty well. Seems like you could potentially run a UART connection at the speeds that you want over these ports. I'm not sure, and there could be clock domain problems on the receive side that I am not considering. I suppose that a further question would be how many PMOD ports you would be willing to dedicate to this, if your project allows you to dedicate more pins and send data in parallel, you can run at a slower clock and debounce more easily... For selecting a protocol to use, it depends heavily on your requirements. UART is a pretty good fit for just two boards, but if you are considering adding more boards to the project later, then SPI or I2C would be easier to extend. It also depends on whether you are able to pick a board to act as a master, or if you want the project to be more peer-to-peer (probably not using the term correctly). Also consider how frequently your data will need to be sent, a bit at a time likely needs something else entirely.
  5. To clarify the problem a little more: The tutorial likely uses Verilog for it's target language. The tutorial hasn't been updated in a while, and likely targets Vivado 2015 or 2014. While the process of creating a custom core hasn't changed much in this time, the tutorial is likely missing a step where you select what language you want to work in that may have been added for Vivado 2017. I missed the section 4.3 syntax in the first post, take a look at the syntax for axi_bresp for how to translate the counter register to VHDL. The user logic section will also need to be changed to VHDL, or you can just restart the tutorial, and pay particular attention to any dropdown menus that default to a VHDL option, these may not exist, I am still primarily using Vivado 2016 personally, and haven't walked through making a custom IP in that version yet.
  6. @FarmerJo Well, I'm guessing you are coming to VHDL from Verilog, and if I recall correctly, the tutorial expects the user to be writing Verilog, though I could be wrong. These are not the same language and have different syntax. What is called a parameter in Verilog is a generic in VHDL (I am sure there are some slight differences, but my VHDL isn't especially strong). VHDL infers whether something should be equivalent to a wire or reg based on how it is used, rather than in Verilog where you have to call it out specifically. As for specific fixes, take a look at the code around your PWM_COUNTER_MAX parameter, C_S_AXI_DATA_WIDTH uses the correct VHDL syntax for what the tutorial is having you do here. For your PWM# wires, the port S_AXI_AWREADY uses the typical VHDL single bit output port syntax. Hope this helps, Arthur
  7. @StudentAmsterdam In Vivado IPI, re-customize the GPIO IP to set the first channel width to 32 bits, check the all outputs or all inputs block as appropriate. set the default output and tristate values as appropriate. If you want a second 32 bit output enable dual channel. In SDK, I find it easier to work with the raw registers than with the xpgio header (I would not recommend this for any other IPs, AXI GPIO just happens to be super simple). Some super-basic sample code of how this works would be below, intended to blink each bit of both GPIO channels once per second: #include "xparameters.h" #include "xil_io.h" #include "sleep.h" #define GPIO_BASEADDR (<base address of gpio block in xparameters.h>) int main() { Xil_Out32(GPIO_BASEADDR+4, 0);//set Tristate of GPIO channel one to all output Xil_Out32(GPIO_BASEADDR+12, 0);//set Tristate of GPIO channel two to all output Xil_Out32(GPIO_BASEADDR, 0);//set output of GPIO channel one to all 0 Xil_Out32(GPIO_BASEADDR+8, 0);//set output of GPIO channel two to all 0 while (1) { sleep(1);//wait 1s Xil_Out32(GPIO_BASEADDR, 0xFFFFFFFF);//set output of GPIO channel one to all 1 Xil_Out32(GPIO_BASEADDR+8, 0xFFFFFFFF);//set output of GPIO channel two to all 1 sleep(1); Xil_Out32(GPIO_BASEADDR, 0);//set output of GPIO channel one to all 0 Xil_Out32(GPIO_BASEADDR+8, 0);//set output of GPIO channel two to all 0 } return 0; } Note that BASEADDR is the address of the channel one output register, +4 is the offset for the channel one tristate register, etc. These addresses do not depend on anything like channel width. Hope this helps, Arthur
  8. @gutielo Well, the most important question we need you to answer before making suggestions is how fast do you want this connection to be?. Thanks, Arthur
  9. 2'h1 is the offset from the base address in terms of the registers, so it would be offset by 4 when accessing from SDK. Where I think you are getting confused is in thinking about memory addresses as seen by SDK as "registers", which has a different meaning in the context of the HDL. SDK accesses the HDL code you define based on memory addresses, the HDL converts these addresses into values it can use to select which slave register to write to, or which piece of logic to read from. The process starting at line 213 defines how addresses are translated into registers when SDK writes values into the slave registers, so commenting out cases here defines which addresses cannot be written to. With the 2'h1 case commented out, calling Xil_Out32(BASE_ADDRESS+4, ...); will not have any effect on the values that your HDL sees. The process starting at line 363 defines how addresses are translated into what data will be read back into SDK. The way to think about this is that 213 defines what and where Xil_Out32(base_address + 4*HDL_address, data); will write into the slave registers. 363 defines what data will be selected when you call Xil_In32(base_address + 4*HDL_address);. With this in mind, the address represented by the read 2'h1 case selects the data previously written into slv_reg0 by the write 2'h0 case. Does that help?
  10. @JessPlazas Have you taken a look at this project? It's written in Verilog, but it's pretty much what you are describing...
  11. 1) slv_reg1 isn't being used because it's memory address is taken by the feedback from slv_reg0. I have that address configured as read only. For line 218, good catch, I forgot, and didn't actually test this code, just knocked it together quickly to illustrate . 2) As previously mentioned, this is intended to illustrate how to set up read-only and write-only registers. The assignment on line 369 is intended to show how to get data from PL to PS, the same as on line 371, but with the data flow coming from the processor instead of a port. Lets assume that we treat each slave reg as a port of it's own, the code I posted was intended to map to something a little like the following pseudo code. I am thinking of the slv_reg# ports in this pseudocode block not as actual registers, but as what the processor will need to treat the associated addresses as. module thing ( //ports output [N-1:0] led, input [M-1:0] sw, //implied bus to processor input [31:0] slv_reg0, output [31:0] slv_reg1, input [31:0] slv_reg2, output [31:0] slv_reg3 ); parameter N=4; parameter M=4; assign led = slv_reg2; assign slv_reg3 = sw; assign slv_reg1 = slv_reg0; endmodule 3) Absolutely, but if you aren't using SDK, there isn't much reason to include the AXI code. At that point you might just be better off with a pure-hdl project. Something you could do that would be similar, but take advantage of the AXI bus would be: assign led = sw | slv_reg2;
  12. An example of what I would do for this would be the two attached verilog source files. The attached image shows how to make the parameters visible in the customization GUI. In the IP Packager's Customization Parameters tab, double click on any parameter you want to be able to change from your block design and check the Visible in Customization GUI box. The IP that these files would instantiate sets things up so that the following should always evaluate to true. (the IP just copies slv_reg0 onto slv_reg1's address). Xil_Out32(BASEADDR, value); newvalue = Xil_In32(BASEADDR+4); return (value == newvalue); The led and sw ports can be resized by customizing the IP in your block design. If you make those ports external in the block design and then properly constrain them, then Xil_Out32(BASEADDR+8, value); will set your boards leds, while Xil_In32(BASEADDR+12); will return the state of your boards switches. myip_v1_0.v myip_v1_0_S00_AXI.v
  13. The packager itself can look scary, but you don't need to worry about nearly any of the options if you are just trying to get something simple up and running. At this point, just merge your changes and Re-package the IP.
  14. In the template, you can find a few relevant areas when it comes to customization: First, the place to put any parameters you want to add. //Users to add parameters here Second, the place to put any additional ports you want to add. For instance, if you wanted to connect LEDs to your IP. // Users to add ports here output [3:0] led, If you wanted to connect to switches. input [3:0] sw, If you want ports and/or parameters to the IP, you need to add them to the port maps of both <myip>_v1_0.v and <myip>_v1_0_S00_AXI_inst. Make sure to edit the instantiation of the "Axi Bus Interface S00_AXI" as well. Relevant code in myip_v1_0_S00_AXI: If you want to configure one of the register addresses to communicate from PL to PS, you will need to edit the synchronous process on lines 211-261 of this file. Comment out lines referring to the slv_reg# that you want to replace. If you want to change the name of the slv_reg#, make sure to replace it in lines 365-368 as well. The slave register can be replaced with a wire output of a verilog module you want to instantiate, for instance. This is key to getting communication set up: If you want a particular address to be written from the processor: use the slv_reg with the appropriate number (with 32 bit wide registers, slv_reg1 would be located at BASEADDR+4 when you are using Xil_Out32) in code added in the section at line 392 (Add user logic here). If you want a particular address to be read from the processor: replace all instances of that slave register's name when it appears on the right hand side of an assignment in the _S00_AXI file with your own signal. Comment out all instances where that slave register appears on the left hand side of an assignment. Do not touch any other predefined signals in either file, unless you really know what you are doing. You can basically do whatever you want in the Add user logic here area, as long as you keep in mind how your IP will be communicating with the rest of your design. AXI lets you communicate with the processor (one bit at a time), additional ports let you communicate with other IP, instantiated modules in the block design, and external ports, parameters let you reconfigure the IP while designing, so that you don't need to edit the IP again later (hopefully), and so that you can reuse it in different situations.
  15. I apologize if a lot of this is redundant with the tutorial. First, create a new axi4 peripheral, this you probably know. You can edit the number of registers and size of them, in case you need more than 4x32 bits in your interface. I believe that adding more registers or making them wider does not affect your bandwidth over AXI, so this is just a convenience. MAKE SURE you select edit IP before finishing. More to come...