I have to write 4 bit counter in AHDL.
I haven't had contact with AHDL before.
The task is:
Please implement a 4 digit counter (BCD counting) in the circuit
Cyclone IV EP3CE115F29C7 FPGA being the heart of the commissioning
system De2-115 from terasic.
The counter should work with a 1Hz clock to be able to observe the change of states
display in development kit.
The outputs of the seven-segment decoders should be connected to the appropriate
FPGA pins to enable display control.
The final program should allow FPGA programming and observations
counter counting.
I have something similar in VHDL. Can you guys can help me how to rewrite this to altera?
Is there any converter maybe? I saw something like this but only from AHDL to VHDL.
I will be grateful for all the tips.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity bcd_counter is
generic (
width : integer := 4
);
port (
clk : in std_logic;
enable : in std_logic;
reset : in std_logic;
output : out std_logic_vector(width - 1 downto 0)
);
end entity bcd_counter;
architecture behaviour of bcd_counter is
signal state : unsigned (2 ** width - 1 downto 0);
begin
output <= std_logic_vector(state);
count : process(clk, reset, enable)
begin
if(reset = '0') then
state <= (others=> '0');
elsif(rising_edge(clk) and enable = '1') then
state <= state + 1;
end if;
end process count;
end architecture behaviour;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity counter_logic is
generic (
digits : integer := 4
);
port (
clk : in std_logic;
reset : in std_logic;
output : out std_logic_vector (4 * digits - 1 downto 0)
);
end entity counter_logic;
architecture behaviour of counter_logic is
constant digitWidth : integer := 4;
signal state : std_logic_vector(digitWidth * digits -1 downto 0);
signal resetLines : std_logic_vector(digits - 1 downto 0);
signal enableLines : std_logic_vector(digits - 1 downto 0);
component bcd_counter is
generic (
width : integer := 4
);
port (
clk : in std_logic;
enable : in std_logic;
reset : in std_logic;
output : out std_logic_vector(width - 1 downto 0)
);
end component;
begin
counters: for i in digits - 1 downto 0 generate
nthCounter : bcd_counter
generic map (width => digitWidth)
port map (
clk => clk,
enable => enableLines(i),
reset => resetLines(i),
--przypisanie wyjść liczników do linii
output => state((i + 1) * digitWidth - 1 downto i * digitWidth)
);
resetLines(i) <= (not state(i * digitWidth) and state(i * digitWidth + 1) and state(i * digitWidth + 2) and not state(i * digitWidth + 3)) or reset;
end generate counters;
--TODO: add if generate for case of single digit counter
enableLinesCondition: if digitWidth > 1 generate
lines: for i in digits - 2 downto 0 generate
enableLines(i + 1) <= not state(i * digitWidth) and state(i * digitWidth + 1) and state(i * digitWidth + 2) and not state(i * digitWidth + 3);
end generate lines;
end generate enableLinesCondition;
enableLines(0) <= '1';
output <= state;
end architecture behaviour;
Related
I'm trying to do a circuit consisting of a 2 to 1 multiplexer (8-bit buses), an 8-bit register and an 8-bit adder. These components are all tested and work as expected.
The thing is: if I try to send the output of the Adder to one of the inputs of the
multiplexer (as seen in the image by the discontinued line), the simulation will stop rather suddenly. If I don't do that and just let ain do its thing, everything will run just as it should, but I do need the output of the adder to be the one inputted to the multiplexer.
The simulation is the following:
The code is:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Sumitas is
port (m : in STD_LOGIC;
clk : in STD_LOGIC;
ain : in STD_LOGIC_VECTOR (7 downto 0);
Add : out STD_LOGIC_VECTOR (7 downto 0));
end Sumitas;
architecture rtl of Sumitas is
component Adder8bit
port (a, b : in STD_LOGIC_VECTOR (7 downto 0);
Cin : in STD_LOGIC;
S : out STD_LOGIC_VECTOR (7 downto 0);
Cout : out STD_LOGIC);
end component;
component GenericReg
generic (DataWidth : integer := 8);
port (en : in STD_LOGIC;
dataIn : in STD_LOGIC_VECTOR (DataWidth - 1 downto 0);
dataOut : out STD_LOGIC_VECTOR (DataWidth - 1 downto 0));
end component;
component GenericMux2_1
generic (DataWidth : integer := 8);
port (a, b : in STD_LOGIC_VECTOR (DataWidth - 1 downto 0);
Z : in STD_LOGIC;
S : out STD_LOGIC_VECTOR (DataWidth - 1 downto 0));
end component;
constant DW : integer := 8;
signal AddOut_s, MuxOut_s : STD_LOGIC_VECTOR (7 downto 0);
signal PCOut_s : STD_LOGIC_VECTOR (7 downto 0);
begin
m0 : GenericMux2_1
generic map (DataWidth => DW)
port map (a => "00000000",
b => AddOut_s,
Z => m,
S => MuxOut_s);
PC : GenericReg
generic map (DataWidth => DW)
port map (en => clk,
dataIn => MuxOut_s,
dataOut => PCOut_s);
Add0 : Adder8bit
port map (a => "00000001",
b => PCOut_s,
Cin => '0',
S => AddOut_s,
Cout => open);
Add <= AddOut_s;
end rtl;
and the testbench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity bm_Sumitas is
end bm_Sumitas;
architecture benchmark of bm_Sumitas is
component Sumitas
port (m : in STD_LOGIC;
clk : in STD_LOGIC;
ain : in STD_LOGIC_VECTOR (7 downto 0);
Add : out STD_LOGIC_VECTOR (7 downto 0));
end component;
signal clk_s, m_s : STD_LOGIC;
signal Add_s, ain_s : STD_LOGIC_VECTOR (7 downto 0);
constant T : time := 2 ns;
begin
benchmark : Sumitas
port map (m => m_s,
clk => clk_s,
ain => ain_s,
Add => Add_s);
clk_proc: process
begin
clk_s <= '0';
wait for T/2;
clk_s <= '1';
wait for T/2;
end process;
bm_proc : process
begin
m_s <= '0';
wait for 10 ns;
m_s <= '1';
wait for 100 ns;
end process;
ains_proc : process
begin
ain_s <= "00001111";
for I in 0 to 250 loop
ain_s <= STD_LOGIC_VECTOR(TO_UNSIGNED(I, ain_s'length));
wait for T;
end loop;
end process;
end benchmark;
How can I do the thing I want? I'm ultimately trying to simulate a computer I designed. I have every component already designed and I'm coupling them together.
Constructing a Minimal, Complete, and Verifiable example requires filling in the missing components:
library ieee;
use ieee.std_logic_1164.all;
entity Adder8bit is
port (a, b : in STD_LOGIC_VECTOR (7 downto 0);
Cin : in STD_LOGIC;
S : out STD_LOGIC_VECTOR (7 downto 0);
Cout : out STD_LOGIC);
end entity;
architecture foo of adder8bit is
signal sum: std_logic_vector (9 downto 0);
use ieee.numeric_std.all;
begin
sum <= std_logic_vector ( unsigned ('0' & a & cin) +
unsigned ('0' & b & cin ));
s <= sum(8 downto 1);
cout <= sum(9);
end architecture;
library ieee;
use ieee.std_logic_1164.all;
entity GenericReg is
generic (DataWidth : integer := 8);
port (en : in STD_LOGIC;
dataIn : in STD_LOGIC_VECTOR (DataWidth - 1 downto 0);
dataOut : out STD_LOGIC_VECTOR (DataWidth - 1 downto 0));
end entity;
architecture fum of genericreg is
begin
dataout <= datain when en = '1';
end architecture;
with behavioral model substitutes.
(It's not that much work, copy the component declarations paste them, substitute entity for component and add the reserved word is, followed by simple behaviors in architectures.)
It reproduces the symptom you displayed in your simulation waveform:
You can see the essential point of failure occurs when the register enable (ms_s) goes high.
The simulator will report operation on it's STD_OUTPUT:
%: make wave
/usr/local/bin/ghdl -a bm_sumitas.vhdl
/usr/local/bin/ghdl -e bm_sumitas
/usr/local/bin/ghdl -r bm_sumitas --wave=bm_sumitas.ghw --stop-time=40ns
./bm_sumitas:info: simulation stopped #11ns by --stop-delta=5000
/usr/bin/open bm_sumitas.gtkw
%:
Note the simulation stopped at 11 ns because of a process executing repeatedly in delta cycles (simulation time doesn't advance).
This is caused by a gated relaxation oscillator formed by the enabled latch, delay (a delta cycle) and having at least one element of latch input inverting each delta cycle.
The particular simulator used has a delta cycle limitation, which will quit simulation when 5,000 delta cycles occur without simulation time advancing.
The genericreg kept generating events with no time delay in assignment, without an after clause in the waveform, after 0 fs (resolution limit) is assumed.
Essentially when the enable is true the signal will have at least one element change every simulation cycle due to the increment, and assigns the signal a new value for at least one element each simulation cycle without allowing the advancement of simulation time by not going quiescent.
You could note the simulator you used should have produced a 'console' output with a similar message if it were capable (and enabled).
So how it this problem cured? The easiest way is to use a register (not latch) sensitive to a clock edge:
architecture foo of genericreg is
begin
dataout <= datain when rising_edge(en);
end architecture;
Which gives us the full simulation:
7.1 - Consider an Arithmetic Circuit that can perform four operations: a+b, a-b, a+1 and a-1, where a and b are 16-bit Unsigned Numbers and the desired operation is specified by a 2-bit Control Signal, ctrl.
Is it possible to design this circuit just with one adder without using sequential logic.
I designed this circuit with 2's complementary logic but i cannot add logic (a + (not b) + 1) just one adder without memory components
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Ex_7_1_b is
generic( BUS_WIDTH : integer := 16 );
port ( a : in STD_LOGIC_VECTOR (BUS_WIDTH - 1 downto 0);
b : in STD_LOGIC_VECTOR (BUS_WIDTH - 1 downto 0);
ctrl : in STD_LOGIC_VECTOR (1 downto 0);
y : out STD_LOGIC_VECTOR (BUS_WIDTH - 1 downto 0)
);
end Ex_7_1_b;
architecture Behavioral of Ex_7_1_b is
signal adder : unsigned(BUS_WIDTH - 1 downto 0);
signal mux_sign : unsigned(BUS_WIDTH - 1 downto 0);
signal mux_inp_sel : unsigned(BUS_WIDTH - 1 downto 0);
signal mux_val : unsigned(BUS_WIDTH - 1 downto 0);
signal result : unsigned(BUS_WIDTH - 1 downto 0);
begin
mux_val <= to_unsigned(0, mux_val'length) when ctrl(1) = '1' else to_unsigned(1, mux_val'length);
mux_inp_sel <= mux_val when ctrl(0) = '1' else unsigned(b);
mux_sign <= not (mux_inp_sel) when ctrl(1) = '1' else mux_inp_sel;
result <= unsigned(a) + mux_sign;
y <= std_logic_vector(result);
end Behavioral;
I designed this circuit with Renaud Pacalet contribute.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Ex_7_1_b is
generic( g_BUS_WIDTH : integer := 16 );
port (
i_a : in std_logic_vector (g_BUS_WIDTH - 1 downto 0);
i_b : in std_logic_vector (g_BUS_WIDTH - 1 downto 0);
i_ctrl : in std_logic_vector (1 downto 0);
o_y : out std_logic_vector (g_BUS_WIDTH - 1 downto 0)
);
end Ex_7_1_b;
architecture RTL of Ex_7_1_b is
signal r_A_Ext, r_B_Ext : unsigned(g_BUS_WIDTH downto 0);
signal r_Carry_In : std_logic;
signal r_Adder : unsigned(g_BUS_WIDTH - 1 downto 0);
signal w_Mux_Inv : unsigned(g_BUS_WIDTH - 1 downto 0);
signal w_Mux_Sel : unsigned(g_BUS_WIDTH - 1 downto 0);
signal r_Result : unsigned(g_BUS_WIDTH downto 0);
begin
r_A_Ext <= unsigned(i_a & '1');
w_Mux_Sel <= to_unsigned(1, w_Mux_Sel'length) when i_ctrl(1) = '1' else unsigned(i_b);
w_Mux_Inv <= not (w_Mux_Sel) when i_ctrl(0) = '1' else w_Mux_Sel;
r_Carry_In <= '1' when i_ctrl(0) = '1' else '0';
r_B_Ext <= w_Mux_Inv & r_Carry_In;
r_Result <= r_A_Ext + r_B_Ext;
o_y <= std_logic_vector(r_Result(g_BUS_WIDTH downto 1));
end RTL;
The solution you found yourself is fine but it uses a 17-bits adder instead of a 16-bits one. With smart enough synthesizers it should not make any difference. Just for completeness here is another, 16-bits (and slightly simpler), solution:
architecture RTL of Ex_7_1_b is
signal x, y0, y1: unsigned(g_BUS_WIDTH - 1 downto 0);
begin
x <= unsigned(i_a);
y0 <= unsigned(i_b) when i_ctrl(1) = '0' else x"0001";
y1 <= not y0 when i_ctrl(0) = '1' else y0;
o_y <= std_logic_vector(x + y1 + i_ctrl(0));
end architecture RTL;
Note: this works only in VHDL 2008 where the addition of an unsigned and a std_logic is defined. If you must use an older version of the VHDL standard use the following, instead:
architecture RTL of Ex_7_1_b is
signal x, y0, y1: unsigned(g_BUS_WIDTH - 1 downto 0);
signal c: natural range 0 to 1;
begin
x <= unsigned(i_a);
y0 <= unsigned(i_b) when i_ctrl(1) = '0' else x"0001";
y1 <= not y0 when i_ctrl(0) = '1' else y0;
c <= 1 when i_ctrl(0) = '1' else 0;
o_y <= std_logic_vector(x + y1 + c);
end architecture RTL;
Is it possible to create an entity with a port that is an array of std_logic_vectors, with both the size of the array and the std_logic_vector coming from generics? Ie. is it possible to create eg. a bus multiplexer with both the bus width and bus count configurable?
entity bus_multiplexer is
generic (bus_width : positive := 8;
sel_width : positive := 2);
port ( i : in array(integer range 2**sel_width - 1 downto 0) of std_logic_vector(bus_width - 1 downto 0);
sel : in std_logic_vector(sel_width - 1 downto 0);
o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer;
architecture dataflow of bus_multiplexer is
begin
o <= i(to_integer(unsigned(sel)));
end dataflow;
The above doesn't seem to work because the array type needs to be defined separately.
Defining the type before the port also does not work, as then it expects the entity definition to end after it. Defining it after the port definition doesn't work since it'd be used before that. Defining it in a package doesn't work because the type definition doesn't seem to like having an unconstrained range in the "base type".
Is it possible to somehow do this in VHDL-93? (What about VHDL-2008?)
Defining the type as array(natural range <>, natural range <>) of std_logic in the package works - as in the port definition doesn't give an error - but actually using it if it's defined that way seems to be quite unwieldy.
Is there some sane way to use it like this? Is there some simple way to map N separate std_logic_vectors to a port defined like that, and likewise for the actual output logic?
I tried the original and o <= i(to_integer(unsigned(sel)), bus_width - 1 downto 0), but neither worked. I know I could do it one bit at a time, but I'd prefer something simpler. And while the bit-by-bit -approach might be okay for the internal implementation, I certainly wouldn't want to have to do that for the port mapping every time I use the component...
Is there some sane(-ish) way to do this?
(Addendum: I know there are some similar questions, but most of them don't deal with the case of both ranges coming from generics, and were solved using a type definition in a package. The one that did talk about two generic dimensions apparently didn't need the input to come from distinct std_logic_vectors and ended up using the "2d-array of std_logic" method, which doesn't work for me (at least without further clarification about how to use it without losing one's sanity))
This works with VHDL2008:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package bus_multiplexer_pkg is
type bus_array is array(natural range <>) of std_logic_vector;
end package;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.bus_multiplexer_pkg.all;
entity bus_multiplexer is
generic (bus_width : positive := 8;
sel_width : positive := 2);
port ( i : in bus_array(2**sel_width - 1 downto 0)(bus_width - 1 downto 0);
sel : in std_logic_vector(sel_width - 1 downto 0);
o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer;
architecture dataflow of bus_multiplexer is
begin
o <= i(to_integer(unsigned(sel)));
end dataflow;
And it can be used like this:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.all;
use work.bus_multiplexer_pkg.all;
entity bus_multiplexer_4 is
generic (bus_width : positive := 8);
port ( bus0, bus1, bus2, bus3 : in std_logic_vector(bus_width - 1 downto 0);
sel : in std_logic_vector(1 downto 0);
o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer_4;
architecture structural of bus_multiplexer_4 is
signal i : bus_array(3 downto 0)(bus_width - 1 downto 0);
begin
i <= (0 => bus0, 1 => bus1, 2 => bus2, 3 => bus3);
u: entity bus_multiplexer generic map (bus_width => bus_width, sel_width => 2) port map (i => i, sel => sel, o => o);
end;
It doesn't work with VHDL93, however, because you can't leave the std_logic_vector unconstrained in the type definition, as stated in the question.
Unfortunately, I don't know if there's any way to do anything similar without 2d arrays with VHDL93.
Edit: Paebbels's answer shows how to do this in VHDL93 by using 2d arrays, with custom procedures to make it manageable. Since his example is quite big, here's also a minimal example of the same concept:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package bus_multiplexer_pkg is
type bus_array is array(natural range <>, natural range <>) of std_logic;
procedure slm_row_from_slv(signal slm : out bus_array; constant row : natural; signal slv : in std_logic_vector);
procedure slv_from_slm_row(signal slv : out std_logic_vector; signal slm : in bus_array; constant row : natural);
end package;
package body bus_multiplexer_pkg is
procedure slm_row_from_slv(signal slm : out bus_array; constant row : natural; signal slv : in std_logic_vector) is
begin
for i in slv'range loop
slm(row, i) <= slv(i);
end loop;
end procedure;
procedure slv_from_slm_row(signal slv : out std_logic_vector; signal slm : in bus_array; constant row : natural) is
begin
for i in slv'range loop
slv(i) <= slm(row, i);
end loop;
end procedure;
end package body;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.bus_multiplexer_pkg.all;
entity bus_multiplexer is
generic (bus_width : positive := 8;
sel_width : positive := 2);
port ( i : in bus_array(2**sel_width - 1 downto 0, bus_width - 1 downto 0);
sel : in std_logic_vector(sel_width - 1 downto 0);
o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer;
architecture dataflow of bus_multiplexer is
begin
slv_from_slm_row(o, i, to_integer(unsigned(sel)));
end dataflow;
And it can be used like this:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.all;
use work.bus_multiplexer_pkg.all;
entity bus_multiplexer_4 is
generic (bus_width : positive := 8);
port ( bus0, bus1, bus2, bus3 : in std_logic_vector(bus_width - 1 downto 0);
sel : in std_logic_vector(1 downto 0);
o : out std_logic_vector(bus_width - 1 downto 0));
end bus_multiplexer_4;
architecture structural of bus_multiplexer_4 is
signal i : bus_array(3 downto 0, bus_width - 1 downto 0);
begin
slm_row_from_slv(i, 0, bus0);
slm_row_from_slv(i, 1, bus1);
slm_row_from_slv(i, 2, bus2);
slm_row_from_slv(i, 3, bus3);
u: entity bus_multiplexer generic map (bus_width => bus_width, sel_width => 2) port map (i => i, sel => sel, o => o);
end;
Yes, it's possible.
Your attempt with a two dimensional array is good, because nested 1 dimensional array need a fixed size in the inner dimensions. So the way to handle such a 2D array is to write some functions and procedures, which convert the 2D array into nested 1D vectors.
I answered a similar question here:
- Fill one row in 2D array outside the process (VHDL) and
- Creating a generic array whose elements have increasing width in VHDL
Here is my vectors package.
And here is an example of an multiplexer for a FIFO interface, which is variable in data width as well as in input count. It uses a round robin arbiter to select the inputs.
Entity 'PoC.bus.Stream.Mux':
-- 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: Patrick Lehmann
--
-- 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;
use IEEE.NUMERIC_STD.all;
library PoC;
use PoC.config.all;
use PoC.utils.all;
use PoC.vectors.all;
entity Stream_Mux is
generic (
PORTS : POSITIVE := 2;
DATA_BITS : POSITIVE := 8;
META_BITS : NATURAL := 8;
META_REV_BITS : NATURAL := 2
);
port (
Clock : IN STD_LOGIC;
Reset : IN STD_LOGIC;
-- IN Ports
In_Valid : IN STD_LOGIC_VECTOR(PORTS - 1 downto 0);
In_Data : IN T_SLM(PORTS - 1 downto 0, DATA_BITS - 1 downto 0);
In_Meta : IN T_SLM(PORTS - 1 downto 0, META_BITS - 1 downto 0);
In_Meta_rev : OUT T_SLM(PORTS - 1 downto 0, META_REV_BITS - 1 downto 0);
In_SOF : IN STD_LOGIC_VECTOR(PORTS - 1 downto 0);
In_EOF : IN STD_LOGIC_VECTOR(PORTS - 1 downto 0);
In_Ack : OUT STD_LOGIC_VECTOR(PORTS - 1 downto 0);
-- OUT Port
Out_Valid : OUT STD_LOGIC;
Out_Data : OUT STD_LOGIC_VECTOR(DATA_BITS - 1 downto 0);
Out_Meta : OUT STD_LOGIC_VECTOR(META_BITS - 1 downto 0);
Out_Meta_rev : IN STD_LOGIC_VECTOR(META_REV_BITS - 1 downto 0);
Out_SOF : OUT STD_LOGIC;
Out_EOF : OUT STD_LOGIC;
Out_Ack : IN STD_LOGIC
);
end;
architecture rtl OF Stream_Mux is
attribute KEEP : BOOLEAN;
attribute FSM_ENCODING : STRING;
subtype T_CHANNEL_INDEX is NATURAL range 0 to PORTS - 1;
type T_STATE is (ST_IDLE, ST_DATAFLOW);
signal State : T_STATE := ST_IDLE;
signal NextState : T_STATE;
signal FSM_Dataflow_en : STD_LOGIC;
signal RequestVector : STD_LOGIC_VECTOR(PORTS - 1 downto 0);
signal RequestWithSelf : STD_LOGIC;
signal RequestWithoutSelf : STD_LOGIC;
signal RequestLeft : UNSIGNED(PORTS - 1 downto 0);
signal SelectLeft : UNSIGNED(PORTS - 1 downto 0);
signal SelectRight : UNSIGNED(PORTS - 1 downto 0);
signal ChannelPointer_en : STD_LOGIC;
signal ChannelPointer : STD_LOGIC_VECTOR(PORTS - 1 downto 0);
signal ChannelPointer_d : STD_LOGIC_VECTOR(PORTS - 1 downto 0) := to_slv(2 ** (PORTS - 1), PORTS);
signal ChannelPointer_nxt : STD_LOGIC_VECTOR(PORTS - 1 downto 0);
signal ChannelPointer_bin : UNSIGNED(log2ceilnz(PORTS) - 1 downto 0);
signal idx : T_CHANNEL_INDEX;
signal Out_EOF_i : STD_LOGIC;
begin
RequestVector <= In_Valid AND In_SOF;
RequestWithSelf <= slv_or(RequestVector);
RequestWithoutSelf <= slv_or(RequestVector AND NOT ChannelPointer_d);
process(Clock)
begin
if rising_edge(Clock) then
if (Reset = '1') then
State <= ST_IDLE;
else
State <= NextState;
end if;
end if;
end process;
process(State, RequestWithSelf, RequestWithoutSelf, Out_Ack, Out_EOF_i, ChannelPointer_d, ChannelPointer_nxt)
begin
NextState <= State;
FSM_Dataflow_en <= '0';
ChannelPointer_en <= '0';
ChannelPointer <= ChannelPointer_d;
case State is
when ST_IDLE =>
if (RequestWithSelf = '1') then
ChannelPointer_en <= '1';
NextState <= ST_DATAFLOW;
end if;
when ST_DATAFLOW =>
FSM_Dataflow_en <= '1';
if ((Out_Ack AND Out_EOF_i) = '1') then
if (RequestWithoutSelf = '0') then
NextState <= ST_IDLE;
else
ChannelPointer_en <= '1';
end if;
end if;
end case;
end process;
process(Clock)
begin
if rising_edge(Clock) then
if (Reset = '1') then
ChannelPointer_d <= to_slv(2 ** (PORTS - 1), PORTS);
elsif (ChannelPointer_en = '1') then
ChannelPointer_d <= ChannelPointer_nxt;
end if;
end if;
end process;
RequestLeft <= (NOT ((unsigned(ChannelPointer_d) - 1) OR unsigned(ChannelPointer_d))) AND unsigned(RequestVector);
SelectLeft <= (unsigned(NOT RequestLeft) + 1) AND RequestLeft;
SelectRight <= (unsigned(NOT RequestVector) + 1) AND unsigned(RequestVector);
ChannelPointer_nxt <= std_logic_vector(ite((RequestLeft = (RequestLeft'range => '0')), SelectRight, SelectLeft));
ChannelPointer_bin <= onehot2bin(ChannelPointer);
idx <= to_integer(ChannelPointer_bin);
Out_Data <= get_row(In_Data, idx);
Out_Meta <= get_row(In_Meta, idx);
Out_SOF <= In_SOF(to_integer(ChannelPointer_bin));
Out_EOF_i <= In_EOF(to_integer(ChannelPointer_bin));
Out_Valid <= In_Valid(to_integer(ChannelPointer_bin)) and FSM_Dataflow_en;
Out_EOF <= Out_EOF_i;
In_Ack <= (In_Ack 'range => (Out_Ack and FSM_Dataflow_en)) AND ChannelPointer;
genMetaReverse_0 : if (META_REV_BITS = 0) generate
In_Meta_rev <= (others => (others => '0'));
end generate;
genMetaReverse_1 : if (META_REV_BITS > 0) generate
signal Temp_Meta_rev : T_SLM(PORTS - 1 downto 0, META_REV_BITS - 1 downto 0) := (others => (others => 'Z'));
begin
genAssign : for i in 0 to PORTS - 1 generate
signal row : STD_LOGIC_VECTOR(META_REV_BITS - 1 downto 0);
begin
row <= Out_Meta_rev AND (row'range => ChannelPointer(I));
assign_row(Temp_Meta_rev, row, i);
end generate;
In_Meta_rev <= Temp_Meta_rev;
end generate;
end architecture;
Hi I want to implement an 128 bits hierarchical carry look ahead adder but I don't know how to use levels in my implementation, in fact i don't know how to write the code. I write my code for 16 bits adder but i should use 4-bits blocks and combine them in levels. I almost know that I need 32 numbers of 4-bits blocks in level 1 and 8 numbers in level 2 and so on. However my code should be run for 128 to 256 bits operands but i don't know how to do this. please help me
if you already have 4bit adder, you should implement the hierarchical adder
with for generate statement like this:
library ieee;
use ieee.std_logic_1164.all;
entity carry_leveled is
generic(c_word_length : integer := 128;
c_adder_count : integer := c_word_length / 4 --count of adder entities to generate
);
port(
clk_i : in std_logic;
rst_i : in std_logic;
x_i : in std_logic_vector(c_word_length - 1 downto 0);
y_i : in std_logic_vector(c_word_length - 1 downto 0);
sum_o : out std_logic_vector(c_word_length - 1 downto 0)
);
end entity carry_leveled;
architecture RTL of carry_leveled is
component carry_lookahead_adder
port(
clk_i : in std_logic;
rst_i : in std_logic;
x_i : in std_logic_vector(c_word_length - 1 downto 0);
y_i : in std_logic_vector(c_word_length - 1 downto 0);
carry_i : in std_logic;
carry_out : out std_logic;
sum_o : out std_logic_vector(3 downto 0)
);
end component;
signal carry_vector : std_logic_vector(c_adder_count - 1 downto 0);
signal sum : std_logic_vector(c_word_length - 1 downto 0);
begin
sum_o <= sum;
carry_lookahead_adder_inst_0 : component carry_lookahead_adder
port map(clk_i => clk_i,
rst_i => rst_i,
x_i => x_i(c_adder_count - 1 downto 0),
y_i => y_i(c_adder_count - 1 downto 0),
carry_i => '0',
carry_out => carry_vector(0),
sum_o => sum(c_adder_count - 1 downto 0));
carry_look_adder_generate : for i in 1 to c_adder_count - 1 generate
carry_lookahead_adder_inst_i : component carry_lookahead_adder
port map(clk_i => clk_i,
rst_i => rst_i,
x_i => x_i((i + 1) * c_adder_count - 1 downto i * c_adder_count),
y_i => y_i((i + 1) * c_adder_count - 1 downto i * c_adder_count),
carry_i => carry_vector(i - 1),
carry_out => carry_vector(i),
sum_o => sum((i + 1) * c_adder_count - 1 downto i * c_adder_count)
);
end generate carry_look_adder_generate;
end architecture RTL;
hope i could help you
it is easier to implement in behavioral modeling language, see the following tutorial for 16 bit and just replace the numbers for 128 bits
16 bit carry look ahead adder vhdl code
I'm looking for the correct syntax to build a generic line delay package using generics and for loops in a process. I understand that for loops when used with generate are for concurrent statements, but surely there must be a way to build it.
For example:
entity Delay_Line is
Generic (
CLK_DELAYS : integer := 10);
Port (
CLK : in STD_LOGIC;
i_Din : in STD_LOGIC;
o_Q : out STD_LOGIC;
o_Qnot : out STD_LOGIC);
end Delay_Line;
architecture Delay_Line_arch of Delay_Line is
signal din_dly : std_logic_vector(CLK_DELAYS-1 downto 0);
begin
din_dly(0) <= i_Din;
process(CLK)
begin
if rising_edge(CLK) then
for index in 0 to CLK_DELAYS-1 generate
begin
din_dly(index+1) <= din_dly(index);
end;
end if;
end process;
o_Q <= din_dly(CLK_DELAYS);
o_Qnot <= NOT (din_dly(CLK_DELAYS));
end Delay_Line_arch;
Typically I would just add a bunch of:
din_delay(9) <= din_delay(8);
din_delay(8) <= din_delay(7);
...
in the code, but honestly I'd like something a little more reusable as a package.
It isn't really necessary to use such elaborate methods to implement shift registers. You can implement them directly in one line using array concatenation and slicing.
constant DELAY_STAGES : positive := 10; -- Or use a generic parameter
signal delay_line : std_logic_vector(1 to DELAY_STAGES);
...
process(clk) is
begin
if rising_edge(clk) then
delay_line <= i_Din & delay_line(1 to DELAY_STAGES-1); -- Shift right
end if;
end process;
-- Retrieve the end of the delay without a hard-coded index
o_Q <= delay_line(delay_line'high);
The brevity of this approach pretty much eliminates any convenience of having a component that you need to instantiate with port and generic maps. Plus you have the flexibility of being able to tap off whatever intermediate signals you may need.
Well I don’t have 50 rep yet but to get Pablo R’s method to work with large busses and delays bus_size := 16 and delay := 256. I had to change:
temp_bus2 <= i_bus2 & temp_bus2(delay*bus_size - 1 downto (delay-1)*bus_size);
to
temp_bus2 <= i_bus2 & temp_bus2(delay*bus_size - 1 downto (bus_size);
A bit late, but this is my generic_delay component:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITY generic_delay is
generic (
bus_size : natural;
delay : natural
);
port (
i_Clock : IN STD_LOGIC;
i_reset : IN STD_LOGIC;
i_bus1 : in std_logic_vector(bus_size - 1 downto 0);
i_bus2 : in std_logic_vector(bus_size - 1 downto 0);
o_bus1 : out std_logic_vector(bus_size - 1 downto 0);
o_bus2 : out std_logic_vector(bus_size - 1 downto 0)
);
end generic_delay;
architecture a of generic_delay is
----------------------------
-- SIGNALS DECLARATION
----------------------------
signal temp_bus1 : std_logic_vector(delay*bus_size - 1 downto 0);
signal temp_bus2 : std_logic_vector(delay*bus_size - 1 downto 0);
BEGIN
-----------------------------------------
-- SYNCHRONOUS PROCESS
-----------------------------------------
process(i_Clock, i_reset)
begin
if i_reset = '1' then
temp_bus1 <= (others => '0');
temp_bus2 <= (others => '0');
elsif falling_edge(i_Clock) then
if delay > 1 then
temp_bus1 <= i_bus1 & temp_bus1(delay*bus_size - 1 downto (delay-1)*bus_size);
temp_bus2 <= i_bus2 & temp_bus2(delay*bus_size - 1 downto (delay-1)*bus_size);
else
temp_bus1 <= i_bus1;
temp_bus2 <= i_bus2;
end if;
elsif (RISING_EDGE(i_Clock)) then
o_bus1 <= temp_bus1(bus_size - 1 downto 0);
o_bus2 <= temp_bus2(bus_size - 1 downto 0);
end if; -- reset + rising_edge(clk)
end process logic;
-------------------------------------------------------
end a;