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
circ_buffer[wr_index] <= A;
else if(wr_b)
circ_buffer[wr_index] <= B;
if(wr_a || wr_b)
wr_index <= wr_index + 1;

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

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]) ...

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.