Skip to content

Instantly share code, notes, and snippets.

@jrmoserbaltimore
Created January 30, 2022 14:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jrmoserbaltimore/f3fa09edcf1670f332b3bda9b9a7eefd to your computer and use it in GitHub Desktop.
Save jrmoserbaltimore/f3fa09edcf1670f332b3bda9b9a7eefd to your computer and use it in GitHub Desktop.
carry-save adder
from amaranth import *
class CarrySaveAdder(Elaboratable):
"""
A simple carry-save adder.
"""
def __init__(self, width):
self.width = width
# Input ports
self.A = Signal(width)
self.B = Signal(width)
self.C = Signal(width)
self.SubA = Signal(1)
# output ports
self.S = Signal(width, reset_less=True)
self.Cout = Signal(width, reset_less=True)
def elaborate(self, platform):
m = Module()
As = Signal(self.width)
m.d.comb += As.eq(self.A ^ Repl(self.SubA, self.width))
# XOR to produce the partial sum. XOR with SubA to set subtraction
# for i in range(self.width):
# m.d.sync += self.S[i].eq(As[i] ^ self.B[i] ^ self.C[i])
m.d.sync += self.S.eq(As ^ self.B ^ self.C)
# Set the LSB to indicate subtraction
m.d.sync += self.Cout[0].eq(self.SubA)
# Set the carry bits
# for i in range(self.width-1):
# m.d.sync += self.Cout[i+1].eq(
# ((self.A[i] ^ self.SubA) & self.B[i])
# | ((self.A[i] ^ self.SubA) & self.C[i])
# | (self.B[i] & self.C[i])
# )
m.d.sync += self.Cout[1:self.width].eq(((As & self.B) | (As & self.C) | (self.B & self.C)) << 1);
return m
/* Generated by Amaranth Yosys 0.10.0 (PyPI ver 0.10.0.dev46, git sha1 dca8fb54a) */
(* \amaranth.hierarchy = "top" *)
(* top = 1 *)
(* generator = "Amaranth" *)
module top(B, C, SubA, S, Cout, clk, rst, A);
wire [31:0] \$1 ;
wire [31:0] \$10 ;
wire [31:0] \$12 ;
wire [31:0] \$14 ;
wire [31:0] \$16 ;
wire [32:0] \$18 ;
wire [31:0] \$3 ;
wire [31:0] \$5 ;
wire [32:0] \$7 ;
wire [31:0] \$8 ;
input [31:0] A;
wire [31:0] As;
input [31:0] B;
input [31:0] C;
output [31:0] Cout;
reg [31:0] Cout = 32'd0;
wire [31:0] \Cout$next ;
output [31:0] S;
reg [31:0] S = 32'd0;
wire [31:0] \S$next ;
input SubA; // Vivado complains the default_nettype is 'none'
input clk; // and says these can't be of mode input
input rst;
assign \$10 = As & C;
assign \$12 = \$8 | \$10 ;
assign \$14 = B & C;
assign \$16 = \$12 | \$14 ;
assign \$1 = A ^ { SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA, SubA };
assign \$3 = As ^ B;
assign \$5 = \$3 ^ C;
assign \$8 = As & B;
always @(posedge clk)
Cout <= { \$18 [30:0], SubA };
always @(posedge clk)
S <= \$5 ;
assign \$7 = \$18 ;
assign \Cout$next [31:1] = \$18 [30:0];
assign \Cout$next [0] = SubA;
assign \S$next = \$5 ;
assign As = \$1 ;
assign \$18 = { \$16 , 1'h0 };
endmodule
from amaranth.back import verilog
from CarrySaveAdder import CarrySaveAdder
CarrySaveAdder = CarrySaveAdder(32)
with open("CarrySaveAdder.v", "w") as f:
f.write(verilog.convert(CarrySaveAdder, emit_src=False,
ports=[CarrySaveAdder.A,
CarrySaveAdder.B,
CarrySaveAdder.C,
CarrySaveAdder.SubA,
CarrySaveAdder.S,
CarrySaveAdder.Cout
]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment