Jump to content
  • 0

Best approach for getting a signal from a sensor into C code/SDK


rnelsonee

Question

Hello all,

I've been reading up on this for a few days, and I see a lot of details, but I want to make sure I have this right: I have some digital data coming in on a wire, and I just want to queue it up and package it and send it as a UDP packet to a computer. I was thinking an Arty board can be used for this, so that's on order.

I have the input coming in, and can write VHDL if needed to to help with timing. I'm realizing as I write this I might not even need VHDL, but my data is coming in several kHz, so maybe I need to write VHDL to handle that.

I would use the Arty tutorial steps to get a Microblaze, DDR3, and Ethernet IP block. Question 1: If I write my own VHDL, so I need it package it as an IP? I'm not concerned about code reuse/modularity. If no IP, can I just Add Port... twice and add an input and tie it directly to an output? And then I just modify my .xdc file. That seems... to simple :)

Question 2: Do I need to use AXI? It seems like that's how users like to get data between the VHDL and SDK C code. But it seems like maybe I can use xil_io.h or xpgio.h to just access data directly. So if I do need AXI, this is where I get confused as in Vivado I can add an IP or I can add an AXI Peripheral. It seems like I'd only want one of those, but if I add an IP before, how does that connect to the AXI Periph?

Sorry for the very basic question, but it just seems like all this IP and AXI data I've been playing with might be overkill. I have data on a pin, and I just want to get it as a variable in the SDK C code.

Thank you all!

- Rick

Link to comment
Share on other sites

4 answers to this question

Recommended Posts

@rnelsonee

You have this mostly correct. If you are using Vivado 2016.2 or later, you will be able to use the "Add Module" selection from the right-click menu in the block design to add in any custom HDL code included in the project. I just checked, and there doesn't appear to be any initial bus type conflict with tying a module to an AXI GPIO controller like this. The GPIO method will be less efficient in terms of resource usage than creating an IP core to do the same thing, but if you want to get  a project running quickly, might give it a shot. You will need to use AXI to communicate, and this is why you will need to use a GPIO controller or other packaged AXI IP core.

You may want to read through these forum threads for more discussion of your questions, first, second.

Hope this helps,

Arthur

Link to comment
Share on other sites

@artvvb

Thank you very much for you help. The 'Add Module' is a neat feature! Although to be honest, I couldn't figure out where to put my outputs on the block diagram (type mismatch between my signals out and GPIO bus). But I'll take a step back on just focus on getting data up first. Right now I added an AXI GPIO block and configured it to look at the shield pins on the Arty, so I'm hoping that means I can just poll data at a high enough rate (it's actually ~8 MHz, I was mistaken).

I did notice when creating my own IP, it seems like it just created a boilerplate HDL code rather than 'transforming' HDL code into an IP, so maybe I just wasn't thinking of it the right way. I understand it needs this to have the right signal names and mux the data, but it doesn't look like it uses existing HDL code. I see a User Logic session, but reg_data_out is already written to in the boilerplate. I guess you replace those assignments

But anyway, I'll be able to try today. This is my setup, and I'm hoping I can access those shield pins with something like this, right?

 

XGpio xgpio = { 0x40000000, //base address
                1, //is ready?
                0, //interrupt enabled?
                0}; //dual channel?

XGpio_Config xgpio_config = {     0, //device id
                                0x40000000, //base address
                                0, //interrupt?
                                0}; //dual channel?

XGpio_CfgInitialize(&xgpio, &xgpio_config, 0x40000000);

while(1)
 {
         val = XGpio_DiscreteRead(&xgpio, 1);
 }

 

Link to comment
Share on other sites

@rnelsonee

It's a bit hard to tell how the GPIO is set up without seeing it's settings, or the input/output direction of the ports inside of the interface - if you click the plus next to GPIO/2 it will show the ports the interface is made up of. As for custom cores, I believe that most of what Vivado is doing is creating a wrapper that it can interpret for the existing HDL code.

For connecting to the GPIO bus, you need to make sure that the bus widths and input/output type are the same, and connecting them by first expanding the GPIO interface (click the plus symbol on the IP in the design), then "drawing" a line from the gpio_io_[i/o] bus to your HDL bus of the same width. The input/output type of the buses to be connected need to match, which you can do by configuring the GPIO IP core. If you have a lot of different signals that need to be touched by the processor, you may want to pack them all into an inout bus in your HDL. The following example is intended to be used with a 16 bit wide, one channel GPIO core configured for neither all inputs nor all outputs.

//verilog example
module myhdl ( /* other signals, */ gpio_bus);
	// input/output other signals, likely includes clk
	inout [15:0] gpio_bus;
	wire [3:0] in1, in2;
	wire [3:0] out1, out2;
	
	assign gpio_bus[3:0] = out1;
	assign gpio_bus[7:4] = out2;
	assign in1 = gpio_bus[11:8];
	assign in2 = gpio_bus[15:12];
	//do stuff
endmodule

Whether or not you are using the Add Module + GPIO method, or otherwise, I'd recommend starting your C code as follows. I think this will use standard configuration, so you may not have to worry about the XGpio_Config. The biggest differences here are the use of XGpio_Initialize and _SetDataDirection.

// C example (following the bus bit directions from the HDL example)
#include "xparameters.h"
//[...]
XGpio myDevice; // I think _Initialize handles setting this object up
XGpio_Initialize(&myDevice, XPAR_AXI_GPIO_0_DEVICE_ID); // or whatever your connected gpio base address is called in xparameters
XGpio_SetDataDirection(&myDevice, 1, 0xff00); // pointer, channel number - starts at 1, in/out bits - out is 0
val = XGpio_DiscreteRead(&myDevice, 1);

Hope this helps,
Arthur

Link to comment
Share on other sites

Awesome, thank you for your help, that was perfect. I was worried because the left side of the AXI GPIO block was the slave AXI, and the HDL-facing interface was on the right, indicating output. But I think I can just make those inputs in the C code. But I'll go ahead and work on making a custom IP. For now I can access buttons via XGpio with your code (changed 0xff00 to 1) and see things change in a Terminal. So that's a good step.

For those checking in the future, this tutorial shows how to write HDL and just use a port map to interface with the generated code. Then that becomes a fast AXI  IP.

Link to comment
Share on other sites

Archived

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

×
×
  • Create New...