`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 |