rnelsonee

Members
  • Content Count

    13
  • Joined

  • Last visited

About rnelsonee

  • Rank
    Member

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. @D@n Just for closure, thanks again - it looks like I got it. I talked to the other engineer and he also figured I was creating a problem where there wasn't one: he said he'll just delay the data so it's mid-clock and I can just use two D flip-flops, which is your solution.
  2. @D@n Haha, yeah, I like that idea - it's similar to what I first tried - just treating it like any old signal. I must have been using a rising_edge(my_clk) somewhere though because of those warnings I got (I didn't 'specify' that the signal coming in was a clock in any special way, so I guess the implementer just knows I'm using it as a clock by seeing such rising_edge statements). I'll see if I can work your idea into my code - my code is all VHDL and broken into components, so I'll have to play with it for a while. I actually have 3 components currently based on this slower clock, so I'd like to modularize it. Is it fair to do this: module clock_converter( input wire i_sys_clk, input wire i_data_clk, output reg r_stb); reg [2:0] clock_transfer; always @(posedge i_sys_clk) begin clock_transfer <= { clock_transfer[2:0], i_data_clk }; r_stb <= (!clock_transfer[2])&&(clock_transfer[1]); end endmodule And then in my components I change "if rising_edge(clk) then" to "if (r_stb) then"? If I'm missing something, just let me know - I'm not sure what r_stb or o_stb stand for.
  3. @hamster, Thank you for that post! I just had my weekly status meeting and I mentioned to the engineer working on the board going into mine that I wasn't going to use the clock he's providing and I don't think that was what he wanted to hear. I put in a new bufg call like so i_bufg: bufg port map (i => CLK100MHz, o => CLK100MHz_buffered); i_bufg2: bufg port map (i => my_clk_ext, o => my_clk_int); but am still getting place errors for poor routing. I don't know why it's so hard to just find a suitable clock pin - it seems like my dev board just wasn't designed for it. [Place 30-574] Poor placement for routing between an IO pin and BUFG. If this sub optimal condition is acceptable for this design, you may use the CLOCK_DEDICATED_ROUTE constraint in the .xdc file.... my_clk_ext_IBUF_inst (IBUF.O) is locked to IOB_X0Y39 and i_bufg2 (BUFG.I) is provisionally placed by clockplacer on BUFGCTRL_X0Y0 Is the issue using two bufg's, or do I need to keep trying different pins?
  4. @D@n, Thank you for the response. I'd assumed that was not good design since it's not a multiple. For those who find this in the future, here is some GPL code in which you provide the ratio of clocks (256/3125 in my example) and it generates a clock. And sure enough, it's working! The clock drift in simulation worries me, but I guess that's just how it is - the drift corrects in time. And that link makes for some good reading. I think I'm okay with my buffer, but with my terribly newbie assumption above, maybe I'm making a wrong assumption here too. But the 8MHz process reads bits, saves to a buffer, and when it's full, it does a one-line assignment of one array to another (say 'buffer' to 'value'), and then set another signal to high. When my 25MHz sees the signal goes high, it starts the send process with the 'value' array, and it takes plenty of clock cycles to get to 'array' (it's building the Ethernet and IP headers). So while it's not a bi-directional handshake, I can't conceptualize a pitfall. Thanks again!
  5. So I must admit I'm more a software guy than a hardware guy, so hopefully this is an easy one. I want to read in bits on pins at 8.192 MHz, buffer them, and send them out on Ethernet via UDP. Ethernet requires 50 MHz and 25 MHz (not a multiple of 8.192 MHz). I have everything working in simulation, and even in the hardware realm by using the Ethernet clock for my fake data (I just have a counter that counts to N*(25/8.192) instead of counting to N before sending the packet, sending N bits). It's based off the excellent ArtyEthernetTX project which has this for line 1 of the XDS # Clock signal set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports clk100MHz] create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports clk100MHz] So I tried to add a new clock with an I/O pin, like set_property -dict { PACKAGE_PIN R11 IOSTANDARD LVCMOS33 } [get_ports { sample_clock }]; #IO_0_14 Sch=ck_io[30] But I got errors saying it was "poor placement routing" and the solution from Xilinx is to move it to a clock-capable in. Unfortunately, I can't find any reference in the Arty manual to a clock capable pin! I tried the clock pin for the SPI header, but that had the same error. I figure there's three solutions 1) Find a clock capable pin (there has to be one, right?) and you guys can help me find one! 2) Since Arty has a 100MHz "internal" clock, somehow tap that in my VHDL file and use E3 for my external clock 3) Wrap my whole thing in a Custom IP, duplicate every input and output to the wrapper, connect my external clock to pin E3, use Clocking Wizard to generate 100 MHz. I think 3 will work, but it just seems like overkill - certainly you can drive a development board with an external clock and still be able to send data out via Ethernet. Thank you all for any help! I hope I'm missing something obvious here
  6. To anyone that sees this in the future: My issue was with TLAST. I had it high, and my Custom IP sent out 4 bytes at a time. This limited the DMA to only give out 4 bytes at a time. By only asserting TLAST once every N bytes (you can't keep it at 0, despite the AXI-S spec saying it's optional) the DMA will read back N bytes. This thread links to a custom IP you can use to generate TLAST for you which sits between the FIFO and the DMA so your Custom IP doesn't need to do it.
  7. @D@n Thanks again for continuing to reply. And yeah, I'll see if that can work. I'm taking data (1000 bytes or so), throwing a few bytes of header onto it, and sending it over Ethernet. Since I'm only getting 4 bytes per function call from DMA, there doesn't seem to be any advantage to DMA. I figured the main purpose of a DMA was to allow me to use a pointer to grab a chunk of data, but that doesn't seem to be the case - I guess it just saves some processing cycles. If the FIFO can give me a few hundred bytes per function call, I'll use that. I assumed there was no way in the SDK/C code to 'pop' data out of a FIFO, but it looks like there might be a function for that.
  8. So it looks like enabling unaligned transfers didn't solve the issue: I'm still only transferring 4 bytes at a time. I really thought that was going to be it. Backing up a bit - is the DMA even required? Is there a way to just read the AXI data from the FIFO?
  9. Oh, hah, I should have mentioned the printf's are just for debugging. In my real program, this all goes out on a UDP port. This program for this post is just to help me get data fast enough - once it works I'll put this code into my other code, without printf. Thank you for the tips - the Allow Unaligned Transfers certainly looks like it might have been the issue - I'm regenerating the bitstream now. And the 0.2Mhz was lousy terminology on my part - the signal from the DMA down to the FIFO saying it was ready happens at about 0.2MHz - it's not a clock or anything. It's just that the "I'm ready for data" signal is slower than what I need it to be. And I'll play with TKEEP - I'm using AXI-S (stream), so I think TKEEP isn't used at all, just TREADY. Hopefully I don't have to use anything more complicated, I just send my data with TVALID and TLAST on high.
  10. Hello all, I am trying to stream data from a Custom IP, right now it's just a counter running at 8MHz, to a FIFO, to DMA. This is an image of the design. But the DMA and FIFO only ask (TREADY/WREADY) for data about 0.2 MHz. I'm sure it's because my code is only getting 4 bytes at a time from DMA, so even in a simple loop it's not fast enough. My question is hopefully an easy one: with something like XAxiDma_SimpleTransfer(&AxiDma,(u32) RxBufferPtr, MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA); I should be able to have an array of size MAX_PKT_LEN ready to use (I'm just trying to send this out via UDP as fast as possible)? I'd imagine a pointer should be available to point to a 'set' of contiguous memory, correct? I only get 4 bytes from the above function. I'm using a fairly simple program found online using XAxiDma_SimplePollExample(). In that program, it reads the first 1024 bytes just fine, and then actually the next 4 bytes, but then it starts 'dropping' data as my Custom IP keeps on going (I have the TREADY flag ignored for testing). The program output is here where you see it start to skip. And Here are the DMA settings and here are the FIFO settings. Thank you to anyone who can help! I've been at this for over a week and it's got to be a 2-minute fix I'm sure! I appreciate *any* help, I'm very new at all this.
  11. 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.
  12. @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); }
  13. 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