Bit-Wise Binary Operators

Bit-Wise Operators in Verilog

Verilog supports several operations that work bit-by-bit across a pair of vectors. Given two vectors a and b with the same bit width, we have these operations:

Operator Operation
a&b Bitwise AND
a|b Bitwise OR
a^b Bitwise XOR
~(a&b) Bitwise NAND
~(a|b) Bitwise NOR
~(a^b) Bitwise XNOR

A first example is given in src/testbench.v. Open the file and study its contents. Run make to simulate the demo cases. The first few lines look like this:

clk:            0   a:  00000000    b:  00000000    a&b: 00000000   a|b: 00000000   a^b: 00000000
clk:            1   a:  00100100    b:  10000001    a&b: 00000000   a|b: 10100101   a^b: 10100101
clk:            2   a:  00001001    b:  01100011    a&b: 00000001   a|b: 01101011   a^b: 01101010

Every bitwise operation returns a vector. For the last line, we have a=00001001 and b=01100011, and they share a non-zero value only in the last bit position. Therefore the bitwise results are

As an exercise, predict the results for NAND, NOR, and XNOR operations. Modify testbench.v to test these operations, and run the simulation to verify your calculations.

Assigned Tasks

Create a Module

Create file named src/bitwise_operations.v and declare a module named bitwise_operations. The module should have these I/O ports:

In the module definition, make a clocked always block:

always @(posedge clk) begin
   //...your code here...//
end

In the always block, use if/else statements to implement these cases:

Simulate the Module

Next, in testbench.v, place an instance of the bitwise_operations module. Modify the testbench as follows:

When finished, run make to simulate your module. Carefully inspect the output and verify that the correct operations are performed for each case.

Implement the Module

Now edit build.tcl and change the following:

Next open bitwise_operations.xdc. You will see a lot of commented lines copied from Basys3_Master.xdc. First, note the clk lines:

## Clock signal
#set_property PACKAGE_PIN W5 [get_ports clk]                            
    #set_property IOSTANDARD LVCMOS33 [get_ports clk]
    #create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]

Since your design uses a clock, uncomment the lines that reference the clk port and start with set_property or create_clock. These properties are necessary for the following:

In the Basys3 XDC template, the first line pertaining to a given port is not indented, and subsequent lines pertaining to the same port are indented.

Next, examine the switch lines. The first few look like this:

## Switches
#set_property PACKAGE_PIN V17 [get_ports {sw[0]}]                   
    #set_property IOSTANDARD LVCMOS33 [get_ports {sw[0]}]
#set_property PACKAGE_PIN V16 [get_ports {sw[1]}]                   
    #set_property IOSTANDARD LVCMOS33 [get_ports {sw[1]}]
#set_property PACKAGE_PIN W16 [get_ports {sw[2]}]                   
    #set_property IOSTANDARD LVCMOS33 [get_ports {sw[2]}]

Uncomment all the set_property lines related to the switches. Next, edit each line replacing sw[] with a port name from your module. You should make the following substitutions:

Next move down to the LEDs. Uncomment the set_property lines and change led[0] through led[6] to q[0] through q[6], respectively.

Program the Module

When finished, run make implement to build the design. Program it onto the Basys3 board. When programmed, you should test the following:

Demonstrate one working condition for each op value. Photograph it and place the photo in your working directory, with filenames case1, case2, and so on (with an appropriate graphics file extention).

When finished, turn in your work using git:

git add src/* test_result.txt case* *.rpt *.bit
git commit . -m "Complete."
git push origin main

Then indicate on Canvas that your work is complete.