Newer
Older
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
//-----------------------------------------------------------------------------
// SoC Labs Basic SHA-256 Configuration Synchroniser
// A joint work commissioned on behalf of SoC Labs, under Arm Academic Access license.
//
// Contributors
//
// David Mapstone (d.a.mapstone@soton.ac.uk)
//
// Copyright 2023, SoC Labs (www.soclabs.org)
//-----------------------------------------------------------------------------
module sha256_config_sync (
input logic clk,
input logic nrst,
input logic en,
// Synchronous, localised reset
input logic sync_rst,
// ID In and Handshaking
input logic [5:0] id_in,
input logic id_in_last,
input logic id_in_valid,
output logic id_in_ready,
// Config data and Handshaking
input logic [63:0] cfg_in_size,
input logic [1:0] cfg_in_scheme,
input logic cfg_in_last,
input logic cfg_in_valid,
output logic cfg_in_ready,
// Data Out data and Handshaking
output logic [63:0] cfg_out_size,
output logic [1:0] cfg_out_scheme,
output logic [5:0] cfg_out_id,
output logic cfg_out_last,
output logic cfg_out_valid,
input logic cfg_out_ready
);
logic [1:0] state, next_state;
logic next_cfg_in_ready;
logic next_id_in_ready;
logic [63:0] next_cfg_out_size;
logic [1:0] next_cfg_out_scheme;
logic [5:0] next_cfg_out_id;
logic next_cfg_out_last;
logic next_cfg_out_valid;
// State Machine Sequential Logic
always_ff @(posedge clk, negedge nrst) begin
if ((!nrst) | sync_rst) begin
state <= 2'd0;
cfg_out_size <= 64'd0;
cfg_out_scheme <= 2'd0;
cfg_out_id <= 6'd0;
cfg_out_last <= 1'b0;
cfg_out_valid <= 1'b0;
cfg_in_ready <= 1'b0;
id_in_ready <= 1'b0;
end else if (en == 1'b1) begin
state <= next_state;
cfg_out_size <= next_cfg_out_size;
cfg_out_scheme <= next_cfg_out_scheme;
cfg_out_id <= next_cfg_out_id;
cfg_out_last <= next_cfg_out_last;
cfg_out_valid <= next_cfg_out_valid;
cfg_in_ready <= next_cfg_in_ready;
id_in_ready <= next_id_in_ready;
end else begin
cfg_out_valid <= 1'b0;
cfg_in_ready <= 1'b0;
id_in_ready <= 1'b0;
end
end
always_comb begin
// Default
next_state = state;
next_cfg_out_size = cfg_out_size;
next_cfg_out_scheme = cfg_out_scheme;
next_cfg_out_id = cfg_out_id;
next_cfg_out_last = cfg_out_last;
next_cfg_out_valid = cfg_out_valid;
next_cfg_in_ready = cfg_in_ready;
next_id_in_ready = id_in_ready;
// Override
case (state)
2'd0: begin
next_cfg_in_ready = 1'b1;
next_id_in_ready = 1'b1;
next_state = 2'd1;
end
2'd1: begin
// Check outputs can be written to
if (cfg_out_valid && !cfg_out_ready) begin
// If data out is valid and ready is low, there is already data waiting to be transferred
next_cfg_in_ready = 1'b0;
next_id_in_ready = 1'b0;
// If there is no Valid data at the output or there is a valid transfer happening on this clock cycle
end else begin
// These can be overloaded later if data is written to the outputs
next_cfg_out_valid = 1'b0;
next_cfg_in_ready = 1'b1;
next_id_in_ready = 1'b1;
next_cfg_out_last = 1'b0;
// Check cfg input
if (cfg_in_ready && cfg_in_valid) begin
next_cfg_out_last = cfg_in_last;
next_cfg_out_scheme = cfg_in_scheme;
next_cfg_out_size = cfg_in_size;
next_cfg_in_ready = 1'b0;
next_state = 2'd2;
end
// Check Id input
if (id_in_ready && id_in_valid) begin
next_cfg_out_id = id_in;
next_id_in_ready = 1'b0;
next_state = 2'd3;
end
// Check if both inputs handshaked
if ((id_in_ready && id_in_valid) && (cfg_in_ready && cfg_in_valid)) begin
next_cfg_out_valid = 1'b1;
if (!cfg_out_valid && cfg_out_ready) begin
// In case where no valid data and ready is waiting for valid data
// - (will be asserted next cc), guaranteed handshake next cycle
next_cfg_in_ready = 1'b1;
next_cfg_in_ready = 1'b1;
end else begin
next_cfg_in_ready = 1'b0;
next_id_in_ready = 1'b0;
end
next_state = 2'd1;
end
end
end
2'd2: begin // Cfg already handshaked - wait for ID handshake
// These can be overloaded later if data is written to the outputs
next_cfg_out_valid = 1'b0;
next_cfg_in_ready = 1'b0;
next_id_in_ready = 1'b1;
// Check Id input
if (id_in_ready && id_in_valid) begin
next_cfg_out_id = id_in;
next_cfg_out_valid = 1'b1;
if (cfg_out_ready) begin // Guaranteeded Handshake next clock cycle
next_cfg_in_ready = 1'b1;
next_id_in_ready = 1'b1;
end else begin
next_cfg_in_ready = 1'b0;
next_id_in_ready = 1'b0;
end
next_state = 2'd1;
end
end
2'd3: begin // ID already handshaked - wait for config handshake
// These can be overloaded later if data is written to the outputs
next_cfg_out_valid = 1'b0;
next_cfg_in_ready = 1'b1;
next_id_in_ready = 1'b0;
// Check config input
if (cfg_in_ready && cfg_in_valid) begin
next_cfg_out_last = cfg_in_last;
next_cfg_out_scheme = cfg_in_scheme;
next_cfg_out_size = cfg_in_size;
next_cfg_out_valid = 1'b1;
if (cfg_out_ready) begin // Guaranteeded Handshake next clock cycle
next_cfg_in_ready = 1'b1;
next_id_in_ready = 1'b1;
end else begin
next_cfg_in_ready = 1'b0;
next_id_in_ready = 1'b0;
end
next_state = 2'd1;
end
end
endcase
end
endmodule