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
|
/*
* This module transforms a Wishbone pipelined MASTER interface with 32-bit
* data port and 8-bit granularity into one with 16-bit data port and 16-bit
* granularity. It's just a wrapper, it is not considered a Wishbone SLAVE nor
* MASTER by itself (although it could be presented that way). See Wishbone
* datasheets of data interfaces in stack_machine.v and wrapped_stack_machine.v.
*/
`default_nettype none
module interface_wrapper
(
input wire CLK_I,
input wire RST_I,
output wire RAW_ACK_I,
output wire RAW_ERR_I, /* We'll start using it soon */
input wire [20:0] RAW_ADR_O,
output wire [31:0] RAW_DAT_I,
input wire [31:0] RAW_DAT_O,
input wire [3:0] RAW_SEL_O,
input wire RAW_STB_O,
input wire RAW_CYC_O,
input wire RAW_WE_O,
output wire RAW_STALL_I,
input wire WRAPPED_ACK_I,
output wire [19:0] WRAPPED_ADR_O,
input wire [15:0] WRAPPED_DAT_I,
output wire [15:0] WRAPPED_DAT_O,
output wire WRAPPED_STB_O,
output wire WRAPPED_CYC_O,
output wire WRAPPED_WE_O,
input wire WRAPPED_STALL_I
);
wire raw_request_wanted;
wire raw_request_completes;
wire wrapped_request_sent;
wire wrapped_request_completes;
assign raw_request_wanted = RAW_CYC_O && RAW_STB_O;
assign raw_request_completes = RAW_CYC_O && RAW_ACK_I;
assign wrapped_request_sent = WRAPPED_CYC_O && WRAPPED_STB_O &&
!WRAPPED_STALL_I;
assign wrapped_request_completes = WRAPPED_CYC_O && WRAPPED_ACK_I;
/* "Parsing" raw command */
wire nothing_selected;
wire [1:0] highest_selected_byte;
wire [1:0] transfers_needed;
wire start_with_read;
assign nothing_selected = RAW_SEL_O == 4'b0;
assign highest_selected_byte = RAW_SEL_O[3] ? 3 :
RAW_SEL_O[2] ? 2 :
RAW_SEL_O[1] ? 1 : 0;
assign transfers_needed = nothing_selected ? 1 :
(RAW_ADR_O[0] + highest_selected_byte + 2) / 2;
assign start_with_read = !RAW_WE_O || RAW_ADR_O[0] ||
RAW_SEL_O[0] != RAW_SEL_O[1] ||
RAW_SEL_O[2] != RAW_SEL_O[3] ||
nothing_selected;
/* Sending commands */
reg [1:0] left_to_send;
reg [19:0] ADR;
reg WE;
reg STB;
reg [47:0] write_data;
/* Receiving responses */
reg [31:0] received_data_part;
reg [1:0] acks_waited_for;
reg [20:0] saved_ADR;
reg [1:0] writes_back_needed;
reg [4:0] write_mask;
wire [47:0] received_data;
wire command_sequence_finishes;
wire can_accept_raw_command;
assign received_data = {received_data_part, WRAPPED_DAT_I};
assign command_sequence_finishes = acks_waited_for == 1 && WRAPPED_ACK_I;
assign can_accept_raw_command = acks_waited_for == 0 ||
(writes_back_needed == 0 &&
command_sequence_finishes);
assign RAW_ACK_I = writes_back_needed == 0 && command_sequence_finishes;
assign RAW_DAT_I = saved_ADR[0] ? received_data >> 8 : received_data;
assign RAW_STALL_I = !can_accept_raw_command;
assign WRAPPED_CYC_O = RAW_CYC_O;
assign WRAPPED_ADR_O = ADR;
assign WRAPPED_WE_O = WE;
assign WRAPPED_STB_O = STB;
assign WRAPPED_DAT_O = write_data[15:0];
always @ (posedge CLK_I) begin
if (wrapped_request_sent) begin
/* Variable assignments here are overridden further down */
left_to_send <= left_to_send - 1;
if (WE)
ADR <= ADR + 1;
else
ADR <= ADR - 1;
if (left_to_send == 1)
STB <= 0;
if (WE)
write_data <= {16'bx, write_data[47:16]};
end // if (wrapped_request_sent)
if (wrapped_request_completes) begin
received_data_part <= {received_data_part[15:0], WRAPPED_DAT_I};
acks_waited_for <= acks_waited_for - 1; /* might get overridden */
end
if (writes_back_needed != 0 && command_sequence_finishes) begin
/* Write data back */
left_to_send <= writes_back_needed;
ADR <= saved_ADR[20:1];
WE <= 1;
STB <= 1;
write_data[47:40] <= received_data[47:40];
if (!write_mask[4])
write_data[39:32] <= received_data[39:32];
if (!write_mask[3])
write_data[31:24] <= received_data[31:24];
if (!write_mask[2])
write_data[23:16] <= received_data[23:16];
if (!write_mask[1])
write_data[15:8] <= received_data[15:8];
if (!write_mask[0])
write_data[7:0] <= received_data[7:0];
acks_waited_for <= writes_back_needed;
writes_back_needed <= 0;
end // if (writes_back_needed != 0 && command_sequence_finishes)
if (raw_request_wanted && can_accept_raw_command) begin
/* Setting up for sending commands */
left_to_send <= transfers_needed;
if (start_with_read)
ADR <= RAW_ADR_O[20:1] + transfers_needed - 1;
else
ADR <= RAW_ADR_O[20:1];
WE <= !start_with_read;
STB <= 1;
if (RAW_ADR_O[0])
write_data <= {8'bx, RAW_DAT_O, 8'bx};
else
write_data <= {16'bx, RAW_DAT_O};
/* Setting up for receiving responses */
acks_waited_for <= transfers_needed;
saved_ADR <= RAW_ADR_O;
if (RAW_WE_O && start_with_read && !nothing_selected)
writes_back_needed <= transfers_needed;
else
writes_back_needed <= 0;
if (RAW_ADR_O[0])
write_mask <= {RAW_SEL_O, 1'b0};
else
write_mask <= {1'b0, RAW_SEL_O};
end // if (raw_request_wanted && can_accept_raw_command)
/* Override what's needed */
if (RST_I) begin
left_to_send <= 0;
STB <= 0;
acks_waited_for <= 0;
writes_back_needed <= 0;
end
end // always @ (posedge CLK_I)
`ifdef SIMULATION
/* Avoid undefined values */
initial begin
left_to_send <= 0;
STB <= 0;
acks_waited_for <= 0;
writes_back_needed <= 0;
end
`endif
endmodule // interface_wrapper
|