• 0

Write output data from pmodMic3 to PC


I'm using Basys3 board with pmodMic3, and I would like to write a 'real-time' output data (12 bits for each output according to reference manual) to PC (a txt file maybe?) . Is that possible? Please advice. 

Thanks in advance!


Link to post
Share on other sites

4 answers to this question

Recommended Posts

  • 0


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,


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.

Link to post
Share on other sites
  • 0


you may have some luck with this. It may reach 30 MBit/s, which is the limit for one channel of the FTDI chip. It uses the MPSSE mode instead of UART to overcome the abovementioned UART limits using a dedicated clock signal.
busbridge3 link

I've used it for real-time data acquisition, in one case using 900+ kSPS for dual-channel 12 bit ADC data (which is about 24 MBit/s with some other overhead on the interface).

However, writing "proper" code to shuffle the data from FIFO to PC is not completely trivial. One solution goes like this:
- assuming the "busbridge3" interface, 32-bit address/data bus on the FPGA side
- design a FIFO that collects the real time data
- put a read-sensitive status "register" on the bus e.g. 0x80000000 that queries the fill level of the FIFO. On a read event, the same value is copied to a hidden register "A"
- put a "FIFO pop" register on the bus e.g. 0x80000001 with this function:
- - if A is non-zero, decrease A and pop a value from the FIFO to the bus
- - otherwise, keep A at zero and return dummy data

Your software then does this:
- queue a single-word read from 0x80000000
- queue an arbitrary length block read e.g. 100 times from 0x80000001 (with address increment 0 - reading the same address over and over)
- fire the USB transaction
- from the result, the first value is the number of valid words (from "A")
- use as many data values from the readback block and discard the rest (dummy data)

- as an optimization, you may read 0x80000000 again at the end of the block to know whether there is leftover data that would require a larger block size in the next round. This can make a huge difference in avoiding dropouts if your PC isn't tuned for real-time-ish operation.

If you pack two consecutive 12 bit ADC frames into one 24-bit word, you don't waste capacity on padding (busbridge3 allows 8/16/24/32 bit data width).

Edited by xc6lx45
Link to post
Share on other sites
  • 0

@[email protected]

Hi Dan,

Thanks so much for the detailed explanation !! 

I've been trying working on it and seems I *kind of* got what I expected from behavioral simulation (According to datasheet, the 12 bits of digital data are sent to the system board in 16 clock cycles with the first four bits as leading zeroes and the remaining 12 bits representing the 12 bits of data, my top module reads sample in every other 16 clock cycles to allow time to transfer). My simulation result shows:



Then I tried it on board, I tried sending the data to PC through UART, and used Realterm  to read the data received, however it either gives me all 0 or something obviously not correct (since each sample is supposed to start with four leading zeros, which doesn't agree with the data I received from Realterm).

I attached my code here, I'm completely new to FPGA and  verilog coding, and this is my first project. I've been stuck for quite a while and I'm just wondering if I'm on the correct direction at all. Could you help take a look at my code please? I just want to make sure what I'm trying here is not totally insane... 😢 I'm using Digilent Basys 3 and Vivado 2018.3.

Thank you very much !!






Link to post
Share on other sites
  • 0


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."


Edited by [email protected]
Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now