Saturday, August 28, 2010

Lattice / Xilinx FIFO resource issues

If you are like me, then when you design logic to interact with a FIFO, you make sure to carefully control your reads and writes. Since I do this for all FIFOs, it is very wasteful to have logic internal to the FIFO that checks whether I'm writing to a full FIFO, or reading from an empty FIFO.

Altera's tools allow you to choose whether or not you want such overflow and underflow logic in the FIFO. Xilinx and Lattice's tools do not. What this means is that every time you create and instantiate a FIFO with Lattice or Xilinx chips, there is logic that will negatively affect timing and use more resources, internal to the FIFO. This logic is so wasteful (and dangerous since it hides bugs), that I feel it important to point this out to the general public.

If you are using Lattice's IPExpress, the logic is shown in the Verilog or VHDL source files. This is great because it allows you to disable the logic with some simple comments.

For Xilinx, there doesn't appear to be a way to get at the source code that creates the logic, so I would strongly advise asking your FAE to request that Xilinx adds an option to Core Generator to allow for lighter weight FIFO creation that excludes this 'safety' feature.

In my system, I found a significant savings by hacking the (Lattice) created Verilog FIFO and disabling the empty and full check. Since my system depends on correct read and write logic, this was a function that was very useless to me. If I was reading when there was no data, or writing when there was no room - the system won't work anyhow - so I MAKE sure that doesn't happen in my logic.

Thursday, August 19, 2010

gvim 7.3 64-bit (x64) Windows 7, Vista, XP - build instructions and installer

This is an update to:
http://ionipti.blogspot.com/2010/04/build-gvim-72-x64-and-create-installer.html

You can download the actual installer from: http://nkcorner.com/gvim73.exe (64 bit only, includes all patches up to and including 7.3.003).

To create the 7.3 version, you must download:
ftp://ftp.vim.org/pub/vim/unix/vim-7.3.tar.bz2

There are no extra or lang archives. Everything is included in the main archive.

Download the 7.3 patches:
ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.001
ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.002
ftp://ftp.vim.org/pub/vim/patches/7.3/7.3.003

Follow all of the previous instructions (except for what relates to extra and lang archives).

Also modify the gvim.nsi file to change all instances of gvimext64.dll to gvimext.dll.

Other than that, it is all the same.

Monday, August 16, 2010

WRT54GL - GoogleWiFiSecure - OpenWRT

It had to be an eventuality that someone would try to get OpenWRT onto Google's secure wifi network, and that ended up being me. As I couldn't find any other information I had to figure this out for myself.

Here it is:
Use Backfire trunk (currently it's approximately 10.03.1 RC1). Use wpa_supplicant (instead of wpad or wpad-mini), and set it to use libopenssl. Add libopenssl. Add luci-medium too. Use the 47xx Broadcom as opposed to the old 2.4 kernel. Compile. Flash. Look for excellent compilation instructions on OpenWRT's website. I used Debian Lenny in a virtual machine (Oracle VirtualBox) and it went very smoothly.

After compiling and flashing, reboot and then telnet into the system and edit /lib/wifi/wpa_supplicant.sh line 84 from:
peap|ttls)
to
PEAP|TTLS)

It's a bug and hopefully they will fix it. The bug is either in LUCI or wpa_supplicant (probably depends who you ask), but this will get it working either way.

Now go into luci and set the settings. "Path-to-certificate" can be left blank. It will not affect anything (other than to verify server, but Google's WIFI doesn't support that). Set all the other settings as Google instructs:

To connect to GoogleWiFiSecure, create a new network connections profile with the following settings:

SSID: GoogleWiFiSecure (case-sensitive)

WPA/WPA2 Settings
EAP type: EAP-PEAP or EAP-TTLS
Encryption method: AES (preferred) or TKIP
Authentication Protocol: MS-CHAP-V2 or CHAP
Trusted Server Name for Authentication: onex.wifi.google.com

Under the 802.1x settings be sure to enter the username and password that you obtained earlier.

Reboot router and it should work.

Currently this is a NAT configuration. I'm sure with more work you can configure it to be a bridge, but as I passed the router back to my friend, and I have my own internet, I don't care anymore...

Here is a link to the compiled .trx file. You'll need the ability to burn the trx file.
http://nkcorner.com/openwrt-brcm47xx-squashfs.trx
Here is a link to the .config file I used:
http://nkcorner.com/openwrt-config (rename to .config)

PS - For the config, you just do make defconfig, and then choose the Broadcom BCM947xx/953xx (WITHOUT the 2.4!). If you use 2.4 then you won't have the 802.1x authentication which is required for Google's secure Wifi.
Then add wpa-supplicant (remove wpad-mini), and set wpa_supplicant to use libopenssl instead of internal. Then add libopenssl. Also add luci-medium if you want graphical configuration.
Everything else will work fine.

And YES - BCM947xx is the correct target, I know, I know, but the WRT54GL uses the BCM5352. Don't worry, it is the same chipset or something as the BCM947xx series...

This is it.

I'm sure that wpa_supplicant.sh can be changed when creating the image, but I never bothered with it, cause I don't care enough. If you make that change and would like to share how then by all means post a comment. Also note that it seems that after a change is made you will have to power cycle the router to get it to get back onto the wifi network. I don't know why, but I'm happy enough that it gets there once so I didn't bother trying to debug this. A mostly impossible step given my limited knowledge of how OpenWRT works anyhow.

As I don't have this router anymore, I'm probably not gonna update this blog much more unless someone posts an interesting comment which should be added.

Hopefully this will help someone.

Friday, August 13, 2010

SystemVerilog - Interface with modports - master with multiple slaves

Playing around with Quartus 10.0, and so far this is synthesizable. This code uses a generate block to create multiple modports such that I can easily connect many slaves to a single interface programmatically where the interface has one bit per slave in a single bus.

This creates a 6-to-1 multiplexer sourced from 6 latches. Each latch has its own preset, clear, and select, and they all use a shared data and enable input.

Note the use of $size. It could have been done in other ways I'm sure.
Note the use of 'slave_modport_gen' in the instantiation of the slaves. This is how to reference the separate modports that are created in the interface. The need for separate modports is b/c I need to control different bits of q_bus for each modport.
Note the use of .sel(sel_in[i]) in the modport port direction descriptions. This is an alias (aliased to sel inside the module), also required to have the same module be able to control the desired bit of q_bus.


`timescale 1ns/1ns

interface bus # (
 parameter NUM_SLAVES = 1
) (
 input [NUM_SLAVES - 1:0] sel_in,
 input e_in,
 input d_in,
 input [NUM_SLAVES - 1:0] s_in,
 input [NUM_SLAVES - 1:0] r_in,
 output q_out
);

 logic q_bus [NUM_SLAVES - 1:0];

 modport master(
 input sel_in,
 output q_out,

 input q_bus
 );

 genvar i;
 generate
 for(i = 0; i < NUM_SLAVES; i++) begin : slave_modport_gen
  wire e_comb;
  assign e_comb = sel_in[i] && e_in;
  modport slave(
   input .e(e_comb),
   input .d(d_in),
   input .s(s_in[i]),
   input .r(r_in[i]),
   output .q(q_bus[i])
  );
 end
 endgenerate
endinterface

module master(
 bus.master m
);
 integer i;
 always_comb begin
  m.q_out = 0;
  for(i = 0; i < $size(m.sel_in); i++) begin
   if(m.sel_in[i])
    m.q_out = m.q_bus[i];
  end
 end
endmodule

module slave (
 interface s
);
 always_latch begin
  if(s.e)
   s.q <= s.d;
  if(s.s)
   s.q <= 1;
  if(s.r)
   s.q <= 0;
 end
endmodule

module top # (
 parameter NUM_SLAVES = 6
) (
 input [NUM_SLAVES - 1:0] sel_in,
 input e_in,
 input d_in,
 input [NUM_SLAVES - 1:0] s_in,
 input [NUM_SLAVES - 1:0] r_in,
 output q_out
);

 bus # (
  .NUM_SLAVES(NUM_SLAVES)
 ) bus_inst(
  .sel_in(sel_in),
  .e_in(e_in),
  .d_in(d_in),
  .s_in(s_in),
  .r_in(r_in),
  .q_out(q_out)
 );

 master master_inst(bus_inst);

 genvar i;
 generate
 for(i = 0; i < NUM_SLAVES; i++) begin : slave_gen
  slave slave_inst(bus_inst.slave_modport_gen[i].slave);
 end
 endgenerate

endmodule

Wednesday, August 11, 2010

Modelsim - simulating from 2 vendors at once - Verilog

Here's an interesting problem. You want to simulate code from Lattice along with code from Xilinx. (For example when you are simulating a Xilinx PCIe Root Complex against a Lattice PCIe Endpoint!)

Of course you couldn't attempt this without partitioning into libraries (because of name conflicts). So perhaps you have a library called lattice_work and xilinx_work. When compiling the code there are primitives like NAND, NOR, XOR... that are used in the both sets of code. The Lattice code will need to use Lattice's primitives, and the Xilinx code will need to use Xilinx's primitives.

You can use the +v and -y options to have the primitives found and compiled into the lattice_work and xilinx_work libraries, and then you can use the -L work trick (see previous blog http://ionipti.blogspot.com/2010/07/simulating-2-lattice-pcie-cores.html).

The problem with this method is that now whenever you run vlog with the incr flag, it will not only check if the Lattice and Xilinx code is up to date, it will also go and check the primitives! That's a huge waste of time! Also, your lattice_work and xilinx_work libraries will get filled with lots of primitives that you don't care to see.

What I like to do is to compile all the primitives into separate libraries. For example I have for Lattice, ecp3_work and pmi_work. For Xilinx I have unisims_work and secureip_work. The primitives are in ecp3_work and unisims_work. This is a nice method, and of course saves time since I never have to recompile or check for updates on these files. The drawback is that the Lattice code and Xilinx code will arbitrarily pick out the NAND, NOR, XOR, etc primitives and will of course cause lots of errors.

I prefer to not have to add source code modifiers, ie I'd like the source code to not have to change in order to fix this. `uselib is a great solution that typically requires it to be placed before the source. My solution has been to create uselib_xilinx.v and uselib_lattice.v files and add that file in the vlog command per each source file.

For example, instead of calling
vlog lattice_code.v
I now call
vlog uselib_lattice.v lattice_code.v

uselib_lattice.v looks like this:
`uselib dir=ecp3_work dir=pmi_work

This works because the `uselib attribute persists through the vlog command. So even if you call vlog with many files, the `uselib will persist. This of course would be problematic if you have additional `uselib calls in your code since they will override the uselib_lattice's or uselib_xilinx's `uselib attribute.

I wish Modelsim would fix their library issues. The solution of -L work is very problematic, and leads to the bug I describe here (http://ionipti.blogspot.com/2010/07/modelsim-working-with-multiple.html). If they would only add some nice switches into the vlog and vsim commands it would make life much easier.

SystemVerilog disable fork

The short of it is that 'disable fork' is a pain. The long of it is that you have no choice, and perhaps an example might make your lives easier:

fork
begin
fork
begin
#3000;
$display("timeout");
end
begin
sem.get(1);
end
join_any
disable fork;
end
join

Why wrap it in another fork-join pair? This is due to how disable fork works. disable fork disables ALL forks at its level and below. If the above code is inside of a task which is part of a module, then calling disable fork without it being wrapped will disable all forks running in the module. I KNOW! It's ludicrous! Yes, but this is how it works.
What about named forks? Also problematic. This is because when you use a named fork and then call disable , it will disable all instances of the same named fork. If you have multiple threads running the same task and both are in the named fork, then one disable will kill both of them. I KNOW! It's ludicrous! ...
Any other options? I don't know. This seems to be the only way to do the job in SystemVerilog. Perhaps avoiding semaphores and doing everything with wait statements or events, but for now I prefer to use semaphores as they are an item I can 'new', and therefore they allow for much more flexibilty.