blob: 4351ff24d6096a1d8cc9554e77e687a889ccb48e [file] [log] [blame]
`default_nettype none
// Keep I/O fixed for TinyTapeout
module user_module_341176884318437971(
input wire [7:0] io_in,
output wire [7:0] io_out
);
/*
* Local signals
*/
// Used as a clock.
wire clk;
// Used as a synchronous reset.
wire rst;
// Indicates that the first nibble is registered.
reg int_nibble_stored;
// The registered first nibble.
reg [3:0] int_first_nibble;
// The resistered output.
reg [7:0] int_out;
// The multiplied 8-bit output.
wire [7:0] int_mult_result;
/*
* Logic
*/
// Using io_in[0] as clk.
assign clk = io_in[0];
// Using io_in[1] as rst.
assign rst = io_in[1];
// Assign the
assign io_out = int_out;
always @(posedge clk) begin
if (rst) begin
int_nibble_stored <= 1'b0;
int_first_nibble <= 4'd0;
int_out <= 8'd0;
end else begin
// If we havent latched in the first nibble,
// then do so first.
if (!int_nibble_stored) begin
int_first_nibble <= io_in[7:4];
int_nibble_stored <= 1'b1;
end else begin
// Register the multiplier result.
int_out <= int_mult_result;
// Reset the nibble registered flag.
int_nibble_stored <= 1'b0;
// Reset the nibble data.
int_first_nibble <= 4'd0;
end
end
end
/*
* Instances
*/
Mult_Wallace4 inst_mul (
.a(int_first_nibble),
.b(io_in[7:4]),
.o(int_mult_result)
);
endmodule
// Unsigned 4x4-bit multiplier with
// Wallace tree reduction. Generated
// with my own tool.
module Mult_Wallace4 # (
parameter N = 4
)(
input wire [N-1:0] a,
input wire [N-1:0] b,
output wire [2*N-1:0] o
);
wire [N-1:0] ppts[N-1:0];
assign ppts[0][0] = a[0] & b[0];
assign ppts[0][1] = a[0] & b[1];
assign ppts[0][2] = a[0] & b[2];
assign ppts[0][3] = a[0] & b[3];
assign ppts[1][0] = a[1] & b[0];
assign ppts[1][1] = a[1] & b[1];
assign ppts[1][2] = a[1] & b[2];
assign ppts[1][3] = a[1] & b[3];
assign ppts[2][0] = a[2] & b[0];
assign ppts[2][1] = a[2] & b[1];
assign ppts[2][2] = a[2] & b[2];
assign ppts[2][3] = a[2] & b[3];
assign ppts[3][0] = a[3] & b[0];
assign ppts[3][1] = a[3] & b[1];
assign ppts[3][2] = a[3] & b[2];
assign ppts[3][3] = a[3] & b[3];
wire [11:0] s;
wire [11:0] cout;
ha HA1 (.a(ppts[0][1]), .b(ppts[1][0]), .s(s[0]), .cout(cout[0]));
fa FA2 (.a(ppts[0][2]), .b(ppts[1][1]), .cin(ppts[2][0]), .s(s[1]), .cout(cout[1]));
fa FA3 (.a(ppts[0][3]), .b(ppts[1][2]), .cin(ppts[2][1]), .s(s[2]), .cout(cout[2]));
ha HA4 (.a(ppts[1][3]), .b(ppts[2][2]), .s(s[3]), .cout(cout[3]));
ha HA5 (.a(cout[0]), .b(s[1]), .s(s[4]), .cout(cout[4]));
fa FA6 (.a(ppts[3][0]), .b(cout[1]), .cin(s[2]), .s(s[5]), .cout(cout[5]));
fa FA7 (.a(ppts[3][1]), .b(cout[2]), .cin(s[3]), .s(s[6]), .cout(cout[6]));
fa FA8 (.a(ppts[2][3]), .b(ppts[3][2]), .cin(cout[3]), .s(s[7]), .cout(cout[7]));
ha HA9 (.a(cout[4]), .b(s[5]), .s(s[8]), .cout(cout[8]));
fa FA10 (.a(cout[5]), .b(s[6]), .cin(cout[8]), .s(s[9]), .cout(cout[9]));
fa FA11 (.a(cout[6]), .b(s[7]), .cin(cout[9]), .s(s[10]), .cout(cout[10]));
fa FA12 (.a(ppts[3][3]), .b(cout[7]), .cin(cout[10]), .s(s[11]), .cout(cout[11]));
assign o[7] = cout[11];
assign o[6] = s[11];
assign o[5] = s[10];
assign o[4] = s[9];
assign o[3] = s[8];
assign o[2] = s[4];
assign o[1] = s[0];
assign o[0] = ppts[0][0];
endmodule
// Full adder
module fa (
input wire a,
input wire b,
input wire cin,
output wire s,
output wire cout
);
/*
* Local signals
*/
// wire int_a_xor_b;
// wire int_a_and_b;
// wire int_a_xor_b_and_cin;
/*
* Logic
*/
// Implement a full adder with individual gates.
// assign int_a_xor_b = a ^ b;
// assign int_a_and_b = a & b;
// assign int_a_xor_b_and_cin = int_a_xor_b & cin;
// assign s = int_a_xor_b ^ cin;
// assign cout = int_a_xor_b_and_cin | int_a_and_b;
// Instantiate a full adder cell from the
// standard cell library.
// sky130_fd_sc_hd__fah inst_fa (
// .A (a),
// .B (b),
// .CI (cin),
// .SUM (s),
// .COUT(cout)
// );
// Infer a full adder.
assign {cout, s} = a + b + cin;
endmodule
// Half adder
module ha (
input wire a,
input wire b,
output wire s,
output wire cout
);
/*
* Logic
*/
// Implement a half adder with individual gates.
// assign s = a ^ b;
// assign cout = a & b;
// Instantiate a half adder cell from the
// standard cell library.
// sky130_fd_sc_hd__ha inst_ha (
// .A (a),
// .B (b),
// .SUM (s),
// .COUT(cout)
// );
// Infer a half adder.
assign {cout, s} = a + b;
endmodule
// Carry save adder
module csa #(
parameter NUM_BITS = 4
) (
input wire [NUM_BITS-1:0] a, // Input A
input wire [NUM_BITS-1:0] b, // Input B
input wire [NUM_BITS-1:0] c, // Input C
output wire [NUM_BITS-1:0] p, // Output p (propagate)
output wire [NUM_BITS-1:0] g // Output g (generate)
);
genvar i;
generate
for (i = 0; i < NUM_BITS; i = i + 1) begin
fa fa_i (
.a (a[i]),
.b (b[i]),
.cin (c[i]),
.s (p[i]),
.cout(g[i])
);
end
endgenerate
endmodule
// Ripple carry adder
module rca #(
parameter NUM_BITS = 4
) (
input wire [NUM_BITS-1:0] a,
input wire [NUM_BITS-1:0] b,
output wire [NUM_BITS-1:0] s,
output wire cout
);
/*
* Local signals
*/
// The carry out to carry in signals.
wire [NUM_BITS:0] int_carry;
/*
* Logic
*/
genvar i;
generate
for (i = 0; i < NUM_BITS; i = i + 1) begin
if (i == 0) begin
// The first bits have no carry in,
// so just generate a half adder.
ha ha_0 (
.a (a[i]),
.b (b[i]),
.s (s[i]),
.cout(int_carry[i])
);
end else begin
fa fa_i (
.a (a[i]),
.b (b[i]),
.cin (int_carry[i-1]),
.s (s[i]),
.cout(int_carry[i])
);
end
end
endgenerate
assign cout = int_carry[NUM_BITS-1];
endmodule