Wednesday, July 27, 2011

Time to Time

Yesterday, we successfully digitized an asynchronous, externally-supplied asymmetrical sawtooth input pulse from the waveform generator, at 1/2 speed (250 Msps), with fairly good (but not yet perfect) reliability/stability in the digital values output from the test bench.  Today I want to work on improving the performance & reliability.  Some things to try:
  1. Make sure physical synthesis (logic performance optimization) is turned on in fitter.
  2. Add a Synopsis Design Constraints (.sdc) file to configure timing-driven synthesis/fitting.
  3. Add synchronizer stages to the input-capture front end, to reduce any metastability issues.
Also, I need to make a more detailed outline of the various portions of the C code that need to be written.  Since more than one of us will be working on the C code now, we need to divide up the firmware design into different source files that we can work on independently.  Different files can then be assigned to different developers to code up and test.

OK, let's start item #1 above.  Physical synthesis (Assignments --> Settings --> Compilation Process Settings --> Physical Synthesis Optimizations --> Perform physical synthesis for combinational logic) checkbox is already checked.  However, the effort level is only set to "Normal."  Let's turn it up to "Extra" and see if that helps.  It probably won't, since we have not even set up the .sdc file yet, but, worth a try, perhaps...  Nope, it didn't.

Referring back to my .sdc file for my FPGAminer project (a personal project at home), we will want lines like the following in our .sdc file:

create_clock -period "20.000 ns" -name {clkin_50MHz} {clkin_50MHz}
derive_pll_clocks -use_tan_name
derive_clock_uncertainty

Next, #2:  Now opening the TimeQuest timing analyzer and letting it generate an initial .sdc file from the Quartus settings file.  Looks like it generate the first two lines itself, but let me go ahead and add the derive_clock_uncertainty.  Side note: It sets the JTAG clock period to 20 ns, but I think it is supposed to be 10 based on how it was set in the old project; keep this in mind if there are JTAG problems.

Went through the timing netlist actions; that seemed to work fine.

Now let's recompile, and hopefully get proper timing-driven synthesis.

It says we failed to meet timing requirements in the high-speed counter (Fmax 200MHz instead of 250MHz).  However, the results are looking good anyway!  Here are the new data outputs:

Hex, scope order:    06, 00, 30, 02, 2C, 04, 24,  07, 1D, 09, 15, 0B, 0F
Hex, normal order:   06, 00, 02, 04, 07,  09, 0B, 0F, 15, 1D, 24, 2C, 30
Decimal, normal:      6, 0, 2, 4, 7, 9, 11, 15, 21, 29, 36, 44, 48

The "6" is the number of levels crossed; the rest are multiples of our 2 ns time step size.  The resulting graph, given our current thresholds (same as yesterday's) looks like this (red line; light blue one is the old 4-ns resolution pulse-form capture data from yesterday):


Darryl is here, and I have him working on writing a driver in C for his DAC_CPU_IF module.  It will be called DAC_driver.{c,h} and it will define 3 functions:  dac_set_level(), init_dacs(), dac_ramp_test().  The init_dacs() will initialize to different levels from the automatic initialization that's already built into David's dac_control hardware (so we can tell if setting the new levels worked).  The dac_ramp_test() will reproduce the linear voltage ramp produced by Darryl's existing dac_cpu_test input driver stub.  I showed Darryl the relevant doc (for the PIO), and suggested he use the macros for setting/clearing individual bits for toggling bit 15 (the main control bit), and use ordinary C bit-bashing operators (<<, |) to put together the data fields.

We are about done with the hardware now, although eventually we may want to create an interface to the ADCs so that we can turn them off.  I put the datasheets for the ADCs on the Dropbox, in the "FEDM_design\Component Datasheets" folder.

Here is a complete (for now) list of C modules that will need to be written:
  • dac_driver.{c,h} - Driver for the digital-analog converters. (Darryl, Mike)
  • reentr.{c,h} - Support for reentrant operation (multiple execution contexts). (Mike)
  • interrupt.{c,h} - Code for setting up and handling interrupts. (Mike)
  • icdp_driver.{c,h} - Driver for the input capture datapath. (David, Darryl)
  • serial_driver.{c,h} - High-level driver for the user serial port (DE9 at J49), a.k.a. uart_0.  (This really just uses standard I/O library functions, which use the driver built into the runtime.)
  • cmd_interp.{c,h} - Command interpreter for command lines sent via JTAG UART and/or the user serial port (which will initially come from UwTerminal, and later will be command lines from the server from a TikiTerm window)
  • main.c - Finish filling in main-line code to start everything up.
OK, with some help, Darryl got most of the way through writing his DAC driver code.  After he left I finished it and cleaned it up and added comments and made sure it compiled.  Then I added a call from main to call it, and hooked it up in the top-level schematic.

At one point, I had to create a new folder for the firmware (software_v2) because of apparently some stupid Vista permissions problem, perhaps resulting from Darryl working in the same folder, or from both of us having the Nios IDE tool open in the same workspace in the same time (perhaps we shouldn't do that).

Just tested the new design, with firmware, it works!  All DAC outputs were set to (new) default levels, in software, to an accuracy of 1-2 mV.

Note:  There is some 300 mV noise at about the system clock frequency during the streaming of the pulse data to the scope, which may explain why I'm seeing an unstable value in the time of the falling crossover of the threshold at 300 mV - this should (may?) get better though once the CPU is pulling the pulse data, since that will happen more slowly.

    No comments:

    Post a Comment