Showing posts with label asic design. Show all posts
Showing posts with label asic design. Show all posts

Thursday, July 16, 2009

I Program Computers

A new housemate moved in recently. We were getting to know each other - talking about our backgrounds, our favourite football teams and all the usual getting-to-know-you good stuff. He'd half remembered from our initial meeting that I did something vaguely technical for a living, and asked did I "program computers or what?".
"I'm an electronics engineer. I help to design the digital parts of chips", I NACKed.
"Ah", says he, "so how do you do that then?"
"Emm", I was caught out. "By ah, programming computers...", I sheepishly admitted.
It brings up a topic close to my heart - are Electronic Engineers (EEs) learning as much as they should from Computer Science and Software Engineering?

Digital Design is Programming


Software Engineering is important to EEs because digital designers, and especially functional verification engineers, are in essence specialised software engineers. For digital designers, our thoughts are necessarily grounded in hardware but those thoughts are expressed in software. The special requirements of concurrency and timing for describing hardware requires dedicated Hardware Description Languages (HDLs), but these are programming languages none the less - computers can be made to execute them.

If computers can run our HDLs as programs, then its natural as engineers to want to check the arse off our designs before they make it to manufacturing. We want to make sure that we've expressed our ideas correctly. We're obsessive about checking so we put our functional verification engineer hats on and we run simulations, and now we're suddenly programming for real. Our testbenches and testcases are now software proper. It no longer matters if the code we write is translatable into flip-flops and NOR gates, so long as the input signals are wiggled in the correct way and that the outputs wiggle as we'd expect. And even better (maybe?), we're allowed to abstract now.

I'm of the opinion that a lot of Electronic Engineers don't read enough about software development as they should. Software seems to be, or at least seemed to be, a minor detail that we could get the co-op to sort out. And as far as my own university course was concerned - why did I have to independently discover the joys of source control? I've read a few books like "Code Complete", "Emergent Design" and "Pragmatic Programmer" and wished with every line I read that an equivalent existed for us digital designers. Maybe there is, it's just that programming related resources are easier to find on the web.

Since we're all programmers now, we should learn how to program. From what I read, real software programmers seem to have a small niggling worry that they're somehow inferior to 'real' engineers. That's backwards though - us 'real' engineers need to start befriending real programmers and learn from them. We're so dependent on computers that we need to learn how to program for real. We need source control, we need unit tests, we need to learn to refactor and we need to learn to spot code smells. We need to write scripts to generate RTL, scripts to launch batches of sims over the network and create Makefiles to automate synthesis. We're software engineers and we haven't the slightest clue we are - at least, we've no ideal we will be when we leave college.

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?


.