/** * 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