0

How do I convert a tristate bus to 2-state logic for synthesis?

I've made a little test

module test1( inout tristate, output flattened);
    assign flattened = tristate ? 1 : 0;
endmodule

module test2( inout tristate, output reg flattened);
    always @(tristate) begin
        case(tristate)
            0:          flattened = 0;
            default: flattened = 1;
        endcase
    end
endmodule

`timescale 1ns / 1ps

module test_tb;
    reg tristateEnable;
    reg tristateValue;
    wire tristate = tristateEnable ? tristateValue : 1'bz;
    wire flattened1, flattened2;

    test1 uut1(tristate, flattened1);
    test2 uut2(tristate, flattened2);

    initial begin
        tristateValue = 1'b0;
        tristateEnable = 1;
        #10 tristateValue = 1'b1;
        #10 tristateEnable = 1'b0;
    end

endmodule

Simulating it I got that module test1 sets flattened to X and module test2 sets it to 1, the latter is what I wanted, but I haven't synthesized it yet. Is there a better / standard way of doing this?

EML
  • 9,619
  • 6
  • 46
  • 78
jabozzo
  • 591
  • 1
  • 6
  • 17
  • I simulated your tests using VCS, the results simulation results are identical for test1 and test2. Can you please elaborate your intent? I think test1 might be preferable, just a guess. – sharvil111 Dec 22 '15 at 04:42

1 Answers1

1

You've asked two questions: (1) what is the difference between the conditional operator and the case statement, and (2) how to handle tri-state values.

On the language question:

In short, Verilog has a 4-state data type, and the operators handle the 4 states differently.

  1. The case statement does a "4-state test", otherwise known as "case equality". The case expression (tristate in your example) is compared against 0, 1, x, and z. When it is z, the default branch is taken, so flattened is 1, as you found.
  2. The conditional ('ternary') operator also does a 4-state test, and finds tristate as z. It doesn't know what to do now, so it combines the two values you supplied (0 and 1) into a resulting x, which is what you see. Basically, it's trying to be smart. See table 5-21 in the 2005 LRM. Note that the if statement does not do a 4-state test.

Tristates: you're confused because your control signal (tristate) goes to z; it's the data signal (flattened) that should go to z. You don't 'flatten' tristates for synthesis; you normally model a pull-up or pull-down. This will be specific to your technology, but you may just need to instantiate a pullup or pulldown component. Your synthesiser may or may not do this automatically for you if you have code like

assign sig_o = (ena == 1'b1)? sig_i : 1'bz;

You need to read your synthesiser docs to be sure. Note that you should only ever use a conditional operator like this if ena is guaranteed to be 2-state (0/1).

EML
  • 9,619
  • 6
  • 46
  • 78
  • In my case, I am conecting to an external usb controller with a 32-bit bidirectional communication line. My simplified connection scheme would be: `module communications(inout data_bus, input out_stream, output in_stream, ..) .... assign data_bus = (en_data_bus) ? out_stream :1'bz; assign in_stream = databus; ... endmodule` It simulates without problems, but in_stream gets optimized out in synthesis. Since I cant use tristates internally in the fpga im trying to force in_stream to 2-state. – jabozzo Dec 22 '15 at 15:20
  • If it's being optimised out it has nothing to do with tristates - it's because you're not using it, so it's not necessary. It also looks like there may be some confusion in your in/out directions, and possibly your module connections. – EML Dec 22 '15 at 15:53
  • Yes, I'm aware of that. In my code it's actively using it so it may be a chained optimization thing. Anyway, the original question is answered, thank you! – jabozzo Dec 22 '15 at 18:57
  • @eml for point number 1, can we use casez to ignore all the `z` design? – rahulcodesinverilog Dec 27 '15 at 02:41
  • On using `casez` to ignore all `z`'s in design: you could, but it's not a good idea. See www.sunburst-design.com/papers/CummingsSNUG1999SJ_SynthMismatch.pdf, section 4.4. You can't leave floating nodes in your design anyway, so just make sure that everything is pulled up or down. For an input or an I/O, make sure that you instantiate a cell which has a pull up or down. – EML Dec 27 '15 at 10:53