-
Notifications
You must be signed in to change notification settings - Fork 0
/
offset_sampler.v
219 lines (178 loc) · 6.05 KB
/
offset_sampler.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
211
212
213
214
215
216
217
218
219
//
// Text fixture for the Simple SPI interface on the raspi.
//
// UNCLASSIFIED // PROPRIETARY // GOV USE RIGHTS
// This will hopefully be replaced with an FOSS license soon.
//
// Copyright (c) Assured Information Security, inc.
// Author: Kyle J. Temkin
//
`default_nettype none
module offset_sampler(
input wire clk,
input wire ets_clk,
input wire baseclk,
input wire request_run,
// Input charactersitics
input wire [31:0] pre_value,
input wire [31:0] post_value,
// Timing characteristics
input wire [31:0] dut_signal_select,
input wire [31:0] total_cycles,
// Output
output wire running,
output reg result_ready,
output reg [31:0] result
);
// Define our FSM states.
localparam STATE_RESET = 9'b000000000;
localparam STATE_WAIT = 9'b000000001;
localparam STATE_PREPARE = 9'b000000010;
localparam STATE_PRIME = 9'b000000100;
localparam STATE_SAMPLE = 9'b000001000;
localparam STATE_COUNT = 9'b000010000;
localparam STATE_BUBBLE1 = 9'b000100000;
localparam STATE_BUBBLE2 = 9'b001000000;
localparam STATE_OUTPUT1 = 9'b010000000;
localparam STATE_OUTPUT2 = 9'b100000000;
reg [8:0] state;
// I/O for the device under test.
reg dut_load_pre;
reg dut_load_post;
reg [31:0] dut_input_buffer;
wire dut_output;
// !!! Signals in the ETS clock domain.
reg ets_offset_sample;
reg [1:0] sample_request_synchronizer;
// </ets-domain>
reg count_sample;
reg [1:0] sample_synchronizer;
// The number of ones observed on the output sample.
reg clear_one_count;
reg increment_one_count;
reg [31:0] one_count;
// The number of test iterations that have been performed thus far.
reg clear_iter_count;
reg increment_iter_count;
reg [31:0] iter_count;
//
// Datapath
//
assign running = (state != STATE_WAIT);
// Input register for the DUT.
always @(posedge clk) begin
if (dut_load_pre)
dut_input_buffer <= pre_value;
else if (dut_load_post)
dut_input_buffer <= post_value;
end
// Core device under test.
dut sample_dut (dut_input_buffer, dut_signal_select, dut_output);
// Offset sampling register for the DUT output.
always @(posedge ets_clk)
ets_offset_sample <= dut_output;
// Synchronizer to bring ETS-domain samples back into the main clock domain.
always @(posedge clk)
sample_synchronizer <= {sample_synchronizer[0], ets_offset_sample};
// One-counter for the captured ETS results.
// Counts the total number of post-synchronized samples that are '1'
// when count_sample is high.
always @(posedge clk) begin
if (clear_one_count)
one_count <= 0;
else if (sample_synchronizer[1] && count_sample)
one_count <= one_count + 1;
end
// Iteration counter
always @(posedge clk) begin
if (clear_iter_count)
iter_count <= 0;
else if(increment_iter_count)
iter_count <= iter_count + 1;
end
//
// Control
//
initial begin
// Ignored on lattice FPGAs, so this must always have state code 0.
state <= STATE_RESET;
end
always @(posedge clk) begin
// Default our control signals to unasserted.
dut_load_pre <= 0;
dut_load_post <= 0;
clear_one_count <= 0;
result_ready <= 0;
clear_iter_count <= 0;
increment_iter_count <= 0;
count_sample <= 0;
case(state)
// On reset, wait for the run signal to be asserted.
STATE_RESET: begin
state <= STATE_WAIT;
end
// Don't perform any tests until the run signal has been asserted.
STATE_WAIT: begin
clear_one_count <= 1;
clear_iter_count <= 1;
if (request_run)
state <= STATE_PREPARE;
end
// Prepare state: prepare the test by applying the "before" input
// value to the DUT inputs.
STATE_PREPARE: begin
dut_load_pre <= 1;
state <= STATE_PRIME;
end
// Prime state: prime the test by the post-clock stimulus.
STATE_PRIME: begin
dut_load_post <= 1;
state <= STATE_SAMPLE;
end
// Sample state-- give the circuit time to sample.
STATE_SAMPLE: begin
increment_iter_count <= 1;
state <= STATE_BUBBLE1;
end
// Bubble state: wait for the sample result to synchronize
// back to our clock domain.
STATE_BUBBLE1: begin
state <= STATE_BUBBLE2;
end
// Bubble state: wait for the sample result to synchronize
// back to our clock domain.
STATE_BUBBLE2: begin
state <= STATE_COUNT;
end
// Count state: tally the synchronized result.
STATE_COUNT: begin
count_sample <= 1;
// If we've completed our run, move to the output state.
// Otherwise, continue to another iteration.
if (iter_count >= total_cycles)
state <= STATE_OUTPUT1;
else
state <= STATE_PREPARE;
end
// Wait state: after asserting count, we need to give the
// counter a cycle to update before our result is ready.
STATE_OUTPUT1: begin
state <= STATE_OUTPUT2;
end
// Output state: output the value achieved during this run.
STATE_OUTPUT2: begin
result_ready <= 1;
result <= one_count;
state <= STATE_WAIT;
end
endcase
end
// If we're simulating, also generate a VCD we can view.
`ifdef COCOTB_SIM
initial begin
$dumpfile ("offset_sampler.vcd");
$dumpvars;
#1;
end
`endif
endmodule