-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlab3_q4.py
95 lines (82 loc) · 3.08 KB
/
lab3_q4.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# Our goal in this exercise is to implement a simplified 1-bit ALU
# that has 2 data inputs: {a, b}, 2 outputs: {r, cout},
# and compute one of the following 3 functions: r = a and b,
# r = a xnor b, and cout, r = a + b
import pyrtl
# Declare two 1-bit data inputs: a, b
a = pyrtl.Input(bitwidth=1, name='a')
b = pyrtl.Input(bitwidth=1, name='b')
# Declare two 1-bit outputs: r, cout
r = pyrtl.Output(bitwidth=1, name='r')
cout = pyrtl.Output(bitwidth=1, name='cout')
# Declare control inputs
op = pyrtl.Input(bitwidth=2, name='op')# < add your code here >
def half_adder(a, b):
"""
ha_carry_out, ha_sum = a + b
"""
ha_sum = a ^ b # < add your code here >
ha_carry_out = a & b# < add your code here >
return ha_sum, ha_carry_out
def alu (a, b, op):
"""
Implementation of the desired simplified ALU:
if op == 0: return a and b
else if op == 1: return a xnor b
else if op == 2" return a + b
"""
# Operation 0: a and b
op0 = a & b# < add your code here >
# Operation 1: a xnor b
op1 = ~ (a^b)# < add your code here >
# Operation 2: a + b
op2_s, op2_c = half_adder(a, b)
# Based on the given "op", return the proper signals as outputs
alu_r = pyrtl.WireVector(bitwidth=1)
alu_cout = pyrtl.WireVector(bitwidth=1)
# < add your code here >
with pyrtl.conditional_assignment:
with op == 0:
alu_r |= op0
alu_cout |= op2_c
with op == 1:
alu_r |= op1
alu_cout |= op2_c
with op == 2:
alu_r |= op2_s
alu_cout |= op2_c
return alu_r, alu_cout
# Call the above-defined "alu" function and connect its results to the block's output ports
temp_r, temp_cout = alu(a, b, op)
r <<= temp_r
cout <<= temp_cout
# Testbench
simvals = {
'a': "010101010101",
'b': "001100110011",
'op': "000011112222"
}
# Simulate and test your "alu" design
sim_trace = pyrtl.SimulationTrace()
sim = pyrtl.Simulation(tracer=sim_trace)
for cycle in range(12):
sim.step({
'a' : int(simvals['a'][cycle]),
'b' : int(simvals['b'][cycle]),
'op': int(simvals['op'][cycle])
})
sim_trace.render_trace()
# Verification of the simulated design -- cross comparison with a software model
for cycle in range(12):
if sim_trace.trace['op'][cycle] == 0:
python_r = sim_trace.trace['a'][cycle] & sim_trace.trace['b'][cycle]
elif sim_trace.trace['op'][cycle] == 1:
not_int = lambda x: 0 if( x == 1) else 1
python_r = not_int(sim_trace.trace['a'][cycle] ^ sim_trace.trace['b'][cycle])
elif sim_trace.trace['op'][cycle] == 2:
python_r = int("{0:02b}".format(sim_trace.trace['a'][cycle] + sim_trace.trace['b'][cycle])[1])
python_cout = int("{0:02b}".format(sim_trace.trace['a'][cycle] + sim_trace.trace['b'][cycle])[0])
if (python_r != sim_trace.trace['r'][cycle] or (python_cout != sim_trace.trace['cout'][cycle] and sim_trace.trace['op'][cycle] == 2)):
print('The design is broken! Time for debugging.')
exit(1)
print('The design passed the test! Congrats!')