Active Low LED and Active Low Switch behavior on FPGA counter-intuitive

I was following a tutorial to get started with Libero SoC with MicroSemi SmartFusion FPGA. I coded a small LED toggle module

module led_toggle( i_sw , o_led );
input   wire [1:0]  i_sw;
output  wire [4:0]  o_led;

assign  o_led[0] = i_sw[0];
assign  o_led[1] = i_sw[1];
assign  o_led[2] = i_sw[0] &  i_sw[1];
assign  o_led[3] = i_sw[0] |  i_sw[1];
assign  o_led[4] = i_sw[0] ^  i_sw[1];
endmodule


Pin mapping

i_sw[0] to on-board switch SW0
i_sw[1] to on-board switch SW1
o_led[7:0] to on-board LEDs D[4:0]


After synthesis, place and rout, I flash the FPGA with the bitstream.

On pressing SW0, led D0 lights up and on pressing SW1, led D1 lights up. This is as expected.

However, it seems leds D2, D3 and D4 donot light up according to the AND, OR and EXOR combination of SW0 and SW1 as per my Verilog design. In fact working backwards from the behavior on-board, the logical expressions for them are

LED D2 = Sw0 | SW1 instead of designed (SW0 & SW1)
LED D3 = SW0 & SW1 instead of designed (SW0 | SW1)
LED D4 = ~(SW0 ^ SW1) instead of designed (SW0 | SW1)


Now in the same tutorial it is mentioned that

Keep in mind the switches and LEDs are active low. That is, the switch creates zero when pushed and the led illuminates when a logical 0 is applied.

So an active low switch with an active low LED is buffer like behavior i.e. LED ON when switch pressed and LED OFF when switch de-pressed. However it doesn't explain the unexpected behavior with leds D2, D3 and D4.

So what am I missing here ?

(note: I am using the verilog operators in this post, but most reference materials you find will probably use other notation)

So what am I missing here ?

For AND and OR we have De-morgans theorem

A | B === ~((~A)&(~B))
A & B === ~((~A)|(~B))


For XOR the following is true (not sure if this identity has a name)

A ^ B === (~A)^(~B)


Your buttons and LEDs are active low. In other words their behaviour is inverted from what one might naively expect. The button produces a 1 when not pressed and a 0 when pressed. Similarly the LED lights up when given a 0 and does not light when given a 1.

  SW0      SW1    i_sw[0] i_sw[1] o_led[2] o_led[3] o_led[4] D2  D3  D4
release  release    1       1        1        1        0     Off Off On
release   press     1       0        0        1        1     On  Off Off
press   release    0       1        0        1        1     On  Off Off
press    press     0       0        0        0        0     On  On  On

• I mean I also did the same but I was not sure" Complement literals as switches are active low and complement the expression as LEDs are active low. But how to get intuitive behavior as per my Verilog design: in my pin constraints, should I add pull ups to LEDs and switches ? – nurabha Aug 25 '20 at 23:48
• Probablly the easiest way is to add inversions in the input and output lines, verilog syntheis tools optimise agressively so this shouldn't cost you anything in terms of performance. – Peter Green Aug 25 '20 at 23:51
• While this is really small example, but If I have to port the design to another board, I will have to modify the design again. Can I not change the default active low to active high using pin constraints ? If yes, how ? – nurabha Aug 25 '20 at 23:55
• I have certainly never seen an inversion function in the pin mapping, though I'm not familiar with the specific toolchain you are using. As for dealing with multiple boards (which are likely to have other differences than just the logic polarity of signals) I see two main approaches, one is to put most of your logic in submodules and to have a different top-level module for each board. The other is to set preprocessor defines in the project file and then ifdef on them in the top-level verilog module. – Peter Green Aug 26 '20 at 0:00
• Ok. Got it. thanks – nurabha Aug 26 '20 at 0:15