/
core.sv
242 lines (219 loc) · 5.28 KB
/
core.sv
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
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
/**
* Core primitives for Calyx.
* Implements core primitives used by the compiler.
*
* Conventions:
* - All parameter names must be SNAKE_CASE and all caps.
* - Port names must be snake_case, no caps.
*/
module std_slice #(
parameter IN_WIDTH = 32,
parameter OUT_WIDTH = 32
) (
input wire logic [ IN_WIDTH-1:0] in,
output logic [OUT_WIDTH-1:0] out
);
assign out = in[OUT_WIDTH-1:0];
`ifdef VERILATOR
always_comb begin
if (IN_WIDTH < OUT_WIDTH)
$error(
"std_slice: Input width less than output width\n",
"IN_WIDTH: %0d", IN_WIDTH,
"OUT_WIDTH: %0d", OUT_WIDTH
);
end
`endif
endmodule
module std_pad #(
parameter IN_WIDTH = 32,
parameter OUT_WIDTH = 32
) (
input wire logic [IN_WIDTH-1:0] in,
output logic [OUT_WIDTH-1:0] out
);
localparam EXTEND = OUT_WIDTH - IN_WIDTH;
assign out = { {EXTEND {1'b0}}, in};
`ifdef VERILATOR
always_comb begin
if (IN_WIDTH > OUT_WIDTH)
$error(
"std_pad: Output width less than input width\n",
"IN_WIDTH: %0d", IN_WIDTH,
"OUT_WIDTH: %0d", OUT_WIDTH
);
end
`endif
endmodule
module std_cat #(
parameter LEFT_WIDTH = 32,
parameter RIGHT_WIDTH = 32,
parameter OUT_WIDTH = 64
) (
input wire logic [LEFT_WIDTH-1:0] left,
input wire logic [RIGHT_WIDTH-1:0] right,
output logic [OUT_WIDTH-1:0] out
);
assign out = {left, right};
`ifdef VERILATOR
always_comb begin
if (LEFT_WIDTH + RIGHT_WIDTH != OUT_WIDTH)
$error(
"std_cat: Output width must equal sum of input widths\n",
"LEFT_WIDTH: %0d", LEFT_WIDTH,
"RIGHT_WIDTH: %0d", RIGHT_WIDTH,
"OUT_WIDTH: %0d", OUT_WIDTH
);
end
`endif
endmodule
module std_not #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] in,
output logic [WIDTH-1:0] out
);
assign out = ~in;
endmodule
module std_and #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic [WIDTH-1:0] out
);
assign out = left & right;
endmodule
module std_or #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic [WIDTH-1:0] out
);
assign out = left | right;
endmodule
module std_xor #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic [WIDTH-1:0] out
);
assign out = left ^ right;
endmodule
module std_sub #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic [WIDTH-1:0] out
);
assign out = left - right;
endmodule
module std_gt #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic out
);
assign out = left > right;
endmodule
module std_lt #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic out
);
assign out = left < right;
endmodule
module std_eq #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic out
);
assign out = left == right;
endmodule
module std_neq #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic out
);
assign out = left != right;
endmodule
module std_ge #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic out
);
assign out = left >= right;
endmodule
module std_le #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic out
);
assign out = left <= right;
endmodule
module std_lsh #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic [WIDTH-1:0] out
);
assign out = left << right;
endmodule
module std_rsh #(
parameter WIDTH = 32
) (
input wire logic [WIDTH-1:0] left,
input wire logic [WIDTH-1:0] right,
output logic [WIDTH-1:0] out
);
assign out = left >> right;
endmodule
/// this primitive is intended to be used
/// for lowering purposes (not in source programs)
module std_mux #(
parameter WIDTH = 32
) (
input wire logic cond,
input wire logic [WIDTH-1:0] tru,
input wire logic [WIDTH-1:0] fal,
output logic [WIDTH-1:0] out
);
assign out = cond ? tru : fal;
endmodule
module std_bit_slice #(
parameter IN_WIDTH = 32,
parameter START_IDX = 0,
parameter END_IDX = 31,
parameter OUT_WIDTH = 32
)(
input wire logic [IN_WIDTH-1:0] in,
output logic [OUT_WIDTH-1:0] out
);
assign out = in[END_IDX:START_IDX];
`ifdef VERILATOR
always_comb begin
if (START_IDX < 0 || END_IDX > IN_WIDTH-1)
$error(
"std_bit_slice: Slice range out of bounds\n",
"IN_WIDTH: %0d", IN_WIDTH,
"START_IDX: %0d", START_IDX,
"END_IDX: %0d", END_IDX,
);
end
`endif
endmodule