Showing posts with label hassle. Show all posts
Showing posts with label hassle. Show all posts

Friday, July 11, 2008

Fixed-Point Arithmetic with Verilog

I'm doing a bit of hardware RTL at the minute, which is a change from my usual testbench code. I'm trying to implement a datapath using fixed-point arithmetic and I'm finding that verilog is not helping me as much as I thought it would. And I've come to realise something...

Fixed-point arithmetic in verilog is broken. And that makes me sad.

Representation

First things first. Let's try to represent a fixed-point number in verilog. What about a vector of bits? Cool, let's say we'll represent our fixed point numbers in N bits:

We'll allow M bits for the integer part and F for the fractional (and, of course, M+F = N).
reg [M+F-1:0] my_number;
OK, so far so good. This is not too self-documenting though - how can you tell that this is a fixed-point number? And where is its binary point? Even worse, you can't tell verilog that the number is supposed to be fixed-point - it doesn't even have a fixed-point 'type'.

Another way is to signal a fixed-point number by having the fractional bits have negative indexes:
reg [M-1:-F] my_number;
For example, an M=1 and F=4 number's vector would be indexed [0:-4]. In this case, we can decree that the binary point is always between indexes 0 and -1, and that any vectors declared with negative indices is a floating point number. This also has the nice property that the value of each bit in the vector is 2index, just like the integer representation.

It's just bookkeeping, though. Nomatter how we spin it, we can't really get verilog to help us out with our fixed-point numbers. For example, say we wanted to add a 1.4 number to a 2.5 - (we'd expect a 3.5 result...):
reg [0:-4] a;
reg [1:-5] b;
reg [3:-5] c;

always @(*) begin
// c = a + b; // this won't line up the binary points for us
c = {a, 1'b0} + b; // we have to make sure that the binary points line up ourselves
end

In this case, Verilog won't line up the binary points for us, it'll line the vectors up LSB to LSB. We're left to make sure that we pad whichever vector to line up the binary points.

Display

Since we can't tell verilog we're working with fixed-point numbers, they're not going to be displayed correctly. Any $displays in the testbench are going to display integers. "But wait!", I hear you say - sure couldn't you just write a function to properly display your fixed-point numbers? Not easily. Functions can't be parameterised (as fair as I'm aware), so you'll have to write conversion functions for each different size of fixed-point number to be displayed. The reason is because slices of vectors must have constant expressions: you can writemy_number[-1:F] if F is a parameter, but not if F is a variable.

In a waveform viewer, our fixed-point numbers are going to be displayed as integers as well. Unless we write expressions (in SimVision, anyway) to convert them.

So, What Now?

To recap, you can't easily work with fixed-point numbers in verilog. Verilog can't help with lining up the binary point for arithmetic, and fixed-point numbers are display incorrectly both in $displays and in waveform viewers.

Should verilog support fixed-point arithmetic? Could you do something with structs and operator overloading in SystemVerilog? (Maybe not for synthesis). It turns out that I don't have solutions or recommendations for any of this, so this was just a rant. Sorry about that...

All this does mean that a lot of the high-level datapath design must be done in Matlab or whatever. I hope Matlab has fixed-point libraries...



An Aside: Text Macros

Why do none of my simulators happily accept the following?

`define two_lsbs(a) a[1:0]
module mess();
reg [3:0] some_vector;
initial begin
$display( "%b", `two_lsbs(some_vector) ); // OK
$display( "%b", `two_lsbs(5) ); // broken
end
endmodule

When you go to use this, simulators complain about unmatched parenthesis when a numeric literal is supplied. Why?


.

Tuesday, July 17, 2007

Linux: Codecs, Proprietary Drivers & Hassle

I'm currently playing around with linux distros trying to find one that suites me. I've a collection of coverdisks from linux mags, and I'm to-ing and fro-ing, installing the various flavours on my new computer. But I'm finding it *very* frustrating.

Vista

First of all, the box came with Vista pre-installed. And whatever else can be said about micros~1 - Vista looks great! But I like my command line, so I reduced the Vista partition; created a few new ones and installed Ubuntu 7.04.

Ubuntu vs Media

My first impressions was that Ubuntu looks fairly ugly - or maybe 'old' is a better word - compared to Vista. Ubuntu catches up with the 3D desktop effects, and after installing NVIDIA's proprietary drivers from the "Restricted Drivers" tool, everything was running smoothly.

That was until I tried to play MP3's and the video tutorials from the guitar mag coverdisks I've lying around. Unsucessfully - although in fairness Vista doesn't play MPEG4's or MOVs out of the box either. I've no internet connection at home, so I can't use the automatic download tools to fetch the codecs. Hunting around on the net gave me no clues on what packages to download - and even if I fire up Synaptic and ask it to write a download script I've still no idea what to ask it to download.

LinuxMint vs Drivers

Then I heard of LinuxMint with it's bundled codecs. So I ordered it from On-Disk and was pleased to see it arrive after only 4 days or so. I much prefer the colour scheme, but again, things like the (IMHO) very poor icons make it look a bit rusty. The mintMenu is fairly cool and friendlier that Ubuntu's two-panel approach. But LinuxMint doesn't come with the *&^%£€<¹!¡ NVIDIA drivers!!


I'm going to have to stop being such a tight-arse and get my home computer wired up to the web. Or wait until NVIDIA open-source their drivers...