diff options
author | Tristan Gingold <tgingold@free.fr> | 2016-02-07 17:29:15 +0100 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2016-02-09 20:25:02 +0100 |
commit | fa9fc93606af761b75e783390ed753f0273f24ca (patch) | |
tree | 603db6320a6daa3106aab372f2416f1696d3400c /testsuite/gna/bug037/arith_addw.vhdl | |
parent | 5ddefe0ca2f02afdb7a10717b9feb77a42fbc901 (diff) | |
download | ghdl-fa9fc93606af761b75e783390ed753f0273f24ca.tar.gz ghdl-fa9fc93606af761b75e783390ed753f0273f24ca.tar.bz2 ghdl-fa9fc93606af761b75e783390ed753f0273f24ca.zip |
bug037: add initial testcase.
Diffstat (limited to 'testsuite/gna/bug037/arith_addw.vhdl')
-rw-r--r-- | testsuite/gna/bug037/arith_addw.vhdl | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/testsuite/gna/bug037/arith_addw.vhdl b/testsuite/gna/bug037/arith_addw.vhdl new file mode 100644 index 000000000..1676a3602 --- /dev/null +++ b/testsuite/gna/bug037/arith_addw.vhdl @@ -0,0 +1,351 @@ +-- EMACS settings: -*- tab-width: 2; indent-tabs-mode: t -*-
+-- vim: tabstop=2:shiftwidth=2:noexpandtab
+-- kate: tab-width 2; replace-tabs off; indent-width 2;
+--
+-- =============================================================================
+-- Authors: Thomas B. Preusser
+--
+-- Entity: arith_addw
+--
+-- Description:
+-- ------------------------------------
+-- Implements wide addition providing several options all based
+-- on an adaptation of a carry-select approach.
+--
+-- References:
+-- * Hong Diep Nguyen and Bogdan Pasca and Thomas B. Preusser:
+-- FPGA-Specific Arithmetic Optimizations of Short-Latency Adders,
+-- FPL 2011.
+-- -> ARCH: AAM, CAI, CCA
+-- -> SKIPPING: CCC
+--
+-- * Marcin Rogawski, Kris Gaj and Ekawat Homsirikamol:
+-- A Novel Modular Adder for One Thousand Bits and More
+-- Using Fast Carry Chains of Modern FPGAs, FPL 2014.
+-- -> ARCH: PAI
+-- -> SKIPPING: PPN_KS, PPN_BK
+--
+-- License:
+-- =============================================================================
+-- Copyright 2007-2015 Technische Universitaet Dresden - Germany
+-- Chair for VLSI-Design, Diagnostics and Architecture
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+-- =============================================================================
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+
+library PoC;
+use PoC.utils.all;
+use PoC.arith.all;
+
+
+entity arith_addw is
+ generic (
+ N : positive; -- Operand Width
+ K : positive; -- Block Count
+
+ ARCH : tArch := AAM; -- Architecture
+ BLOCKING : tBlocking := DFLT; -- Blocking Scheme
+ SKIPPING : tSkipping := CCC; -- Carry Skip Scheme
+ P_INCLUSIVE : boolean := false -- Use Inclusive Propagate, i.e. c^1
+ );
+ port (
+ a, b : in std_logic_vector(N-1 downto 0);
+ cin : in std_logic;
+
+ s : out std_logic_vector(N-1 downto 0);
+ cout : out std_logic
+ );
+end entity;
+
+use std.textio.all;
+
+library IEEE;
+use IEEE.numeric_std.all;
+
+
+architecture rtl of arith_addw is
+
+ -- Determine Block Boundaries
+ type tBlocking_vector is array(tArch) of tBlocking;
+ constant DEFAULT_BLOCKING : tBlocking_vector := (AAM => ASC, CAI => DESC, PAI => DESC, CCA => DESC);
+
+ type integer_vector is array(natural range<>) of integer;
+ impure function compute_blocks return integer_vector is
+ variable bs : tBlocking := BLOCKING;
+ variable res : integer_vector(K-1 downto 0);
+
+ variable l : line;
+ begin
+ if bs = DFLT then
+ bs := DEFAULT_BLOCKING(ARCH);
+ end if;
+ case bs is
+ when FIX =>
+ assert N >= K
+ report "Cannot have more blocks than input bits."
+ severity failure;
+ for i in res'range loop
+ res(i) := ((i+1)*N+K/2)/K;
+ end loop;
+
+ when ASC =>
+ assert N-K*(K-1)/2 >= K
+ report "Too few input bits to implement growing block sizes."
+ severity failure;
+ for i in res'range loop
+ res(i) := ((i+1)*(N-K*(K-1)/2)+K/2)/K + (i+1)*i/2;
+ end loop;
+
+ when DESC =>
+ assert N-K*(K-1)/2 >= K
+ report "Too few input bits to implement growing block sizes."
+ severity failure;
+ for i in res'range loop
+ res(i) := ((i+1)*(N+K*(K-1)/2)+K/2)/K - (i+1)*i/2;
+ end loop;
+
+ when others =>
+ report "Unknown blocking scheme: "&tBlocking'image(bs) severity failure;
+
+ end case;
+ --synthesis translate_off
+ write(l, "Implementing "&integer'image(N)&"-bit wide adder: ARCH="&tArch'image(ARCH)&
+ ", BLOCKING="&tBlocking'image(bs)&'[');
+ for i in K-1 downto 1 loop
+ write(l, res(i)-res(i-1));
+ write(l, ',');
+ end loop;
+ write(l, res(0));
+ write(l, "], SKIPPING="&tSkipping'image(SKIPPING));
+ writeline(output, l);
+ --synthesis translate_on
+ return res;
+ end compute_blocks;
+ constant BLOCKS : integer_vector(K-1 downto 0) := compute_blocks;
+
+ signal g : std_logic_vector(K-1 downto 1); -- Block Generate
+ signal p : std_logic_vector(K-1 downto 1); -- Block Propagate
+ signal c : std_logic_vector(K-1 downto 1); -- Block Carry-in
+begin
+
+ -----------------------------------------------------------------------------
+ -- Rightmost Block + Carry Computation Core
+ blkCore: block
+ constant M : positive := BLOCKS(0); -- Rightmost Block Width
+ begin
+
+ -- Carry Computation with Carry Chain
+ genCCC: if SKIPPING = CCC generate
+ signal x, y : unsigned(K+M-2 downto 0);
+ signal z : unsigned(K+M-1 downto 0);
+ begin
+ x <= unsigned(g & a(M-1 downto 0));
+ genExcl: if not P_INCLUSIVE generate
+ y <= unsigned((g or p) & b(M-1 downto 0));
+ -- carry recovery for other blocks
+ c <= std_logic_vector(z(K+M-2 downto M)) xor p;
+ end generate genExcl;
+ genIncl: if P_INCLUSIVE generate
+ y <= unsigned(p & b(M-1 downto 0));
+ -- carry recovery for other blocks
+ c <= std_logic_vector(z(K+M-2 downto M)) xor (p xor g);
+ end generate genIncl;
+ z <= ('0' & x) + y + (0 to 0 => cin);
+
+ -- output of rightmost block
+ s(M-1 downto 0) <= std_logic_vector(z(M-1 downto 0));
+
+ -- carry output
+ cout <= z(z'left);
+ end generate genCCC;
+
+ -- LUT-based Carry Computations
+ genLUT: if SKIPPING /= CCC generate
+ signal z : unsigned(M downto 0);
+ begin
+ -- rightmost block
+ z <= unsigned('0' & a(M-1 downto 0)) + unsigned(b(M-1 downto 0)) + (0 to 0 => cin);
+ s(M-1 downto 0) <= std_logic_vector(z(M-1 downto 0));
+
+ -- Plain linear LUT-based Carry Forwarding
+ genPlain: if SKIPPING = PLAIN generate
+ signal t : std_logic_vector(K downto 1);
+ begin
+ -- carry forwarding
+ t(1) <= z(M);
+ t(K downto 2) <= g or (p and c);
+ c <= t(K-1 downto 1);
+ cout <= t(K);
+ end generate genPlain;
+
+ -- Kogge-Stone Parallel Prefix Network
+ genPPN_KS: if SKIPPING = PPN_KS generate
+ subtype tLevel is std_logic_vector(K-1 downto 0);
+ type tLevels is array(natural range<>) of tLevel;
+ constant LEVELS : positive := log2ceil(K);
+ signal pp, gg : tLevels(0 to LEVELS);
+ begin
+ -- carry forwarding
+ pp(0) <= p & 'X';
+ gg(0) <= g & z(M);
+ genLevels: for i in 1 to LEVELS generate
+ constant D : positive := 2**(i-1);
+ begin
+ pp(i) <= (pp(i-1)(K-1 downto D) and pp(i-1)(K-D-1 downto 0)) & pp(i-1)(D-1 downto 0);
+ gg(i) <= (gg(i-1)(K-1 downto D) or (pp(i-1)(K-1 downto D) and gg(i-1)(K-D-1 downto 0))) & gg(i-1)(D-1 downto 0);
+ end generate genLevels;
+ c <= gg(LEVELS)(K-2 downto 0);
+ cout <= gg(LEVELS)(K-1);
+ end generate genPPN_KS;
+
+ -- Brent-Kung Parallel Prefix Network
+ genPPN_BK: if SKIPPING = PPN_BK generate
+ subtype tLevel is std_logic_vector(K-1 downto 0);
+ type tLevels is array(natural range<>) of tLevel;
+ constant LEVELS : positive := log2ceil(K);
+ signal pp, gg : tLevels(0 to 2*LEVELS-1);
+ begin
+ -- carry forwarding
+ pp(0) <= p & 'X';
+ gg(0) <= g & z(M);
+ genMerge: for i in 1 to LEVELS generate
+ constant D : positive := 2**(i-1);
+ begin
+ genBits: for j in 0 to K-1 generate
+ genOp: if j mod (2*D) = 2*D-1 generate
+ gg(i)(j) <= (pp(i-1)(j) and gg(i-1)(j-D)) or gg(i-1)(j);
+ pp(i)(j) <= pp(i-1)(j) and pp(i-1)(j-D);
+ end generate;
+ genCp: if j mod (2*D) /= 2*D-1 generate
+ gg(i)(j) <= gg(i-1)(j);
+ pp(i)(j) <= pp(i-1)(j);
+ end generate;
+ end generate;
+ end generate genMerge;
+ genSpread: for i in LEVELS+1 to 2*LEVELS-1 generate
+ constant D : positive := 2**(2*LEVELS-i-1);
+ begin
+ genBits: for j in 0 to K-1 generate
+ genOp: if j > D and (j+1) mod (2*D) = D generate
+ gg(i)(j) <= (pp(i-1)(j) and gg(i-1)(j-D)) or gg(i-1)(j);
+ pp(i)(j) <= pp(i-1)(j) and pp(i-1)(j-D);
+ end generate;
+ genCp: if j <= D or (j+1) mod (2*D) /= D generate
+ gg(i)(j) <= gg(i-1)(j);
+ pp(i)(j) <= pp(i-1)(j);
+ end generate;
+ end generate;
+ end generate genSpread;
+ c <= gg(gg'high)(K-2 downto 0);
+ cout <= gg(gg'high)(K-1);
+ end generate genPPN_BK;
+
+ end generate genLUT;
+
+ end block blkCore;
+
+ -----------------------------------------------------------------------------
+ -- Implement Carry-Select Variant
+ --
+ -- all but rightmost block, implementation architecture selected by ARCH
+ genBlocks: for i in 1 to K-1 generate
+ -- Covered Index Range
+ constant LO : positive := BLOCKS(i-1); -- Low Bit Index
+ constant HI : positive := BLOCKS(i)-1; -- High Bit Index
+
+ -- Internal Block Interface
+ signal aa : unsigned(HI downto LO);
+ signal bb : unsigned(HI downto LO);
+ signal ss : unsigned(HI downto LO);
+ begin
+
+ -- Connect common block interface
+ aa <= unsigned(a(HI downto LO));
+ bb <= unsigned(b(HI downto LO));
+ s(HI downto LO) <= std_logic_vector(ss);
+
+ -- ARCH-specific Implementations
+
+ --Add-Add-Multiplex
+ genAAM: if ARCH = AAM generate
+ signal s0 : unsigned(HI+1 downto LO); -- Block Sum (cin=0)
+ signal s1 : unsigned(HI+1 downto LO); -- Block Sum (cin=1)
+ begin
+ s0 <= ('0' & aa) + bb;
+ s1 <= ('0' & aa) + bb + 1;
+ g(i) <= s0(HI+1);
+ genExcl: if not P_INCLUSIVE generate
+ p(i) <= s1(HI+1) xor s0(HI+1);
+ end generate genExcl;
+ genIncl: if P_INCLUSIVE generate
+ p(i) <= s1(HI+1);
+ end generate genIncl;
+
+ ss <= s0(HI downto LO) when c(i) = '0' else s1(HI downto LO);
+ end generate genAAM;
+
+ -- Compare-Add-Increment
+ genCAI: if ARCH = CAI generate
+ signal s0 : unsigned(HI+1 downto LO); -- Block Sum (cin=0)
+ begin
+ s0 <= ('0' & aa) + bb;
+ g(i) <= s0(HI+1);
+ genExcl: if not P_INCLUSIVE generate
+ p(i) <= 'X' when Is_X(std_logic_vector(aa&bb)) else
+ '1' when (aa xor bb) = (aa'range => '1') else '0';
+ end generate genExcl;
+ genIncl: if P_INCLUSIVE generate
+ p(i) <= 'X' when Is_X(std_logic_vector(aa&bb)) else
+ '1' when aa >= not bb else '0';
+ end generate genIncl;
+ ss <= s0(HI downto LO) when c(i) = '0' else s0(HI downto LO)+1;
+ end generate genCAI;
+
+ -- Propagate-Add-Increment
+ genPAI: if ARCH = PAI generate
+ signal s0 : unsigned(HI+1 downto LO); -- Block Sum (cin=0)
+ begin
+ s0 <= ('0' & aa) + bb;
+ g(i) <= s0(HI+1);
+ genExcl: if not P_INCLUSIVE generate
+ p(i) <= 'X' when Is_X(std_logic_vector(s0)) else
+ '1' when s0(HI downto LO) = (HI downto LO => '1') else '0';
+ end generate genExcl;
+ genIncl: if P_INCLUSIVE generate
+ p(i) <= 'X' when Is_X(std_logic_vector(s0)) else
+ '1' when s0(HI downto LO) = (HI downto LO => '1') else g(i);
+ end generate genIncl;
+ ss <= s0(HI downto LO) when c(i) = '0' else s0(HI downto LO)+1;
+ end generate genPAI;
+
+ -- Compare-Compare-Add
+ genCCA: if ARCH = CCA generate
+ g(i) <= 'X' when Is_X(std_logic_vector(aa&bb)) else
+ '1' when aa > not bb else '0';
+ genExcl: if not P_INCLUSIVE generate
+ p(i) <= 'X' when Is_X(std_logic_vector(aa&bb)) else
+ '1' when (aa xor bb) = (aa'range => '1') else '0';
+ end generate genExcl;
+ genIncl: if P_INCLUSIVE generate
+ p(i) <= 'X' when Is_X(std_logic_vector(aa&bb)) else
+ '1' when aa >= not bb else '0';
+ end generate genIncl;
+ ss <= aa + bb + (0 to 0 => c(i));
+ end generate genCCA;
+
+ end generate genBlocks;
+
+end architecture;
|