2
\$\begingroup\$

I want to create an assignment which takes care of pull-ups from a port pin. I wrote the following:

module test5;

reg value;
reg output_enable;
reg pullup_enable;

wire pullup_helper;
wire value_helper;
wire outp;


assign (highz0, pull1 ) pullup_helper = pullup_enable;
assign                   value_helper = output_enable ? value : 1'bz;
assign                           outp = value_helper  + pullup_helper;


always @(pullup_helper) $display ( "pullup_helper %b", pullup_helper );
always @(value_helper) $display ( "value_helper %b", value_helper );
always @(outp) $display ( "outp %b", outp );

initial begin
    $display ("Start");
    pullup_enable = 0;
    output_enable = 0;
    value = 0;
    #1
    $display ("1");
    output_enable = 1;
    #1
    $display ("2");
    value = 1;
    #1
    $display ("3");
    value = 0;
    #10
    $display("End");
end


endmodule

I got the output:

Start
pullup_helper z
value_helper z
1
value_helper 0
2
value_helper 1
3
value_helper 0
End

Q: Why does outp never change?

EDIT: Because the full answer is related to some comments on the given answers I will summarize the results:

As with support from Greg the answer to the problem is in two steps:

The default installation on Fedora 22 is Icarus 0.9.6. This version is buggy. As Greg tested also version 0.9.7 has the same bug. I installed the latest released version v10 (changed version conventions?)

The second part is simply let drive to assign statements into one wire.

assign (pull1,pull0)  bus = pullup_en ? 1'b1 : 1'bz;
assign                bus = output_en ? value : 1'bz;

With Icarus Verilog V10 it works as expected.

\$\endgroup\$
  • \$\begingroup\$ I get a compile error with 2 simulators. I think you need to change z to 1'bz. \$\endgroup\$ – toolic Oct 22 '15 at 17:43
  • \$\begingroup\$ What do you expect outp to be at what times? \$\endgroup\$ – toolic Oct 22 '15 at 17:47
  • \$\begingroup\$ I expect by setting output_enable that outp becomes the state of value but I always get 'x' as undefined. I can't get any kind of wire to work which can held the value of "low", "high" and "pullup" and no idea how to deal with that. I believe that my idea of a "wire" is totally wrong. It looks that it is simply impossible to drive a wire from multiple assignments. I simply can't catch the idea how the typical way in verilog is to deal with "wires". I think in the electronic way where multiple ports of a controller can added to a network. I simply have no idea how can I write that in verilog. \$\endgroup\$ – Klaus Oct 23 '15 at 15:03
5
\$\begingroup\$

Verilog strengths can be a bit of complicated process understand. To get the full breath of understanding read: IEEE Std 1800-2012 § 10.3, 21.2.1.5, and 28.10 through 28.16.

To print the strength of a bit in a display message, use %v instead of %b. (§ 21.2.1.5)

Verilog mostly works in the digital logic space. Verilog strength only comes into play when two or more assignments continuously drive the same net as a from of conflict resolution. The strength value does not propagate through assignment statements. The strength value can be passed through the verilog switch primitives: nmos, pmos, tranif1, tranif0, cmos, tran, plus resistive switch primitives (which weakens the strengths on pass-through). For verilog primitives switches refer to IEEE Std 1800-2012 § 28.7 through 28.9.

assign (pull1,pull0)  bus = pullup_en ? 1'b1 : 1'bz;
assign                bus = output_en ? value : 1'bz;

assign                out = bus;
assign (weak1,weak0) outw = bus;
cmos inst_name (outs, bus, 1'b1, 1'b0);

// pullup_en output_en  |  out(%v)         outw(%v)        outs(%v)
// ---------------------+----------------------------------------------
//       0         0    |  1'bx(StX)       1'bx(WeX)       1'bz(HiZ)
//       0         1    |  value(St1,St0)  value(We1/We0)  value(St1/St0)
//       1         0    |  1'b1(St1)       1'b1(We1)       1'b1(Pu1)
//       1         1    |  value(St1,St0)  value(We1/We0)  value(St1/St0)

Pullup/pulldown logic from a standard cells libraries provide by your vendor can be used for synthesis. Some synthesizers have pragmas to indicate a pullup/pulldown on a bus. Out side of that, verilog strength is typically not synthesizable. FPGAs have limited bidirectional bus support; if any. ASICs typically try to minimize the size and use of a bidirectional buses.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I still can't understand what is going on. If I simply assign (pull0,pull1) bus = pullup_en ? 1'b1 : 1'bz;and let pullup_en= 1; the result is bus 1 St1 displayed with (%b %v) . Why the strength results in strong and not in pull up? \$\endgroup\$ – Klaus Oct 23 '15 at 7:55
  • \$\begingroup\$ What is the value of output_en? Working example on edaplayground \$\endgroup\$ – Greg Oct 23 '15 at 15:23
  • \$\begingroup\$ Thanks for your example. The problem is the line 'pullup_en:1 output_en:1 value:0 :: bus:x(StX) out:x(StX) outw:x(WeX) outs:x(StX)'. My expected result is simply that the output_en anables the driver and "overwrite" the pullup with 0 as in the real world. The result should be simply "0" and not "x". \$\endgroup\$ – Klaus Oct 23 '15 at 16:15
  • \$\begingroup\$ I changed both assign lines in your code with the following ones: rnmos r3( bus, 1'b1, pullup_en ); nmos p4( bus, value, output_en ); This seems to work. \$\endgroup\$ – Klaus Oct 23 '15 at 16:23
  • \$\begingroup\$ Curious, what simulator are your running? \$\endgroup\$ – Greg Oct 23 '15 at 17:16
2
\$\begingroup\$

When I view the waveforms, I see outp is always unknown (x). outp never changes because pullup_helper is always z. pullup_helper is always z because pullup_enable is always 0. You specified highz0 for when pullup_enable is 0 in your assign statement. Refer to IEEE Std 1800-2012, section 10.3.4 "Continuous assignment strengths".

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ My expectation was that setting output_enable result in value_helper becomes the value of value. And then I thought the strength of value_helper is higher and outp is set correct. But outp is never set. I still can not understand what the problem here is. \$\endgroup\$ – Klaus Oct 23 '15 at 6:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.