/**
* 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.
*/
`default_nettype none
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