/** * 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 module main ( input logic go, input logic clk, input logic reset, output logic done ); import "DPI-C" function string futil_getenv (input string env_var); string DATA; initial begin DATA = futil_getenv("DATA"); $fdisplay(2, "DATA (path to meminit files): %s", DATA); $readmemh({DATA, "/m1.dat"}, m1.mem); end final begin $writememh({DATA, "/m1.out"}, m1.mem); end logic [3:0] m0_addr0; logic [31:0] m0_write_data; logic m0_write_en; logic m0_clk; logic [31:0] m0_read_data; logic m0_done; logic [3:0] m1_addr0; logic [31:0] m1_write_data; logic m1_write_en; logic m1_clk; logic [31:0] m1_read_data; logic m1_done; initial begin m0_addr0 = 4'd0; m0_write_data = 32'd0; m0_write_en = 1'd0; m0_clk = 1'd0; m1_addr0 = 4'd0; m1_write_data = 32'd0; m1_write_en = 1'd0; m1_clk = 1'd0; end std_mem_d1 # ( .IDX_SIZE(4), .SIZE(4), .WIDTH(32) ) m0 ( .addr0(m0_addr0), .clk(m0_clk), .done(m0_done), .read_data(m0_read_data), .write_data(m0_write_data), .write_en(m0_write_en) ); std_mem_d1 # ( .IDX_SIZE(4), .SIZE(4), .WIDTH(32) ) m1 ( .addr0(m1_addr0), .clk(m1_clk), .done(m1_done), .read_data(m1_read_data), .write_data(m1_write_data), .write_en(m1_write_en) ); assign done = 1'b1 ? m1_done : 1'd0; assign m0_clk = 1'b1 ? clk : 1'd0; assign m1_clk = 1'b1 ? clk : 1'd0; endmodule