/** * 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_const #( parameter WIDTH = 32, parameter VALUE = 0 ) ( output logic [WIDTH - 1:0] out ); assign out = VALUE; endmodule 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_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_add #( 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 /// Memories module std_reg #( parameter WIDTH = 32 ) ( input wire [ WIDTH-1:0] in, input wire write_en, input wire clk, input wire reset, // output output logic [WIDTH - 1:0] out, output logic done ); always_ff @(posedge clk) begin if (reset) begin out <= 0; done <= 0; end else if (write_en) begin out <= in; done <= 1'd1; end else done <= 1'd0; end endmodule module std_mem_d1 #( parameter WIDTH = 32, parameter SIZE = 16, parameter IDX_SIZE = 4 ) ( input wire logic [IDX_SIZE-1:0] addr0, input wire logic [ WIDTH-1:0] write_data, input wire logic write_en, input wire logic clk, output logic [ WIDTH-1:0] read_data, output logic done ); logic [WIDTH-1:0] mem[SIZE-1:0]; /* verilator lint_off WIDTH */ assign read_data = mem[addr0]; always_ff @(posedge clk) begin if (write_en) begin mem[addr0] <= write_data; done <= 1'd1; end else done <= 1'd0; end endmodule module std_mem_d2 #( parameter WIDTH = 32, parameter D0_SIZE = 16, parameter D1_SIZE = 16, parameter D0_IDX_SIZE = 4, parameter D1_IDX_SIZE = 4 ) ( input wire logic [D0_IDX_SIZE-1:0] addr0, input wire logic [D1_IDX_SIZE-1:0] addr1, input wire logic [ WIDTH-1:0] write_data, input wire logic write_en, input wire logic clk, output logic [ WIDTH-1:0] read_data, output logic done ); /* verilator lint_off WIDTH */ logic [WIDTH-1:0] mem[D0_SIZE-1:0][D1_SIZE-1:0]; assign read_data = mem[addr0][addr1]; always_ff @(posedge clk) begin if (write_en) begin mem[addr0][addr1] <= write_data; done <= 1'd1; end else done <= 1'd0; end endmodule module std_mem_d3 #( parameter WIDTH = 32, parameter D0_SIZE = 16, parameter D1_SIZE = 16, parameter D2_SIZE = 16, parameter D0_IDX_SIZE = 4, parameter D1_IDX_SIZE = 4, parameter D2_IDX_SIZE = 4 ) ( input wire logic [D0_IDX_SIZE-1:0] addr0, input wire logic [D1_IDX_SIZE-1:0] addr1, input wire logic [D2_IDX_SIZE-1:0] addr2, input wire logic [ WIDTH-1:0] write_data, input wire logic write_en, input wire logic clk, output logic [ WIDTH-1:0] read_data, output logic done ); /* verilator lint_off WIDTH */ logic [WIDTH-1:0] mem[D0_SIZE-1:0][D1_SIZE-1:0][D2_SIZE-1:0]; assign read_data = mem[addr0][addr1][addr2]; always_ff @(posedge clk) begin if (write_en) begin mem[addr0][addr1][addr2] <= write_data; done <= 1'd1; end else done <= 1'd0; end endmodule module std_mem_d4 #( parameter WIDTH = 32, parameter D0_SIZE = 16, parameter D1_SIZE = 16, parameter D2_SIZE = 16, parameter D3_SIZE = 16, parameter D0_IDX_SIZE = 4, parameter D1_IDX_SIZE = 4, parameter D2_IDX_SIZE = 4, parameter D3_IDX_SIZE = 4 ) ( input wire logic [D0_IDX_SIZE-1:0] addr0, input wire logic [D1_IDX_SIZE-1:0] addr1, input wire logic [D2_IDX_SIZE-1:0] addr2, input wire logic [D3_IDX_SIZE-1:0] addr3, input wire logic [ WIDTH-1:0] write_data, input wire logic write_en, input wire logic clk, output logic [ WIDTH-1:0] read_data, output logic done ); /* verilator lint_off WIDTH */ logic [WIDTH-1:0] mem[D0_SIZE-1:0][D1_SIZE-1:0][D2_SIZE-1:0][D3_SIZE-1:0]; assign read_data = mem[addr0][addr1][addr2][addr3]; always_ff @(posedge clk) begin if (write_en) begin mem[addr0][addr1][addr2][addr3] <= write_data; done <= 1'd1; end else done <= 1'd0; end endmodule `default_nettype wire