-
Notifications
You must be signed in to change notification settings - Fork 0
/
hazardtest.v
210 lines (197 loc) · 11.6 KB
/
hazardtest.v
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
module hazardtest();
reg clk, reset;
reg branch_D; // branch control for instr in D
reg [4:0] rs_D, rt_D; // source/target reg of instr in D
reg [4:0] rs_E, rt_E; // source/target reg of instr in D
reg [4:0] writereg_E; // reg that data will be written to for instr in E
reg memtoreg_E; // low when non-LW for instr in E
reg regwrite_E; // low when SW/BEQ/J for instr in E
reg [4:0] writereg_M; // reg that data will be written to for instr in M
reg memtoreg_M; // low when non-LW for instr in M
reg regwrite_M; // low when SW/BEQ/J for instr in M
reg [4:0] writereg_W; // reg that data will be written to for instr in W
reg regwrite_W; // low when SW/BEQ/J for instr in W
reg stall_F_expected; // hold instr in PC reg
reg stall_D_expected; // hold instr in D reg
reg forwardA_D_expected; // select bits for srcA_D
reg forwardB_D_expected; // select bits for srcB_D
reg flush_E_expected; // clear instr in E reg
reg [1:0] forwardA_E_expected; // select bits for srcA_E
reg [1:0] forwardB_E_expected; // select bits for srcB_E
wire stall_F; // hold instr in PC reg
wire stall_D; // hold instr in D reg
wire forwardA_D; // select bits for srcA_D
wire forwardB_D; // select bits for srcB_D
wire flush_E; // clear instr in E reg
wire [1:0] forwardA_E; // select bits for srcA_E
wire [1:0] forwardB_E; // select bits for srcB_E
reg [31:0] vectornum, errors;
reg [49:0] testvectors[10000:0];
hazardunit example( branch_D, // input to be tested
rs_D, rt_D, // input to be tested
rs_E, rt_E, // input to be tested
writereg_E, // input to be tested
memtoreg_E, // input to be tested
regwrite_E, // input to be tested
writereg_M, // input to be tested
memtoreg_M, // input to be tested
regwrite_M, // input to be tested
writereg_W, // input to be tested
regwrite_W, // input to be tested
stall_F, // output to be compared
stall_D, // output to be compared
forwardA_D, forwardB_D, // output to be compared
flush_E, // output to be compared
forwardA_E, forwardB_E // output to be compared
);
always
begin
clk = 1;
#5;
clk = 0;
#5;
end
initial
begin
$readmemb("example.tv", testvectors);
vectornum = 0;
errors = 0;
reset = 1;
#50;
reset = 0;
end
always @ (posedge clk)
begin
#1;
{ branch_D, // input to be tested
rs_D, rt_D, // input to be tested
rs_E, rt_E, // input to be tested
writereg_E, // input to be tested
memtoreg_E, // input to be tested
regwrite_E, // input to be tested
writereg_M, // input to be tested
memtoreg_M, // input to be tested
regwrite_M, // input to be tested
writereg_W, // input to be tested
regwrite_W, // input to be tested
stall_F_expected, // output to be compared to
stall_D_expected, // output to be compared to
forwardA_D_expected, // output to be compared to
forwardB_D_expected, // output to be compared to
flush_E_expected, // output to be compared to
forwardA_E_expected, // output to be compared to
forwardB_E_expected // output to be compared to
} = testvectors[vectornum];
end
always @ (negedge clk)
if (~reset)
begin // skip cycles during reset
if (
{ stall_F, // output to be compared
stall_D, // output to be compared
forwardA_D, forwardB_D, // output to be compared
flush_E, // output to be compared
forwardA_E, forwardB_E // output to be compared
} !==
{ stall_F_expected, // output to be compared to
stall_D_expected, // output to be compared to
forwardA_D_expected, // output to be compared to
forwardB_D_expected, // output to be compared to
flush_E_expected, // output to be compared to
forwardA_E_expected, // output to be compared to
forwardB_E_expected // output to be compared to
}
)
begin // check result
$display( "Error in Test %d: Inputs = %b",
vectornum,
{ branch_D, // input to be tested
rs_D, rt_D, // input to be tested
rs_E, rt_E, // input to be tested
writereg_E, // input to be tested
memtoreg_E, // input to be tested
regwrite_E, // input to be tested
writereg_M, // input to be tested
memtoreg_M, // input to be tested
regwrite_M, // input to be tested
writereg_W, // input to be tested
regwrite_W // input to be tested
});
$display( " Outputs = %b (%b expected)",
{ stall_F, // output to be compared
stall_D, // output to be compared
forwardA_D, forwardB_D, // output to be compared
flush_E, // output to be compared
forwardA_E, forwardB_E // output to be compared
},
{ stall_F_expected, // output to be compared to
stall_D_expected, // output to be compared to
forwardA_D_expected, // output to be compared to
forwardB_D_expected, // output to be compared to
flush_E_expected, // output to be compared to
forwardA_E_expected, // output to be compared to
forwardB_E_expected // output to be compared to
});
errors = errors + 1;
end
else
begin
$display( "CORRECT: Test %d",
vectornum);
end
vectornum = vectornum + 1;
if (testvectors[vectornum] === 50'bx)
begin
$display( "%d tests completed with %d errors",
vectornum, errors);
$finish;
end
end
endmodule
/*
example.tv
0_11111_00000_00000_11111_00000_1_0_00000_0_0_00000_0___1_1_0_0_1_00_00 // rs_D = rs_E, memtoreg_E = 1: expect load hazard (STALL)
0_00000_11111_00000_11111_00000_1_0_00000_0_0_00000_0___1_1_0_0_1_00_00 // rt_D = rs_E, memtoreg_E = 1: expect load hazard (STALL)
1_11111_00000_00000_00000_11111_0_1_00000_0_0_00000_0___1_1_0_0_1_00_00 // branchD = 1, rs_D = writereg_E, regwrite_E = 1: expect branch data hazard (STALL)
1_00000_11111_00000_00000_11111_0_1_00000_0_0_00000_0___1_1_0_0_1_00_00 // branchD = 1, rt_D = writereg_E, regwrite_E = 1: expect branch data hazard (STALL)
1_11111_00000_00000_00000_00000_0_0_11111_1_0_00000_0___1_1_0_0_1_00_00 // branchD = 1, rs_D = writereg_M, memtoreg_M = 1: expect branch control hazard (STALL)
1_00000_11111_00000_00000_00000_0_0_11111_1_0_00000_0___1_1_0_0_1_00_00 // branchD = 1, rt_D = writereg_M, memtoreg_M = 1: expect branch control hazard (STALL)
0_11111_00000_00000_00000_00000_0_0_11111_0_1_00000_0___0_0_1_0_0_00_00 // rs_D != 0, rs_D = writereg_M, regwrite_M = 1: expect srcA_D RAW hazard (FORWARD A_D)
0_00000_11111_00000_00000_00000_0_0_11111_0_1_00000_0___0_0_0_1_0_00_00 // rt_D != 0, rt_D = writereg_M, regwrite_M = 1: expect srcB_D RAW hazard (FORWARD B_D)
0_00000_00000_11111_00000_00000_0_0_11111_0_1_00000_0___0_0_0_0_0_10_00 // rs_E != 0, rs_E = writereg_M, regwrite_M = 1: expect srcA_E RAW hazard (FORWARD A_E)
0_00000_00000_11111_00000_00000_0_0_00000_0_0_11111_1___0_0_0_0_0_01_00 // rs_E != 0, rs_E = writereg_W, regwrite_W = 1: expect srcA_E RAW hazard (FORWARD A_E)
0_00000_00000_00000_11111_00000_0_0_11111_0_1_00000_0___0_0_0_0_0_00_10 // rt_E != 0, rt_E = writereg_M, regwrite_M = 1: expect srcB_E RAW hazard (FORWARD B_E)
0_00000_00000_00000_11111_00000_0_0_00000_0_0_11111_1___0_0_0_0_0_00_01 // rt_E != 0, rt_E = writereg_W, regwrite_W = 1: expect srcB_E RAW hazard (FORWARD B_E)
0_10101_00000_00000_01010_00000_1_0_00000_0_0_00000_0___0_0_0_0_0_00_00 // rs_D != rs_E, memtoreg_E = 1: NO HAZARD
0_11111_00000_00000_11111_00000_0_0_00000_0_0_00000_0___0_0_0_0_0_00_00 // rs_D = rs_E, memtoreg_E != 1: NO HAZARD
0_11111_00000_00000_00000_11111_0_1_00000_0_0_00000_0___0_0_0_0_0_00_00 // branchD != 1, rs_D = writereg_E, regwrite_E = 1: NO HAZARD
1_10101_00000_00000_00000_01010_0_1_00000_0_0_00000_0___0_0_0_0_0_00_00 // branchD = 1, rs_D != writereg_E, regwrite_E = 1: NO HAZARD
1_11111_00000_00000_00000_11111_0_0_00000_0_0_00000_0___0_0_0_0_0_00_00 // branchD = 1, rs_D = writereg_E, regwrite_E != 1: NO HAZARD
0_00000_11111_00000_00000_11111_0_1_00000_0_0_00000_0___0_0_0_0_0_00_00 // branchD != 1, rt_D = writereg_E, regwrite_E = 1: NO HAZARD
1_00000_10101_00000_00000_01010_0_1_00000_0_0_00000_0___0_0_0_0_0_00_00 // branchD = 1, rt_D != writereg_E, regwrite_E = 1: NO HAZARD
1_00000_11111_00000_00000_11111_0_0_00000_0_0_00000_0___0_0_0_0_0_00_00 // branchD = 1, rt_D = writereg_E, regwrite_E != 1: NO HAZARD
0_11111_00000_00000_00000_00000_0_0_11111_1_0_00000_0___0_0_0_0_0_00_00 // branchD != 1, rs_D = writereg_M, memtoreg_M = 1: NO HAZARD
1_10101_00000_00000_00000_00000_0_0_01010_1_0_00000_0___0_0_0_0_0_00_00 // branchD = 1, rs_D != writereg_M, memtoreg_M = 1: NO HAZARD
1_11111_00000_00000_00000_00000_0_0_11111_0_0_00000_0___0_0_0_0_0_00_00 // branchD = 1, rs_D = writereg_M, memtoreg_M != 1: NO HAZARD
0_00000_11111_00000_00000_00000_0_0_11111_1_0_00000_0___0_0_0_0_0_00_00 // branchD != 1, rt_D = writereg_M, memtoreg_M = 1: NO HAZARD
1_00000_10101_00000_00000_00000_0_0_01010_1_0_00000_0___0_0_0_0_0_00_00 // branchD = 1, rt_D != writereg_M, memtoreg_M = 1: NO HAZARD
1_00000_11111_00000_00000_00000_0_0_11111_0_0_00000_0___0_0_0_0_0_00_00 // branchD = 1, rt_D = writereg_M, memtoreg_M != 1: NO HAZARD
0_00000_00000_00000_00000_00000_0_0_11111_0_1_00000_0___0_0_0_0_0_00_00 // rs_D = 0, rs_D = writereg_M, regwrite_M = 1: NO HAZARD
0_10101_00000_00000_00000_00000_0_0_01010_0_1_00000_0___0_0_0_0_0_00_00 // rs_D != 0, rs_D != writereg_M, regwrite_M = 1: NO HAZARD
0_11111_00000_00000_00000_00000_0_0_11111_0_0_00000_0___0_0_0_0_0_00_00 // rs_D != 0, rs_D = writereg_M, regwrite_M != 1: NO HAZARD
0_00000_00000_00000_00000_00000_0_0_11111_0_1_00000_0___0_0_0_0_0_00_00 // rt_D = 0, rt_D = writereg_M, regwrite_M = 1: NO HAZARD
0_00000_10101_00000_00000_00000_0_0_01010_0_1_00000_0___0_0_0_0_0_00_00 // rt_D != 0, rt_D != writereg_M, regwrite_M = 1: NO HAZARD
0_00000_11111_00000_00000_00000_0_0_11111_0_0_00000_0___0_0_0_0_0_00_00 // rt_D != 0, rt_D = writereg_M, regwrite_M != 1: NO HAZARD
0_00000_00000_00000_00000_00000_0_0_11111_0_1_00000_0___0_0_0_0_0_00_00 // rs_E = 0, rs_E = writereg_M, regwrite_M = 1: NO HAZARD
0_00000_00000_10101_00000_00000_0_0_01010_0_1_00000_0___0_0_0_0_0_00_00 // rs_E != 0, rs_E != writereg_M, regwrite_M = 1: NO HAZARD
0_00000_00000_11111_00000_00000_0_0_11111_0_0_00000_0___0_0_0_0_0_00_00 // rs_E != 0, rs_E = writereg_M, regwrite_M != 1: NO HAZARD
0_00000_00000_00000_00000_00000_0_0_00000_0_0_11111_1___0_0_0_0_0_00_00 // rs_E = 0, rs_E = writereg_W, regwrite_W = 1: NO HAZARD
0_00000_00000_10101_00000_00000_0_0_00000_0_0_01010_1___0_0_0_0_0_00_00 // rs_E != 0, rs_E != writereg_W, regwrite_W = 1: NO HAZARD
0_00000_00000_11111_00000_00000_0_0_00000_0_0_11111_0___0_0_0_0_0_00_00 // rs_E != 0, rs_E = writereg_W, regwrite_W != 1: NO HAZARD
0_00000_00000_00000_00000_00000_0_0_11111_0_1_00000_0___0_0_0_0_0_00_00 // rt_E = 0, rt_E = writereg_M, regwrite_M = 1: NO HAZARD
0_00000_00000_00000_10101_00000_0_0_01010_0_1_00000_0___0_0_0_0_0_00_00 // rt_E != 0, rt_E != writereg_M, regwrite_M = 1: NO HAZARD
0_00000_00000_00000_11111_00000_0_0_11111_0_0_00000_0___0_0_0_0_0_00_00 // rt_E != 0, rt_E = writereg_M, regwrite_M != 1: NO HAZARD
0_00000_00000_00000_00000_00000_0_0_00000_0_0_11111_1___0_0_0_0_0_00_00 // rt_E = 0, rt_E = writereg_W, regwrite_W = 1: NO HAZARD
0_00000_00000_00000_10101_00000_0_0_00000_0_0_01010_1___0_0_0_0_0_00_00 // rt_E != 0, rt_E != writereg_W, regwrite_W = 1: NO HAZARD
0_00000_00000_00000_11111_00000_0_0_00000_0_0_11111_0___0_0_0_0_0_00_00 // rt_E != 0, rt_E = writereg_W, regwrite_W != 1: NO HAZARD
*/