Thursday, July 28, 2011

Driving, Interrupted

Today I want to work on the interrupt-handling subsystem (reentr.{c,h}, interrupt.{c.h}), while David hopefully writes most of the driver code for the input-capture datapath.

I need to define some data structures for him to work with, and outline his main functions for him.

Also, I decided to merge the icdp_stat and icdp_ctrl registers into a single bidirectional icdp_ctrl register - it will simplify things not to have any more registers than necessary.  The SOPC builder design and the top-level schematic will need to be changed as well.

We are having a group meeting with Ray at about 4:00 pm.

OK, I wrote reentr.{c,h}, but it still needs to be tested.

The new register format for the icdp_ctrl PIO (with both control & status bits) will now be:
  • Bit #0:  RUN_PAUSEn (output only) - 1 to run, 0 to pause datapath.  Currently unused (DP always runs).
  • Bit #1:  PUMP_DATA (output only) - 1 to pull next word, 0 to relax. 
  • Bit #2:  BUF_FULL (input only, interrupt) - 1 when DP is stalled b/c FIFO is full; 0 otherwise.
  • Bit #3:  HAVE_DATA (input only, interrupt) - 1 where there's data waiting to be read; 0 otherwise.
I updated the SOPC design and am regenerating the Nios system.

Hooked up the CPU in the top-level schematic, and made a new version of the top-level schematic (top7) that removes all of the now-unused test stub modules and cleans up the format a bit.  Recompiling the new schematic with the CPU in place.

Fitter is slow!  At some point, I should perhaps switch it back to Standard mode, and see if it is still fast enough at that speed. 

Now recompiling the firmware, to rebuild the system libraries for the new icdp_ctrl PIO, and test-compile the new reent.c module.

Hum, had a weird problem again where the compilation environment forgot how to build stuff.  I think that both of the times this happened recently, it was because I had just done a "make clean."  Note to self:  Don't do a make clean.  Anyway, created a new software_v3 folder as a workaround.  Whoops, same problem there?  Aha, the problem was my "for reference" folder where I put the GPS main.  Renamed it to for_reference and removed it from the (v2) project.

David wasn't able to open the workspace while I was working in it, so I created another copy called software_david for him to work in.  Later, Darryl can create one named software_darryl, and I will rename mine to software_mpf when I can.  We'll have to manually copy changed source files back and forth between them as needed, but at least we'll all be able to see each other's code.

I wrote the icdp_driver.h file defining the interface to the icdp_driver module, and David and Darryl are working together on writing the implementation (.c file).

We had our group meeting reviewing the project status.  Tyler wasn't able to make it, but David and Darryl and I (and Ray) were there.  Ray says we should do a test with the pocket pulser soon, and plan to test with the real PMTs after Aug. 15th.  There will be a group dinner next Thursday.

David and Darryl are making progress on the icdp_driver.c module.  Meanwhile, I wrote interrupt.{h,c} and am test-compiling them; they have not yet been test.  That will probably have to wait until the ICDP driver is finished (since we will not be able to get repeated interrupt events until the driver is consuming the input data).

OK, interrupt.c compiles cleanly now... Next the students need to finish up icdp_driver.c so that it can be linked in and we can run a test.

David, Darryl, a suggestion:  If you are having trouble putting together the driver code in your head, then break down the problem into smaller, bite-sized pieces: i.e., use modular design.  For example, here is a good helper function you should implement:

unsigned int get_next_word(void);


This should do everything necessary to pump out the next word of data from the device, and return it.  Then you can use this function as many times as you need in the code, without repeating the work of writing it each time.


You can do it.  It's really not difficult at all...

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.

    Tuesday, July 26, 2011

    Power Play

    It occurred to me when leaving yesterday that I should check the +2.5V power supply of the DACs, how it is wired in the OrCAD schematics, where it comes from...  It might be sagging for some reason, possibly explaining the delayed output.  E.g., perhaps there is a short between it and an FPGA pin; or perhaps some other device on the board (an ADC) is drawing a lot of power from it; or perhaps the voltage regulator that is supposed to supply it is not being turned on.  I'll check that today.

    OK, in the OrCAD schematics, the name of the +2.5V supply going to the DACs is "+2.5VCC".  Let's do a search to see where else that is used.

    OK, interestingly, on page B4POWER_PROGRAM, the +2.5V supply is connected to the FPGA on 8 pins with four port names:  VCCIO1 (M22+AA22), VCCIO2 (L22+B22), VCCIO5 (B1+L1), VCCIO6 (M1+AA1).  Not sure yet if the FPGA is supposed to be supplying, or consuming this level.

    On that same page, +2.5VCC also appears to be used by the JTAG interface IC, ref. des. U7, on its VCC port (pin 4).

    The FPGA is probably just consuming the level, because on the B7Regulators page, +2.5VCC appears to be produced by voltage regulator U40 on pin 4.  A handy place to measure the level near the source looks to be JP14 (a SIP-2P), pin 1.

    There do not appear to be any other connections to this node, except for capacitors.

    So, let's check the original design to see what it does with the VCCIO1-2,5-6 ports.  These appear to be all hard-wired pins (upward triangles) for driving I/O banks.  So, maybe it is the VREF groups that are the problem.  At some point I should spend some time trying to better comprehend VREF groups and I/O banks.

    After powering up the board, JP14 (+2.5VCC) reads at 2.416V.  (A bit less than +2.5V - perhaps this is why the DAC outputs don't get closer to +2.5V in any tests?)

    Programmed in the new project.  Hm, no change in the +2.5V supply level.

    Let's go back to the I/O banks.  Each I/O bank has an associated VCCIO pin.

    In the old project, the I/O banks were:
    • OSC100MHzin (3.3V LVCMOS) - Pin AB13, I/O bank 8, VREF group B8_N1.
    • PULSE[1] - (FILL THE REST IN LATER AS NEEDED)
    • PULSE[2]
    • TVTH[5]
    • TVTH[3]
    • P1VTH[3]
    • PULSE[6]
    • P2VTH[6]
    • P4VTH[5]
    • P2VTH[3]
    • P1VTH[1]
    • P1VTH[5]
    • P4VTH[6]
    • TEST[6]
    • TEST[7]
    • TVTH[6]
    • FIFO_FULL
    • P1VTH[6]
    • DACCLK
    • DACCS
    • DACIN
    VCCIO8 is pins AB12+AB20, which go to +3.3VDOWN, and VREFB8N1 is pin AA14, which goes to +1.2VCC, which comes from voltage regulator U39. 

    VCCIO7 is pins AB3+AB11, and VREFB7N1 is pin W6, which goes to +1.2VCC, which comes from voltage regulator U39.

    I noticed a couple of synthesis/fitting settings that were different between the two projects, and made them the same... Now recompiling.  Nope, that didn't help.

    Let me try copying Darryl's new modules over and including them...  Also their version of the controller.

    dac_cpu_test.{vhd,bsf}, dac_cpu_if.{vhd,bsf}, dac_control.{vhd,bsf}

    The reason being, it will be easier to inspect the DAC output signals on the scope to diagnose what's wrong there with a periodic signal.

    Couldn't find anything wrong with the DAC outputs.  And reverting to David's version didn't help.

    Next I tried importing the old top-level file and the instance assignments into my new folder.  No dice.

    Then I tried importing my new design files into the old folder.  That worked.

    So next I tried importing global assignments from the old folder into the new folder.  That worked, but now I have all the pin assignments again.  Plus a bunch of other stuff that I don't understand.  Anyway, it works now.

    Next I deleted the unused pin assignments manually.  While doing this, we noticed various "altera_reserved_" ports that were being used in the old assignments - we kept these, as well as the other global assignments, and that works still.

    Next things we can work on:
    • Share the new folder
    • Test with external pulses
    • Write C driver to set DAC levels
    • Write the rest of the C code (pump pulses on interrupts, generate output stream to Wi-Fi, eventually also handle input commands) 
    OK, I put the new project into the shared folder, and David mounted it from the other computer.

    We hooked up a signal generator to generate approximate triangle waves, and confirmed that the number of thresholds crossed was appropriate for the pulse height.  However, we saw a lot of noise in the digital pulse width values.  This appears to be primarily due to timing errors, perhaps due to the timing constraints file not having been set up properly.  Tomorrow I will see if I can fix this and get a little better performance.  For now, we turned down the system clock speed by a factor of 2, and are getting reasonably stable outputs.  For example:

    Here as an input pulse produced by a waveform generator, with nominal pulse height of +2.6V, 20/60 ns leading/trailing edge transition times, and 58 ns pulse width.   (In this trace, the horizontal scale is 20 ns/division and vertical is 0.5V/div.)

    Test input pulse produced by our waveform generator.
     And, here is the corresponding output from our test bench:


    The purple line at the top is the input pulse, zoomed out to a wider timescale.  The six threshold levels used in this test were 0.24, 0.50, 1.00, 1.50, 2.00, and 2.41V respectively.  The time resolution used for input capture in this test was 4 ns.

    The output digitally reported (streamed out under control of the light blue pump signal) is: All 6 threshold levels were crossed, with crossing times (in hexadecimal): 0, 1, 2, 3, 5, 6, 8, 11, 15, 19, 23, 25.  Multiplying these time counts by the 4 ns resolution, and plotting them against the known threshold voltages, we obtain the following chart,

    Which appears to be a reasonably faithful representation of the original pulse, given the limited time resolution used in this test.  (We could do even better if we were reconstructing a best-fit pulse shape from an analytical model of real input pulses from a PMT.)

    All in all, I'd say it was a day of pretty good successes...

      Monday, July 25, 2011

      De bug! De bug!

      Temporary jury-rigged cooling setup for our FPGA board.
      Today I need to debug the problems with my new project.  We have two major issues at the moment:  (1) Test bench for the IC datapath no longer working reliably after a little while; (2) DAC outputs not right.  The verification problem in Nios IDE went away by itself (this time at least). 
      • Theory: (1) could be a timing problem that manifests at higher temperatures, due to overheating at higher power level caused by the Nios core.  Try cooling, slowing down system clock.
      I tried slowing down the clock by 2x.  This fixed the problem with the test rig for the input-capture datapath (but not the DAC problem).  Then I placed a couple of metal blocks on the board (on the FPGA and the main voltage regulator) with a thermoelectric cooler on the FPGA block.  I will see if this allows me to turn the clock speed back up.  It seems to help, but the DAC controller is still having the same problem.  What is weird is it gets the right value while programming the next design into the FPGA (as soon as the .sof file starts downloading)!

      I brought in a nail file today, and filed down one of the SMA connectors to where it fits OK in its thru-holes.

      Successful test of the CPU interface to the DAC controller.
      The input stub generates a voltage ramp from 0 to +2.4V.
      Back to the old project.  Darryl arrived and coded up a new input stub "dac_CPU_test.vhd" and wired it up.  We found a few bugs in it and fixed them.  After that, his dac_cpu_if.vhd module worked perfectly, generating the desired voltage ramp!  Congrats to Darryl on writing a module that worked perfectly on 1st test!  That is a real milestone for any programmer.

      David and I looked back at the DAC_control module again to see if we could figure out what might be causing it not to work properly in the new project.  We didn't see anything obvious.  But, next we'll try initializing the output signals on first load to see if that helps.

      Now that we know they work, I should also try importing the CPU interface and input stub into my new project...  Maybe for some reason, they will succeed where programming the default levels failed...

      Friday, July 22, 2011

      DAC to the Future

      Today, I hope to finish debugging the DAC controller, so that next week the students can exercise the DAC CPU I/F with a custom driver stub module.

      Also, I need to finish re-testing the skeleton C code and add the serial test code to it.

      David said he might drop by at some point this afternoon with his parents so that they could see the lab.  He said he would text first though.  - They came by and we chatted for a while.  His Dad suggested we use a dremel tool to file down the pin edges on the SMA edge connector.  Ray said we might have one upstairs in the physical electronics lab.  However, we went upstairs and couldn't find it - he might have misremembered.  We could requisition a new one, or perhaps just some new parts.

      After David left, I finished updating the code to take 8 system clock cycles instead of 6 per bit-clock in the DAC output stream, and re-tested the levels.  It worked!  The new values are:  2.4155, 1.9996, 1.5017, 0.9991, 0.4994, 0.0004.  I.e., all but the first are correct to within <1% (<10 mV), and the first one is only off by 100 mV because +2.5V instead of +2.7V is supplied to the DACs, which we already knew was a problem.  Ray says that's fine, because we can add an analog inverter, so that our thresholds will be at the low end of the scale, instead of the high end.

      Here's a graph of the data... Nice and linear, aside from the slight expected slumping at the high end.  Note also all points but the last one fall squarely on the multiples of 0.5V, as expected.
      I tried integrating the latest code into my new, slimmed-down project with the Nios system, but I am having some weird problems:
      1. When I try to download the ELF from the Nios II IDE into the Nios system, it is failing verification and won't proceed with the run.
      2. When the design is loaded, the COSMICi banner appears on the JTAG STDOUT (viewed in nios2-terminal), and the test pulse sequence appears as expected at first, but...
      3. The digitized output data was missing on some of my test runs (but not others);
      4. The DAC levels are initially wrong (way off)... but then,
      5. After just a minute, the following things all happen at about the same time:
        • The sequence of test pulses halts;
        • The DAC level goes to the CORRECT value (?!?!?)
        • An I/O error on JTAG UART causes nios2-terminal to exit.  (Sometimes after outputting a sequence of bad characters first.)
      This is all rather confusing and mysterious, and I don't have a clue what's causing it, and I think I need to just sleep on this over the weekend and return to it again on Monday...  Have a good weekend, dear readers.

      Thursday, July 21, 2011

      Cleaning House

      We were going to have a lunch meeting today, but the place we were planning to meet at was closed.

      I'm thinking maybe today I'll build a new project from scratch, as a maximally-clean place for us to work in, so we don't have to deal with all the files and assignment warnings still left over from Sachin's version.  If we need anything from Sachin's design, we can always pull it in.  And, I can make the port names more informative.

      Meanwhile, David or Darrell or Tyler (or whoever shows up) can continue to work on the DAC controller.

      Once I finish my cleanup, we can reintegrate everything into the new project, and continue working on the C development in there.

      Created a new folder C:\SHARED\FEDM_code_v2\q91 to do the cleanup work in.  (Haven't actually shared it yet.)

      The device will be Stratix II: EP2S30F484C3.

      The design files include (copied from old project's file list):
      • [/] COSMICi_top6.bdf
      • [/] pulse_gen2.vhd
      • [/] hspeed_counter.v
      • [/] my_pll.v (plus .inc, .ppf, .qip, _bb.v)
      • [/] my_altclkctrl.v (plus .inc, .qip, .v, _bb.v)
      • [/] decs_cntr.vhd
      • [/] pde_reg2.vhd
      • [/] pmt_ic_datapath2.bdf
      • [/] pulseform_cap.bdf
      • [/] pulse_prep.bdf
      • [/] pulse_combine.vhd
      • [/] cs_combine.vhd
      • [/] pde_dff2.vhd
      • [/] pulse_cap.vhd
      • [/] pde_dff_en.vhd
      • [/] pde_shift_reg.vhd
      • [/] pde_dff.vhd
      • [/] our_fifo2.bdf
      • [/] fifo_writer2.vhd
      • [/] pulseform_fifo.vhd (plus .bsf, .qip, _wave0.jpg, _wave1.jpg, _waveforms.html)
      • [/] fifo_reader2.vhd
      • [/] stream_pulse_data.vhd
      • [/] stream_pulse_out_test.vhd
      • [/] FEDM_NiosSys.vhd
      • [/] cpu_0_test_bench.vhd
      • [/] cpu_0_mult_cell.vhd
      • [/] cpu_0_oci_test_bench.vhd
      • [/] cpu_0_jtag_debug_module_wrapper.vhd
      • [/] ... (all cpu_0 files)
      Also:
      • [/] Symbol (.bsf) files associated with the above design files.
      • [/] FEDM_NiosSys.* (all files associated with the SOPC system design)
      • [/] jtag_uart_0*.*
      • [/] icdp_ctrl.vhd (these 3 are PIOs)
      • [/] icdp_data.vhd
      • [/] icdp_stat.vhd
      • [/] onchip_memory2_0*.*
      • [/] uart_0*.*
      OK, that's all copied over.  I think that's it, but if I forgot anything I will grab it later.

      Now running the New Project Wizard to create the new project.

      Working directory:  C:\SHARED\FEDM_code_v2\q91
      Project name: COSMICi_FEDM
      Top-level entity: COSMICi_FEDM_top6 (renamed COSMICi_top6.bdf to this)
      Did "Add All" to add all design files in the folder to the project.
      Selected the device.
      Finish.

      Now, I need to create pin assignments.  Let me refer back to our existing project first.

      Currently used pin location assignments are:
      • Input clkin_50MHz -> OSC100MHZin -> PIN_AB13 (3.3V LVCMOS) - (Also clock setting)
      • Output sys_clk -> TVTH[6] -> PIN_AA17 (3.3V LVTTL)
      • Output pd -> FIFO_FULL -> PIN_E12
      • Output hd -> P1VTH[6] -> PIN_F14
      • Output data[0] -> P2VTH[6] -> PIN_J15 (3.3V LVTTL)
      • Output data[1] -> P4VTH[5] -> PIN_G16
      • Output data[2] -> P2VTH[3] -> PIN_G15
      • Output data[3] -> P1VTH[1] -> PIN_F17
      • Output data[4] -> P1VTH[5] -> PIN_F15
      • Output data[5] -> P4VTH[6] -> PIN_G14
      • Output data[6] -> TEST[6] -> PIN_G13
      • Output data[7] -> TEST[7] -> PIN_C12
      • Output pf[1] -> PULSE[1] -> PIN_B11
      • Output pf[2] -> PULSE[2] -> PIN_C10
      • Output pf[3] -> TVTH[5] -> PIN_F9 (3.3V LVTTL)
      • Output pf[4] -> TVTH[3] -> PIN_G8
      • Output pf[5] -> P1VTH[3] -> PIN_F7
      • Output pf[6] -> PULSE[6] -> PIN_H7
      • Output tx -> RESET1 -> PIN_AB15 (J49 pin 3)
      Let's create new assignments for these, and rename the ports a little more sensibly with reference to the details of the actual board/layout/schematic (in descending order of importance).
      • [/] Input clkin_50MHz -> OSC1_p1_50MHz_in -> PIN_AB13 (3.3V LVCMOS)
      • [/] Output sys_clk -> J45_p2_GP0 -> PIN_AA17 (3.3V LVTTL)
      • [/] Output pd -> J48_p2_GP1 -> PIN_E12 (3.3V LVTTL)
      • [/] Output hd -> J55_p2_GP2 -> PIN_F14 (3.3V LVTTL)
      • [/] Output data[0] -> J82_p1_GP3 -> PIN_J15 (3.3V LVTTL)
      • [/] Output data[1] -> J73_p1_GP4 -> PIN_G16 (3.3V LVTTL)
      • [/] Output data[2] -> J74_p1_GP5 -> PIN_G15 (3.3V LVTTL)
      • [/] Output data[3] -> J53_p1_GP6 -> PIN_F17 (3.3V LVTTL)
      • [/] Output data[4] -> J55_p1_GP7 -> PIN_F15 (3.3V LVTTL)
      • [/] Output data[5] -> J72_p1_GP8 -> PIN_G14 (3.3V LVTTL)
      • [/] Output data[6] -> J71_p1_GP9 -> PIN_G13 (3.3V LVTTL)
      • [/] Output data[7] -> J75_p1_GP10 -> PIN_C12 (3.3V LVTTL)
      • [/] Output pf[1] -> J76_p1_GP11 -> PIN_B11 (3.3V LVTTL)
      • [/] Output pf[2] -> J77_p1_GP12 -> PIN_C10 (3.3V LVTTL)
      • [/] Output pf[3] -> J58_p1_GP13 -> PIN_F9 (3.3V LVTTL)
      • [/] Output pf[4] -> J57_p1_GP14 -> PIN_G8 (3.3V LVTTL)
      • [/] Output pf[5] -> J54_p1_GP15 -> PIN_F7 (3.3V LVTTL)
      • [/] Output pf[6] -> J79_p1_GP16 -> PIN_H7 (3.3V LVTTL)
      • [/] Output tx -> J49_p3_UARTTX -> PIN_AB15 (J49 pin 3)
      OK, now let's try a compile!  Had a few mistakes, but those were easily fixed.  Timing analysis failed to meet fmax constraints, but the thing works anyway.  The power consumption is up with my current design compared to the students'; perhaps this is just because the Nios system in there, but at some point we need to go through things, like make sure the ADCs and the USB chip are turned off, and that there are no fights on FPGA pins, to minimize board power consumption.

      Next, I need to try actually running my C code in the new project (both on startup & under debugger), and redo in it a serial output test like the one I did several weeks ago.

      Meanwhile, David is here, and is continuing to write the code for DAC_control.vhd.  He finished the code and we did a test (intending to get 2.5, 2.0, 1.5, 1.0, 0.5, 0.0V) and got ~2.4V on the 1st 3 thresholds, 1.2V on the 4th, and 0 on the last 2.  Then we made a couple of changes (correcting some errors in the timing sequence) and tried again; got (2.4, 2.2, 1.3, 1.2, 0.0, 0.0).  The fact that the maximum value isn't 2.5 isn't surprising, since the board is underpowering the DACs, but the rest of the scale seems a lot more nonlinear than we expected.   But we are getting close.  Next thing to try, tomorrow:  Slow down the timing sequence a little (we are pushing the edge of the spec right now).  Also, examine the control signals on the scope to make sure they appear as intended in the code.

      Meanwhile, Darryl arrived and has started working on the DAC CPU interface (under VirtualBox on the center-desk Mac).  He thinks his module is basically finished, but we still need to test it - we'll do that next week.  He can write a simple input driver stub, or we can just try driving it from the C code.

      A test driver stub module could do something like this:  Every 50 microseconds, increase one of the DAC levels by 1 (it only takes ~10 microseconds for the programming sequence); then on the scope, that level should rise from 0-2.4V in a sawtooth waveform with a ~200 ms period (to go through all 4,096 levels).

        Wednesday, July 20, 2011

        Stacking the DAC

        Today I would like the students to work on coding the DAC controller, while I continue working on the C code.

        I forgot to bring in a nail file for the SMA connectors; will have to retry remembering that tomorrow.

        Darrel is here, he got up to speed on the requirements for the DAC_control module and started coding.

        Meanwhile, I (Mike) integrated the recent changes from the students' work in Dropbox into my new Q:\ shared working directory, and into my new top-level schematic (now named COSMICi_top6.bdf), removed unnecessary debug outputs, recompiled, and regression-tested (well really, just redid the last test in the new working directory).  It is working.

        I am also starting work (in Q:\) on cleaning up the project by updating the project's file list, deleting unused or unnecessary files, and adding files not yet explicitly listed.  I am also adding file headers, cleaning up file formatting, etc.

        I finished deleting from the project's file list all the files we aren't actually using right now.  I added most of the files we are using, except I haven't finished going through all the auto-generated .vhd files for the Nios system yet.

        I deleted the SignalTap instance (which we aren't using), and thought I deleted all the associated assignments, although I am still getting some warnings, so it seems that I must have missed something.  Guess we could always fix this problem by creating a new project from scratch and only copying over the assignments we want.

        Anyway, at least I didn't break the functionality of our input-capture datapath.  Our test bench still works.

        Tuesday, July 19, 2011

        In & Out

        Today I have to go out for an appointment at 11:00-1:00 or so, and another from 1:30-3:00.

        To do today:
        1. [/] Email students my schedule for today. - Did that, also included some instructions in the email.
        2. [/] Get students started developing DAC interface. - Discussed this in the email, copied datasheet to Dropbox folder.  Then we examined the schematic had some discussions
        3. [/] Do receiving on SMA connectors, which I picked up from the office yesterday. - OK, did receiving with date back-dated to yesterday.  Also checked to see if the receptacles fit in the thru-holes.  The pins seem to be slightly too thick (perhaps because they are square instead of round as expected).  They could probably be filed down to the point they would fit.  Try that next.  Couldn't find a suitable file in the lab.  [ ] Bring a nail file or something from home tomorrow.
        4. [ ] Work on MCU C code while students are studying the DAC.
         So, here's what we've figured out so far regarding the DAC controller after looking at the DACs' datasheet and the board schematics in OrCAD.
        • The control signals (in OrCAD) output from the FPGA are: DACCLK (pin A13), DACIN (pin E11), and DACCS (pin Y2).  The 6 DACs are daisy-chained together as a shift register, in the order (from first (least significant) to last (most significant)) VTH1 - VTH6.  
          • DACCLK is the CLK (input register clock) input to all the DACs (all clocked in parallel); 
          • DACIN is the D_IN serial input to all the DACs (really to just the first one on the chain, and daisy-chained to the others), 
          • DACCS is the CS_n/LD control input to all the DACs (all controlled in parallel).
        • The protocol to program the DACs is then (ignoring timing details, which David is figuring out): 
          • (1) Make sure DACCS is lowered, so that we can load new values.
          • (2) Stream the 72 (12x6) data bits, last threshold first, MSB first for each threshold, out to the shift-register chain as follows:
            • Assign the new value of DACIN to the next bit; wait a bit.
            • Raise DACCLK; wait a bit.
            • Lower DACCLK; wait a bit.
          • (3) Raise DACCS; wait a bit.  (This is when the DAC outputs are actually changed.)
        • The DAC transfer function should be approximately linear, with the range 0=0V to 4,095=~+2.5V, except that in practice it may not be able to get quite all the way up to +2.5V, since we are only supplying it with VCC=2.5V, instead of at least 2.7V as was required by the spec.  As a test, we should set our max threshold to 4,095 and measure the output voltage with a multi-meter or the scope.  (Note that if it is not +2.5V, this will limit our sensitivity to low-amplitude pulses.)
        • David worked out the detailed timing sequence for the output control.
        • Our plan is to have the new DAC_control module automatically program some default levels into the DACs after a short pause after it first turns on, then afterwards accept & program new 72-bit words from an external client on request.
        • Then we'll also write another module DAC_CPU_IF (CPU interface) which remembers the current 72-bit word in a register, and takes a 16-bit PIO output bus from the CPU as its input.  Bits 11-0 (12 bits) are the new threshold level, bits 14-12 (3 bits) is the ID 001-110 (1-6) of the DAC whose level to set, and bit 15 (1 bit) is set to 1 to accept a new 12-bit word (load it into the register), and then (just afterwards) to 0.  Then, when all thresholds that need to be modified have been loaded, the high nibble should be set to 1111 (F=15) as a special command which tells DAC_CPU_IF to tell DAC_control to start the sequence to program the new levels; then (just afterwards) bit 15 is cleared.  The driver code in the MCU should wait long enough, after sending this command, to allow the entire programming sequence (for all 6 levels) to finish.  (This hard-coded delay keeps the interface simple by avoiding the need for return handshakes.)
        David is starting on writing DAC_control.  I asked Tyler if he can start on the CPU interface, but first he is reading the SPIE paper.  Darrel should be here tomorrow, and he can work on the CPU interface as well.

          Monday, July 18, 2011

          Things to Do Today

          Things to do today (or at least start doing):

          [/] Check on why I only got half of my last paycheck - call Sonja.  She confirmed it was just an end-of-year processing glitch and that we should get paid for the missing time next payday.

          [/] Figure out why shared network drive didn't work; get it working. - OK, I believe the problem is fixed now.  First I created a new group called Quartus Developers and gave this group ownership of C:\SHARED\FEDM_code, and put all of us into it, as well as a new user "Test User" which I created for testing purposes.  Then I also gave the NETWORK user group full access to C:\SHARED\FEDM_code.  Then I turned on network sharing for C:\SHARED\FEDM_code (instead of just the parent folder C:\SHARED).  Then from the Test User account, I mounted \\COSMICi\FEDM_code\q91 as drive letter Q:\, and then I was finally able to open the Quartus project and the files within it from the Test User account.  I'm not sure if all of these steps were strictly necessary, or if security could have been battened down a little tighter while still allowing access, but hey, it worked.  Next I have to check and make sure that Test User can also still access the project from the other computer.  OK, that works too (after setting up the Test User account on the Acer and pointing Quartus in it at the floating license server at 1800@192.168.0.2).  However, I think we will have problem if the Quartus project files are open on two different computers at once... So we'll need to be careful.

          [/] Check out current status of student work.  Pull their stuff back into the main development line.  Get rid of the extra working directory in Dropbox. - David and Darrell are here.  Ah, and Tyler for a while.  David says they can re-merge the working directories.  Darrel says he thinks he found the problem in the code - I will look at it.  Details below.

          [/] Make forward progress on testing & debugging of input capture datapath. Hopefully finish it this week.

          [/] Check on status of SMA jacks we ordered last month.  Push 'em along...  And solder 'em on when they arrive. - OK, we got 'em.  Still need to solder. [ ]


          [ ] Continue development of Nios C code; get to the point of testing IC datapath with it.

          [ ] Develop DAC <--> PIO interface; program DAC levels in C.

          [ ] Test with real analog inputs.  (It would be nice to have the SMA jacks first...)

          More details of things accomplished today:
          • The guys re-merged the working directories (and moved the temporary one out of Dropbox).
          • Yep, Darrel correctly identified a bug in my code - I didn't update the state properly in one state - I fixed that and it solved the sequencing problems.
          • He also identified that my code was outputting all 6 data pairs instead of only the valid ones (for crossed threshold).  I fixed that and now the output streams are the right length.
          • Darrel then modified his code to output 0 at the end (for cleaner output).
          • We realized we were using the wrong version of the test module but managed to retrieve the correct one from Dropbox's archives of old versions.
          • We changed the logic to correctly handle the first word (number of thresholds).
          • We then had a bug where there was no output after the first word - this was due to using <= instead of = when testing a logic flag!  (1-character error).
          • Then the overall form of the sequence was right (threshold, zero, deltas) but the deltas were all wrong.  I examined my FIFO code and realized that I had swapped the order of the leading & trailing edge longwords within each 128-bit chunk of my data packet (had leading=MSLW on input, and trailing=MSLW on output).  After fixing that we are getting all right outputs.

          YouTube video of results (also posted to lab Tweet stream):

          Friday, July 1, 2011

          It's Julius Caesar's month!

          Today, I am getting ready a list of things that the students can work on over the next couple of weeks.  Here are some relevant items the students can help with:
          1. Create a new test stub to allow the output from the stream_pulse_data module to be viewed conveniently on the scope (as we discussed yesterday, and as I described in my last post).

          2. Study the datasheet for the DACs and write a module to set the threshold levels.  Alternatively (or in addition), write an interface module to the DACs that allows the Nios system to set the threshold levels by bit-bashing in the C code.

          3. Alternatively (or before #2 is completed), Sachin's design can be temporarily re-integrated with ours, for purposes of using it to set the DAC levels.  However, to be able to access it from LabView, we'd have to get one of the XP systems up and running again.  Juan's most recent suggestion was to reinstall XP.

          4. After either #2 or #3 is finished, a real analog input source can be hooked up to the PMT inputs and digitized using the input capture datapath (together with one of our diagnostic output stubs).

          5. I need to create a shared folder (with no spaces in the pathname) so we can all work on Nios system development.  I need to start pulling in code from my previous Nios app (the GPS app).  When this framework is ready, the students can help working on C code development. -- See below for status.
          Pursuant to this last item, I created a folder C:\SHARED\FEDM_code\, and gave full permissions on it to Darrell, David, Tyler, and myself.  We should be able to mount it over the network from the students' accounts on the Windows 7 computer - try that later today.  (Note: Works fine over net from Win 7)

          I created a subfolder q91\ for development in Quartus II 9.1 (32-bit), so that in case eventually we upgrade our license to a newer version of Quartus, we can create a different parallel folder to work in with the new version, and avoid screwing things up with incompatibilities between the versions. 

          I copied all the project files from the shared Dropbox folder "FEDM_design\Our new gelware" into the new folder C:\SHARED\FEDM_code\q91\.

          Now, I have also mapped this folder as a "network drive", "Q:\" (Q for Quartus).  Of course, since it's a local folder, the "network" is really just a loopback in this case.  But, this will allow this to use the same pathname to refer to this folder on other computers in which it really is mapped as a network drive.  That way we won't constantly have to be changing pathname settings when compiling in different places.

          The "software\" subfolder (C:\SHARED\FEDM_code\q91\software, accessed via the name "Q:\software") will be used for Nios system firmware development.  It already contains a "hello_world_0" subfolder left over from some earlier development experiment.  Starting the Nios II IDE (v.9.1) and setting the workspace to that folder (using the name "Q:\software").

          Now creating a new "Nios II C/C++ Application".  The project name is "FEDM_ctrl_fw" (for Front-End Digitizer Module control firmware).  Selecting the appropriate .ptf file, "Q:\FEDM_NiosSys.ptf" (this was created during system generation in SOPC Builder).  Using "Hello World" as the project template. 

          Doing a "Build All" on the newly-created software project, just to make sure the system library and everything builds correctly.  (That's fine, although you have to close other programs in order for there to be enough memory to compile some of the modules.)

          Added the FEDM_NiosSys instance back into the top-level schematic; recompiling the Quartus design...
          Ah, I notice this version of the Nios system doesn't yet have the PIOs - that version was in my LOCAL folder; I'll grab it and put it back in here in a bit...  First though I just want to do the "Hello World" test.

          Compilation was successful; now programming board...  FIFO test is still working.  Starting SOPC Builder -> Nios II -> Nios II Command Shell.  Typed "nios2-terminal"; it auto-detected the JTAG UART through the ByteBlasterII [LPT1] cable, and displayed the "Hello World" console output.  So the Nios system is working as well.

          Switched the current revision we are working in (in this q: folder) over to COSMICi-mods.  I'd like us to do all our work in this revision (or successors to it), so as to keep our new pin assignments separate from all the older pin assignments as much as possible.  That way, we can also safely delete assignments we aren't using, without worrying that they will be lost & gone forever, oh my darling, Clementine.

          Changed the top-level entity for the COSMICi-mods revision to COSMICi_top5, which was the one we were most recently working in (over in the Stratix_TDC_v1 revision).

          Imported settings from Stratix_TDC_V1 revision into the COSMICi-mods revision.

          Recompiling the project again, to make sure I didn't screw anything up when switching revisions.  I did have to remove a test file "testout.vhd" from the project.

          New revision COSMICi-mods works, and "Hello World" still works.  Now it's time to import my newer version of the SOPC system.

          Went to C:\LOCAL\FEDM_gelware\COSMICi-mods\, which is the folder I had been working in before, so as not to interfere with the students' work in the shared Dropbox folder.  Grabbed the FEDM_NiosSys.sopc file, copying it over to Q:\.  Opening SOPC Builder.  Yes, my three PIOs are in there:  icdp_ctrl, icdp_stat, and icdp_data.  Now regenerating the system.

          System generation was successful.   Now doing the equivalent of "make clean; make all" on the software code - i.e., in Nios II IDE, Project -> Clean..., with "Start a build immediately" checked.  This is because the system library has to be rebuilt since the set of devices in the system has changed.  Compiling now...

          That worked.  Now back in Quartus, I am updating the symbol for the FEDM_NiosSys instance back in the COSMICi_top5 schematic, so the ports for the PIOs will appear.  Great, there they are.  Now I am wiring buses to them, called icdp_data[31..0], icdp_stat[7..0], and icdp_ctrl[7..0]. In my blog post from Monday, I documented the meaning of the bits in the stat and ctrl registers.  Connecting them up to appropriately named wires in the COSMICi_top5 schematic.

          Next, I spent a while just straightening up the top-level schematic and adding comments, so we can all settle back in more easily after getting back from our long 4th-of-July weekends, 2-week vacations, etc.  Recompiling now to make sure I didn't eff anything up in the process.

          OK, "Hello world" still works in the new system (with the PIO devices added).

          Next, let's see if we can run interactively within the Nios II IDE environment.  Creating a new Nios II hardware run configuration.  Everything looks good; hitting the Run button.  OK, that restarted the firmware appropriately.

          Now referring back to my old GPS application firmware, in C:\f\DE3\S3\SB+SOPC\GPS_FPGA_app\Nios2IDE_Workspace\nios2_gpsapp_v2\main.c, for reference, to see things that need to be pulled into this new application.

          Adding <system.h> to includes, needed for IRQs.  Recompiling to make sure that's found.  It's fine and the IRQ #define macros are in it.  That worked fine.  Adding other #includes from the GPS app.  Those are found too.

          I need to change the main source filename from "hello_world.c" to "main.c".   But Nios II IDE keeps crashing when I click on the C/C++ Build properties!  Oh well, I just coped the file to the new name, and then deleted hello_word.c from the project.

          Now, I have copied main.c from the GPS app folder to the new software dev folder, Q:\software\FEDM_ctrl_fw\GPSapp_main.c, for easier reference while we are putting the new firmware together.  Perhaps the students can start working on this over the next couple of weeks (if they get other tasks done first).  I will do as much of it as I can before I leave today, but my time is limited.  At least I have created the program template, file header, etc.  The GPSapp_main.c shows how to do everything (set up interrupts, access PIOs, etc.) and can be used as a model.

          I'm basically filling in code in main.c in top-down fashion, putting in lots of comments as I go along, as placeholders for stuff that has not yet been written.  So, what I've done is basically a partially-filled-in program outline.  That way, if the students get to the point of working on the C code, they can (theoretically at least) just pick up wherever I left off, and continue filling in the details.