D@n

Members
  • Content Count

    1844
  • Joined

  • Last visited

  • Days Won

    131

Everything posted by D@n

  1. @Ahmed Alfadhel, I blogged about how to do this for some of my own filters when using Verilator. You can read that post here if it helps, Dan
  2. @Ahmed Alfadhel, Why not run a simulated sweep through the band and read out what the actual filter response is? Dan
  3. @Ahmed Alfadhel, You have a couple of options available to you: It's not clear, from your pictures above, whether or not the -40dB stop band was achieved. Some amount of noise is to be expected due to truncation errors, etc. Without seeing an estimated PSD, I can't tell. It may be that it's doing exactly what you required of it. -40dB is only so good. With more taps, you should be able to go deeper. How deep depends upon your requirements. How good do you want the signal to look? You may also need to provide more bits to both your signal and coefficient values in order to do better. You did prescale your coefficients so that, when rounded to integers, the taps were useful, right? Also, be aware, the filter will be specified for full scale. You'll want to measure it against a full scale input. Anything less will introduce additional truncation error. This is one of those reasons why the dynamic range (i.e. number of bits) of the input and output signals are so important. Enjoy! Dan
  4. When you probed the wires, did you probe the clock line as well? Dan
  5. @Juliana, It awesome to see you working at this! That said, it's time to learn a painful lesson: All of your clocks to need to be on the same (usually posedge) of a single clock or you can have timing errors or even unexplicable results. That means that logic transitioning off of negedge sck is usually a bad idea. You need to be generating sck, and the tools (i.e. Vivado) really struggle to generating a signal outside of a PLL and analyzing the logic that transitions from it. In general, an SCK signal *must* be a logic signal (i.e. not PLL generated). In most SPI designs, the CS signal gates the SCK signal and things get much worse. Indeed, the peripheral will *need* the CS signal to start high and drop low at least once just to get the work going. My suggestion: register the SCK and CS signals, and use the CS signal to indicate the start of each new sample. One other question, when you said you simulated this design, how much did you simulate? Were you able to capture a 1kHz sine wave from a simulated peripheral to know that your design was working? Or just 50 clocks that make you feel good about what's going on? When you did your simulation, did you also simulate the serial port? and verify that the results that would be delivered by the serial port match the data you think the design should send using the same software you intend to use to test the actual design in real-life? In the military, we'd often use the phrase, "Train like you intend to fight." The same applies here to simulation, "Simulate your design like you are going to use it." Dan
  6. @Shaw, A common beginner mistake is to attempt to create a clock within logic, and then to transition on edges of that clock. You've just discovered one of the reasons why that's bad. If A is created from combinatorial logic, then it may glitch before it settles. If something depends upon the edge of signal A, some things will transition, others won't, and the design will not be reliable. Suppose you create B from sequential logic, you still have troubles. A) Vivado can't tell it's frequency, so it can't tell if the logic dependent upon it is still valid, B ) There will be a delay between the original clock signal and the new one, limiting the ability of signals to cross from the first clock domain to the second, C) The new signal won't be using any of the dedicated circuitry within the FPGA. If you need to slow something down, this is not the way to do it. Let me offer two better approaches, a fractional approach and an integer divider approach. Here's the fractional divider, module fractionaldivider(i_clk, i_step, o_stb); input wire i_clk; input wire [31:0] i_step; output reg o_stb; reg [31:0] counter; always @(posedge i_clk) { o_stb, counter } <= counter + i_step; endmodule And the integer divider, module integer_divider(i_clk, i_div, o_stb); input wire i_clk; input wire [31:0] i_div; output reg o_stb; reg [31:0] counter; always @(posedge i_clk) if (counter == 0) counter <= i_div; else counter <= counter - 1; always @(posedge i_clk) o_stb <= (counter == 1); endmodule Note that neither example produces a clock signal. Instead they produce a strobe signal. You can use this to control your timing as part of a "clock-enable" structure--basically a big if statement that controls all of your logic, such as ... always @(posedge clk) if (stb) begin // Your slow logic would go here end You can read more about these techniques here, some rules to help you avoid this type of mistake here, and more about pipeline signaling here. Dan
  7. I've had the opportunity recently to build and verify several AXI cores, not just the AXI-lite cores but also the full AXI slave cores. I have also been both tweeting and blogging about what I've found. This includes not only all of the bugs I found within Xilinx's demonstration AXI slave, but also how to build an AXI slave that actually follows the AXI protocol and gets a much higher throughput. Feel free to check these articles out on ZipCPU.com. Dan
  8. @HelplessGuy, Plus one to the quotes above, and again to the recommendations to simulate everything before letting it touch a board. Just for reference, here's an example design on github that takes in a single analog/digital input from the PMod MIC3 (1Msps), applies a window function (Hanning), FFTs the result, and displays the measured energy spectra as a scrolling raster on an HDMI output. The simulator will also display the result as a window on your screen. Feel free to run it through Vivado and check out the resource usage, or even increase the size of the FFT to see how that impacts things. Dan
  9. @Ahmed Alfadhel, I like to use a basic LFSR when doing a BER test. The LFSR can be used to generate a pseudorandom bit-sequence in the transmitter. In the receiver, assuming you've used an LFSR, then there exists a linear combination of the input bits that will annihilate the sequence (turn all the bits to zero). You can then measure BER based upon the number of bits that are zero at the output. The biggest catch is that, depending upon the number of input bits required to generate the annihilator, you may end up with an estimate that's 3x larger than it needs to be (assuming a three tap annihilator). A little bit of scaling on the back end will then return this to the BER measurement you are looking for. The exception is that in really low BER environments, this method becomes too optimistic due to the math at the back end. This article should tell you what you need to build an LFSR. You'll probably want an LFSR with a longer period, though (google "maximal length LFSR"), and one that can be annihilated easily (google "feedthrough randomizer"). I know Sklar's Digital Communications has a table of polynomials you can use, as does Schneiers Applied Cryptography. You are also likely to find similar tables on line if you google for them. Dan
  10. @tahoe250, A quick Google search should yield almost all of what you need: how to create the IP, integrate it into your design, adjust addresses, build with it, and use it in practice. Be aware, a lot of Xilinx's AXI IP (as of 2018.3) both has bugs in it and is (rather) slow. Check out this post discussing the bugs in their AXI-lite demo core, or this one showing how you can build (and verify) a core without the bugs. Dan
  11. @Juliana, You might want to do the math on this. The PMod MIC3 can produce one sample every 1us (1MHz). This sample will contain 12 bits of valid information, so you will need to transfer to your PC something running at a data rate of nearly 12Mbps. Although the FTDI USB->UART chip is rated for 12Mbaud, I've only ever gotten it as high as 4Mbaud in practice, and I feel more comfortable using it at 1MBaud. (It starts struggling at 4MBaud, and seems to be rock solid at 1MBaud. That and 1MHz divides my favorite FPGA clock rate of 100MHz, while 12MHz doesn't.) Now, let's throw away all but 8-bits per sample, and assume you were running at 1MHz. You'd then need 10MBaud to send all of that data to your computer. (Remember, there are 10 baud intervals per byte.) It's not going to happen. However, there's no reason why you can't either 1) Read out random samples, missing/dropping anything when you can't deal with it, 2) Filter, downsample, and read out the filtered results, or even 3) store data to memory and then flush it to the UART. Hope this helps, Dan P.S. You can find a MIC3 controller here, if you want something that's FPGA proven. There's also a scrolling raster FFT demo here, but that requires the Nexys Video board.
  12. @herve, There's an option for Vivado to create a ".bin" file. Copy this directly to your flash device, starting with the first byte (unless you use warmboot, etc.), and you should be there. Don't forget that you might also need to adjust the configuration load options as well. Dan
  13. @aadgl, I don't really have any tutorials on how to do this, but I do have an example including some documentation on how to set up the example. Using the example, I can access the memory from a Wishbone bus. The basic operation is: (some wishbone master, either CPU, DMA, or whatever) -> (WB to AXI bridge) -> (MIG controller with an AXI front end) -> external memory pins. You can find this project here, and its documentation here. Dan
  14. @longboard, Yeah, that's really confusing isn't it? At issue is the fact that many of these chips are specified in Mega BITS not BYTES. So the 1Gib is mean to refer to a one gigabit memory, which is also a 128 megabyte memory. That's what the parentheses are trying to tell you. Where this becomes a real problem is that I've always learned that a MiB is a reference to a million bytes, 10^6 bytes, rather than a mega byte, or 2^20 bytes. The proper acronyms, IMHO, should be Gb, GB, Mb, and MB rather than GiB or MiB which are entirely misleading. As for the memory, listed as 16 Meg x 8 x 8, that's a reference to 8-banks of 16-mega words or memory, where each word is 8-bits wide. In other words, the memory has 16MB*8 or 128MB of storage. You could alternatively say it had 1Gb of memory, which would be the same thing, but this is often confused with 1GB of memory--hence the desire for the parentheses again. Dan
  15. Combinatorial logic shouldn't depend on the clock, and certainly not on the edge of a clock. My advice would be to put all references to rising edges specifically into your processes. Dan
  16. I'm really not the VHDL designer that others are, but this particular statement caught my attention: controller_was_in_use <= controller_in_use when rising_edge(clk); That ... just doesn't look right. The rising edge of the clock is an instant in time. This is a continuous assignment. Were I the synthesis tool, I'd be tempted to simplify this to 0. Dan
  17. As I recall, you are stuck with the 4:1 mode. That puts your system clock rate somewhere between 80 and 83MHz. The best choice you have for a system clock frequency that will support (naturally and natively) a 1MBaud UART would be 80MHz. On the other hand, UARTs--even at 1MBaud--are slow. You could easily use a second clock with your UART, and use a proper clock domain crossing to get just about any frequency. Dan
  18. @jrosengarden, Looks to me like your 4b carry nibble is inverted from what it needs to be. That's all. Dan
  19. You missed a change. Check out the line: addsub_4bit nibble1(carry[2], s[7:4], a[7:4], b[7:4], carry[1]^op, op); Dan
  20. @jrosengarden, Ok, I think I found your bug. Your carry bits are messed up. In the case of the 4-bit, you want to XOR the operation (not cin) with the carry to get the four bit add/subtract to pass. That will then properly subtract two 4-bit numbers, but it will also leave the carry wrong for the 8-bit adder. To make the 8-bit add/sub work, you'll need to invert carry[1] at the 8b level as well.. See the attached, Dan jrosengarden.tgz
  21. @jrosengarden, Can you tell me how the 4-bit subtract is supposed to work? Specifically, what is the carry supposed to do? Are you trying to calculate (A-B-carry), or (A-B+carry), or ... I'm not sure. I'm currently looking at A=8, B=0, and seeing some results I don't get either. Dan
  22. @jrosengarden, Ok, I found the bug in my proof -- I did "read_verilog file.v" instead of "read_verilog -formal file.v" ... now I'm getting failures on the 4-bit adder. Tell me, what should the response of the 4-bit adder be if A=0, B=4'hE, and cin=1? I'm getting an answer of 4'hF with a carry. Dan
  23. @jrosengarden, Which simulator are you using, and what does your test bench look like? Dan
  24. @jrosengarden, Tell me more. How is it "not" working? It could be associated with how you've set the design up ... Dan
  25. @jrosengarden, I just ran your design through a quick formal analysis. It works. Feel free to try out SymbiYosys yourself. You can read my Verilog tutorial, which includes the basics of how to formally verify a design, on the ZipCPU blog if you'd like. I'm also attaching the files I used for the proof, so you can take a look at what I verified. Dan jrosengarden.tgz