Sunday, July 18, 2010

Modelsim, working with multiple libraries - bug - not finding work

In short,

if you have the work library and another library named test, and you have:
work:
top
work_mod

test:
test_mod

and top instantiated test_mod which instantiates work_mod, you will get an error at vsim time that modelsim can't find work_mod. This is due to how Modelsim determines the work library when instantiating the test_mod. The typical command you would use is:
vsim work.top -L test - this produces an error
vsim work.top -L work -L test - also an error
The only way to get around this issue for now is to use:
vsim work.top -L ./work -L test

What is occurring from what I can tell is that Modelsim treats the work library as special, and in this way creates all sorts of buggy behavior. Another recommendation from Model Tech is to not use the work library and therefore you would have a command like:
vsim mywork.top -L mywork -L test
which would work fine. This is a very untenable solution for all the obvious reasons, so for now I'm sticking with the first workaround.

Error from Modelsim:

# vsim -L test work.top
# Loading work.top
# Loading test.test_mod
# ** Error: (vsim-3033) test_module.v(2): Instantiation of 'work_mod' failed. The design unit was not found.
# Region: /top/test_mod_inst
# Searched libraries:
# C:\tmp\modelsim_test\test (<-This is actually Modelsim mixing up the work library)
# C:\tmp\modelsim_test\test
# Error loading design

Example files:
work.v:

module work();
_library library_inst();
endmodule
module work_sub();
endmodule

library.v:
module _library();
work_sub work_sub_inst();
endmodule

compile.do:
vlib work
vlog work.v
vlib library
vlog -work library library.v
vsim -L library work

#vsim -L ./work -L library work - this will compile and run as noted above.

Friday, July 2, 2010

Simulating 2 Lattice PCIe cores...

I start off every post with some vocal exclamation, so gah!

(All this is from memory, so forgive any unintentional mistakes.)

Lattice IP Express allows you to create PCIe cores. For compilation, you are given 2 NGO files, xxx.ngo and xxx_pcs.ngo. For simulation you are given an obfuscated behavioral model of PCIe and the sources for the pcs NGO. (Why do they compile those sources to xxx_pcs.ngo? I guess it's to save the user from complications, and to save them from using the define files discussed next.) The simulation files are all controlled through files with various `defines in them. These `defines control the compilation of both the beh and pcs files. This is a major problem in Modelsim!

First off, you run into the issue that you can't have 2 cores with different simulation `defines running in the same design. For example I have a DUT (Device Under Test) with Wishbone and a BFM (Bus Functional Model) without it. This can't work b/c the same module names are used in both instances, even when you gave the cores different top level names during IP Express creation!

Next issue is that you can try to change the module names, but the behavioral model has a large amount of tiny modules with obfuscated names and with no easy way to go over the file and rename them all. You can do it, but it would take a nice sed script or some other method, and it would be annoying... The other modules of course could be renamed much easier. Next problem is that the defines are of course the same names, so you'd have to rename those, or compile the files from a top level .v file so the defines stay local at least with the -sv switch. All sorts of headaches involved.

Update!!:
Create separate libraries for the simulation core and the DUT core. Use Modelsim's trick to get vsim to work properly... What is that trick you ask? By setting the first search library as work in the vsim command, Modelsim will perform a search for modules beginning with the library that the module is instantiated inside of.
This won't work:
vsim top_tb -L pcie_sim_work -L pcie_endpoint_work

This will work:
vsim top_tb -L work -L pcie_sim_work -L pcie_endpoint_work

(Note: Lattice requires pcsd_mti_work also... so add -L pcsd_mti_work after mapping the library)

Modelsim discusses this special case in their reference manual under "Handling sub-modules with common names":
"When you specify -L work first in the search library arguments you are directing
vsim to search for the instantiated module or UDP in the library that contains the module
that does the instantiation."

Thursday, June 10, 2010

verilog & parallel case for case statements

So I was coding Verilog and I had a little circular buffer bringing in a mux selection on a per clock basis. I wanted this mux selection value to be treated as one-hot in the case statement.

Quickly mashed up example...

reg [31:0] circ_buffer [3:0]; //8 copies of the selector which is some size (no bigger than 32 bits)

always @ (clk) begin
if(wr_a)
circ_buffer[wr_index] <= A;
else if(wr_b)
circ_buffer[wr_index] <= B;
if(wr_a || wr_b)
wr_index <= wr_index + 1;
end

always @ (clk) begin
case (circ_buffer[rd_index])
A: ...
B: ...
endcase
end

So I want A and B to be defined as one-hot (ie A is 01 and B is 10). And then I want its interpretation to be parallel. This would happen if circ_buffer was a clearly defined state machine, but as it is, it's not. I just read up on parallel case and how it works, and I've seen lots of information... albeit bad information for those who like the most intense and clear control of what they are doing. An example is the document by Sunburst Design.

Here's what I get from most of what people have written. "parallel case" should never be given as a synthesis option b/c it will create RTL that will not behave like it will simulate. The 'proper' usage given is completely useless. Read the document by Sunburst Design and hopefully you'll understand my meaning.

Anyhow, parallel case is a very strong synthesis option that should be used carefully. I would probably advise against it simply b/c the same thing can be accomplished using carefully written if statements. For me, the solution is to simply swap the second part to:

UPDATE (July 25, 2010):
What I've written below is not correct for ASIC design. I've just recently learned that Synopsis treats the 'case' with 'parallel case' option in a special way. It basically instantiates a one-hot even if it could result in 2 sources driving a single wire. This can't happen in an FPGA as an FPGA will always resolve who drives what, but for ASIC design this isn't necessarily the case. To clarify - for ASIC design you may very well want to use the parallel case statement. Using the ifs as I show below would produce a resolved version using gates.
END UPDATE (July 25, 2010)

always @ (clk) begin
if(circ_buffer[rd_index][0]) ...
if(circ_buffer[rd_index][1]) ...
end

Yeah, it's a less pretty way, but it's the way you get the same simulation results as synthesis results. It's much smarter this way. But don't be fooled by the papers and forget that parallel case most definitely has a use, just one that's ill advised, or at the very least not capable of being simulated by any current tools that I know of.

I don't know what I'm gonna do yet, but perhaps leave a parallel case state machine with a check for valid states above it and blow up if now... That takes care of the simulation issue, right? Otherwise I'll do the if statements, one after another.

Saturday, May 22, 2010

vim plugins - seriously

I don't like indentation for Verilog (or VHDL), so I've decided to try and fix it. The best way to do that would be to understand how it works. I opened the ftplugin file verilog.vim and started reading. That's the why. Hopefully someone else will get something from the few useful gems I've gleaned.

DISCLAIMER: I do not know that I'm even understanding this correctly. I'm reading and gleaning as best as I can. It's strange code. Comments with corrections are appreciated.

s: (s colon) - script variables
a: (a colon) - argument variables
b: (b colon) - buffer variables
g: (g colon) - global variables
v: (v colon) - ... maybe it's the visual mode variables

=~ (equal tilda) - type match
: (colon) - type of dictionary or list
%( (percent open-parenthesis) - start of match that doesn't store in back-reference variables
%5c, %<5c, %>5c, %5l, %<5l, %>5l (percent number c), (percent number less-than c), (percent number greater-than c), (percent number l), (percent number less-than l), (percent number greater-than l) - search modifier to find at specific column (c) or line (l) with optional less-than or greater-than specified column or line.

Look at this guy's page, finally stumbled onto it:
http://briancarper.net/blog/vim-regexes-are-awesome
and this page:
http://www.adp-gmbh.ch/vim/searching.html
and this one too:
http://www.ibm.com/developerworks/linux/library/l-vim-script-1/index.html

Tuesday, April 27, 2010

Build gvim 7.2 x64 and create installer for Windows 7, Vista, XP

Update with new installer and changes for building 7.3:
http://ionipti.blogspot.com/2010/08/gvim-73-64-bit-x64-windows-7-vista-xp.html

I've been getting kinda tired of not having a decent installer for gvim 7.2 on my Vista x64 system. I have figured out all of these steps, and I'm sharing them with you. You can download the actual installer from:

http://nkcorner.com/gvim72.exe (64 bit only, includes all patches up to and including 7.2.411)

This version is built exactly as I've shown below. The printing works in Windows, and so do the context menus. It also installs to the Program Files directory as it should. This is only tested on Vista x64.

Here are the steps: (I'm sure they can be somewhat simplified and I'd be happy to hear about that.)


Create a folder called building, eg c:\building

Download these files:
ftp://ftp.vim.org/pub/vim/unix/vim-7.2.tar.bz2
ftp://ftp.vim.org/pub/vim/extra/vim-7.2-extra.tar.gz
ftp://ftp.vim.org/pub/vim/extra/vim-7.2-lang.tar.gz
Unzip them using 7-zip or alternative program.
Each of these archives contain a vim72 folder, extract them all into c:\building\vim72 folder.

Download these files, and extract them to c:\building\patches
ftp://ftp.vim.org/pub/vim/patches/7.2/7.2.001-100.gz
ftp://ftp.vim.org/pub/vim/patches/7.2/7.2.101-200.gz
ftp://ftp.vim.org/pub/vim/patches/7.2/7.2.201-300.gz
ftp://ftp.vim.org/pub/vim/patches/7.2/7.2.301-400.gz

Download these files into c:\building\patches
ftp://ftp.vim.org/pub/vim/patches/7.2/7.2.401
ftp://ftp.vim.org/pub/vim/patches/7.2/7.2.402
ftp://ftp.vim.org/pub/vim/patches/7.2/7.2.403
ftp://ftp.vim.org/pub/vim/patches/7.2/7.2.404
ftp://ftp.vim.org/pub/vim/patches/7.2/7.2.405
ftp://ftp.vim.org/pub/vim/patches/7.2/7.2.406
ftp://ftp.vim.org/pub/vim/patches/7.2/7.2.407
ftp://ftp.vim.org/pub/vim/patches/7.2/7.2.408
ftp://ftp.vim.org/pub/vim/patches/7.2/7.2.409
ftp://ftp.vim.org/pub/vim/patches/7.2/7.2.410
ftp://ftp.vim.org/pub/vim/patches/7.2/7.2.411

Download and install these programs:
http://cdnetworks-us-2.dl.sourceforge.net/project/gnuwin32/sed/4.2-1/sed-4.2-1-setup.exe
http://cdnetworks-us-2.dl.sourceforge.net/project/nsis/NSIS%202/2.46/nsis-2.46-setup.exe
http://hivelocity.dl.sourceforge.net/project/gnuwin32/patch/2.5.9-7/patch-2.5.9-7-setup.exe
Optionally install make, although we will be bypassing the make with a manual command due to incorrect syntax in the Makefile when running on Windows.
http://cdnetworks-us-2.dl.sourceforge.net/project/gnuwin32/make/3.81/make-3.81.exe

Add "C:\Program Files (x86)\GnuWin32\bin\" to your path variable and reopen any command prompts.

Download and extract diff.exe from:
http://hivelocity.dl.sourceforge.net/project/unxutils/unxutils/current/UnxUtils.zip
Copy diff.exe to c:\building\

Download and install Windows SDK for AMD64:
http://download.microsoft.com/download/2/E/9/2E911956-F90F-4BFB-8231-E292A7B6F287/GRMSDKX_EN_DVD.iso
If this link doesn't work, then go to
http://www.microsoft.com/downloads/details.aspx?FamilyID=71deb800-c591-4f97-a900-bea146e4fae1&displaylang=en
and download the GRMSDKX_EN_DVD.iso (which is the AMD64 version)

Download this package and copy upx.exe to c:\building\vim72\nsis
http://upx.sourceforge.net/download/upx304w.zip

Open a command prompt and run
C:\Windows\System32\cmd.exe /E:ON /V:ON /T:0E /K "C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\SetEnv.cmd" /release
Use this command prompt for building as it is now set to 64 bit release.

Install patches by changing directory to c:\building\vim72 and running these commands in this order:
patch --binary -p0 < ..\patches\7.2.001-100
patch --binary -p0 < ..\patches\7.2.101-200
patch --binary -p0 < ..\patches\7.2.201-300
patch --binary -p0 < ..\patches\7.2.301-400
patch --binary -p0 < ..\patches\7.2.401
patch --binary -p0 < ..\patches\7.2.402
patch --binary -p0 < ..\patches\7.2.403
patch --binary -p0 < ..\patches\7.2.404
patch --binary -p0 < ..\patches\7.2.405
patch --binary -p0 < ..\patches\7.2.406
patch --binary -p0 < ..\patches\7.2.407
patch --binary -p0 < ..\patches\7.2.408
patch --binary -p0 < ..\patches\7.2.409
patch --binary -p0 < ..\patches\7.2.410
patch --binary -p0 < ..\patches\7.2.411

Change directory to c:\building\vim72\src, and build using this command:
nmake -f Make_mvc.mak OLE=yes
and
nmake -f Make_mvc.mak OLE=yes GUI=yes
(First command produces vim.exe and second one produces gvim.exe)

Change directory to c:\building\vim72\runtime\doc and run
sed -e "s/[ \t]*\*[-a-zA-Z0-9.]*\*//g" -e "s/vim:tw=78://" uganda.txt | uniq >uganda.nsis.txt
This is the line that should be run from the Makefile in this directory, but Windows make.exe has trouble with it.

Change directory to c:\building\vim72\nsis and open gvmi.nsi in a text editor (preferably not notepad or wordpad...)
At line 22 change (comment out)
!define HAVE_NLS
to
#!define HAVE_NLS
(I don't have a 64-bit libintl.dll)

Replace all instances of PROGRAMFILES with PROGRAMFILES64
(Forces the default installation directory to be the Program Files directory instead of Program Files (x86).)

At line 248 change
   File /oname=vim.exe ${VIMSRC}\vimd32.exe
to
   File /oname=vim.exe ${VIMSRC}\vimw32.exe
(The check for WINNT isn't working on my Vista x64 system... so I force it)

Copy all files and directory from c:\building\vim72\runtime to c:\building\vim72

Rename these files:
c:\building\vim72\src\gvim.exe -> c:\building\vim72\src\gvim_ole.exe
c:\building\vim72\src\vim.exe -> c:\building\vim72\src\vimw32.exe
c:\building\vim72\src\install.exe -> c:\building\vim72\src\installw32.exe
c:\building\vim72\src\uninstal.exe -> c:\building\vim72\src\uninstalw32.exe

Copy and rename this file:
c:\building\vim72\src\xxd\xxd.exe -> c:\building\vim72\src\xxdw32.exe

Change directory to c:\building\vim72\nsis and run:
"c:\Program Files (x86)\NSIS\makensis.exe" gvim.nsi


Enjoy!
Nachum Kanovsky
http://nkcornerconsulting.com
FPGA & Embedded Software Expert

Friday, April 23, 2010

Modelsim, scripts getting locked?

So I was working a lot with Modelsim yesterday simulating DDR2 cores, but I kept having to change the script. But Modelsim wouldn't let me!!! So here's the key, when Modelsim is running a script and you interrupt it while it's running, it may show:
VSIM(paused)
and then you're just screwed! OK OK, type 'abort' and hit enter. This will finally end the script and allow you to modify your script without closing down Modelsim. Shockingly 'quit -sim' doesn't work, nor are there any menu options that help.

Perhaps this'll save someone else problems.

Lattice DDR2 cores - read_data_valid doesn't come up...?

So as is usual, I'm suspicious of crummy simulation models and that's of course the reason why Lattice's ECP3 DDR2 (6.7 and 7.0 beta) cores don't give read_data_valid during simulation... They output the data, but not the read_data_valid signal.

After 2 hours of debugging, I found that it was all in the module hookup. read_tap_delay! The signal that they don't bother documenting, or explaining was causing the problem. I accidentally hooked up read_tap_delay to 2'b0 instead of 6'b0 (shame on me). This killed it. I guess I learn 2 things here, first that lack of documentation doesn't indicate lack of importance! and second that 2'b0 doesn't translate in all situations to fill the port with zeroes!

On the other hand, I finally took the plunge and hooked up Micron's DDR2 model. I have to say that it was the easiest model ever to hook up! Just define sg3 and x16 and voila, it's done. OK OK, there were two small snafus...

Lattice provides their cores with a simulation model, if you try to swap out their DDR2 model (also Micron's), then there is at least one problem. They have a file where they define x8 for all cores. I don't know why, I'd guess it's got something to do with Micron's old model. Anyhow for those of you swapping models for simulation, be aware of that. It will explain why Micron's model suddenly insists on a data bus of incorrect size even though you defined everything properly!

Lattice doesn't include negative differential ports in their top level definition, so if you have a clk_p and clk_n, all that appears in the top level netlist is clk_p, and the lpf file (constraints file) indicates the differential nature and automatically connects the differential pair. (Yes, pairs are fixed in the ECP3 and many other Lattice FPGAs.)

So now I have a DDR2 model requiring clk_n and dqs_n. clk_n is simple, just:
wire clk_n;
assign clk_n = ~clk_p;
easy shmeezy

On the other hand, dqs_n is an experience in learning. To save you the time that you've probably already spent trying to figure this out, here it is:
wire dqs_n;
assign dqs_n = (dqs_p === 1'bz) ? 1'bz : ~dqs_p;

Yes yes, the 3 equal signs are necessary. Shockingly a part of the language I'd never needed to use before, now comes in handy.

Live to learn another day,