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
a&b={0&0,0&1,0&1,0&0,1&0,0&0,0&1,1&1}=00000001
.a|b={0|0,0|1,0|1,0|0,1|0,0|0,0|1,1|1}=01101011
.a^b={0^0,0^1,0^1,0^0,1^0,0^0,0^1,1^1}=01101010
.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.
Create file named src/bitwise_operations.v
and declare a module named bitwise_operations
. The module should
have these I/O ports:
clk
a
and b
with seven bits
eachop
(short for
“operation”) with two bitsreg
q
with seven
bitsIn 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:
op==0
:
Bitwise AND q <= a&b
op==1
:
Bitwise OR q <= a|b
op==2
:
Bitwise XOR q <= a^b
op==3
:
Bitwise NOR q <=~(a|b)
Next, in testbench.v
, place
an instance of the bitwise_operations
module. Modify the
testbench
as follows:
reg
named
op
, initialized as 0.reg
signals
a
and b
, initialized as 0.wire
signal
q
always
block
cycling through all values of op
: 00,01,11,10,00,… and repeat$write
and
$fwrite
lines to report the clock number, a
, b
, op
and q
. Optionally: use
if/else
conditions to report the operation name (“AND”, “OR”, etc) instead of
the numerical value of op
.When finished, run make
to
simulate your module. Carefully inspect the output and verify that the
correct operations are performed for each case.
Now edit build.tcl
and change
the following:
read_xdc
line: change to
bitwise_operations.xdc
synth_design
line: change
top_module
to bitwise_operations
write_bitstream
line: change
to bitwise_operations.bit
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[get_ports clk]
#set_property PACKAGE_PIN W5 [get_ports clk]
#set_property IOSTANDARD LVCMOS33 -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk] #create_clock
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:
PACKAGE_PIN
to indicate
which FPGA pin is connected to the Basys3 clock signalIOSTANDARD
to LVCMOS33
, 3.3V CMOS-compatible logic
signals. Since the FPGA chip can support several different voltages and
signal configurations, it needs to be told which standard is used on the
Basys3 board.clock
, which is critical for proper
routing and timing analysis.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[get_ports {sw[0]}]
#set_property PACKAGE_PIN V17 [get_ports {sw[0]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {sw[1]}]
#set_property PACKAGE_PIN V16 [get_ports {sw[1]}]
#set_property IOSTANDARD LVCMOS33 [get_ports {sw[2]}]
#set_property PACKAGE_PIN W16 [get_ports {sw[2]}] #set_property IOSTANDARD LVCMOS33
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:
sw[0]
through sw[6]
to a[0]
through a[6]
(respectively)sw[7]
through sw[13]
to b[0]
through b[6]
(respectively)sw[14]
and sw[15]
to op[1]
and op[0]
(respectively)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.
When finished, run make implement
to build the design.
Program it onto the Basys3 board. When programmed, you should test the
following:
b
a
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.