I am trying to implement a signed accumulator using Core Gen in Xilinx. According to my understanding an accumulator performs the function of a normal register which is just routing the input to the output, but I wanted clarification on that.
I added the Accumulator IPcore (.xco) module to the project and I have a main file which basically contains the component declaration and the port map. I have a single step process too. Everything compiles and I can see the result on the board but don't quite understand what's going on...
When I input 1000 the 8 bit output on the LEDs is 11111000. Another input of 1111 gives me 11110111. I am attaching the code here for the main vhd file called Accm and the .vho file.
----------------------------------------------------------------------------------
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity Accm is
port( b: in std_logic_vector(3 downto 0);
sclr, clk, b1, b2 : in std_logic;
q : out std_logic_vector(7 downto 0)
);
end Accm;
architecture Behavioral of Accm is
-- signal declaration
type tell is (rdy,pulse,not_rdy);
signal d_n_s: tell;
signal en: std_logic;
-- component declaration
COMPONENT my_accm
PORT (
b : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
clk : IN STD_LOGIC;
sclr : IN STD_LOGIC;
q : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END COMPONENT;
-- port map
begin
A1 : my_accm
PORT MAP (
b => b,
clk => en,
sclr => sclr,
q => q
);
process(clk)
begin
if clk'event and clk='1' then
case d_n_s is
when rdy => en <= '0';
if b1='1' then d_n_s <= pulse; end if;
when pulse => en <= '1';
d_n_s <= not_rdy;
when not_rdy => en <='0';
if b2='1' then d_n_s <= rdy; end if;
end case;
end if;
end process;
-- .VHO CODE
------------- Begin Cut here for COMPONENT Declaration ------ COMP_TAG
COMPONENT my_accm
PORT (
b : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
clk : IN STD_LOGIC;
sclr : IN STD_LOGIC;
q : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
);
END COMPONENT;
-- COMP_TAG_END ------ End COMPONENT Declaration ------------
-- The following code must appear in the VHDL architecture
-- body. Substitute your own instance name and net names.
------------- Begin Cut here for INSTANTIATION Template ----- INST_TAG
your_instance_name : my_accm
PORT MAP (
b => b,
clk => clk,
sclr => sclr,
q => q
);
end Behavioral;
I am also pasting an image of the accumualtor I generated in CoreGen.
I'D appreciate it if someone could explain me what is going on in this program. Thanks!
"Accumulator" can mean many things. In the hardware Xilinx library, the component you instantiated is an adder in front of a register. The adder is adding the current value of the accumulator register with the input term. The accumulator register is wider than the input so you can accumulate (add together) many input terms without overflowing the output.
When your circuit starts, the accumulator contains zero. You input 1000 (-8) which when added to zero becomes 11111000 (-8 sign extended) on the output. You then add 1111 (-1), and the output becomes 11110111 (-9 sign extended).
Once you are done "accumulating", assert SCLR to clear the accumulator register back to zero (or use SSET or SINIT, as appropriate for your logic).
This should all be covered by the documentation for the Xilinx library (try clicking the "datasheet" button in the corgen dialog).
Actually, I think I get it now. It's just acting like an Adder with signed inputs. I think I am correct on this but would appreciate any clarification!
Related
I'm learning VHDL for a university project. The goal is to write a CRC circuit given a certain polynomial. I found online solution that uses register but I wanted to do it by using actual D-FlipFlop.
So I created the D-FlipFlop and put in my main file several instances of them using generate to be more flexible and be able to add or remove flipflop easily.
library IEEE;
use IEEE.std_logic_1164.all;
entity LFSR is
generic (NBit : positive := 8);
port(
clk :in std_logic;
reset :in std_logic;
din :in std_logic;
dout :out std_logic_vector(Nbit-1 downto 0)
);
end LFSR;
architecture rtl of LFSR is
component DFC
port(
clk :in std_logic;
reset :in std_logic;
d :in std_logic;
crc :out std_logic;
q :out std_logic
);
end component DFC;
signal q_s : std_logic_vector (NBit-1 downto 0):= (others => '0');
signal crc_t : std_logic_vector (NBit-1 downto 0):= (others => '0'); --registro temporaneo su cui fare le operazioni
signal int_0 :std_logic := '0';
signal int_2 :std_logic := '0';
signal int_4 :std_logic := '0';
signal int_8 :std_logic := '0';
begin
int_0<= din xor q_s(7);
int_2<= q_s(1) xor q_s(7);
int_4<= q_s(3) xor q_s(7);
GEN: for i in 0 to Nbit-1 generate
FIRST: if i=0 generate
FF1: DFC port map (
clk => clk,
reset => reset,
d => int_0,
crc => crc_t(i), --funziona benissimo se metto dout(i)
q => q_s(i)
);
end generate FIRST;
THIRD: if i=2 generate
FF2: DFC port map (
clk => clk,
reset => reset,
d => int_2,
crc => crc_t(i),
q => q_s(i)
);
end generate THIRD;
FIFTH: if i=4 generate
FF4: DFC port map (
clk => clk,
reset => reset,
d => int_4,
crc => crc_t(i),
q => q_s(i)
);
end generate FIFTH;
INTERNAL: if i>0 and i<Nbit-1 and i/= 2 and i/=4 generate
FFI: DFC port map (
clk => clk,
reset => reset,
d => q_s(i-1),
crc => crc_t(i),
q => q_s(i)
);
end generate INTERNAL;
LAST: if i=Nbit-1 generate
FFN: DFC port map (
clk => clk,
reset => reset,
d => q_s(i-1),
crc => crc_t(i),
q => q_s(i)
);
end generate LAST;
end generate GEN;
variable t : natural := 0;
begin
if(rising_edge(clk)) then
t:= t+1;
if t=24 then
dout <= crc_t;
end if;
end if;
end process;
end rtl;
Of course on line 35, where I put "d => din xor q_s(Nbit-1)", the compiler gives me an error. How can I obtain the result I want to get?
I tried putting intermediary signal to pass this problem, but I can't understand why this is not working as expected.
This is the code of the DFC component:
library IEEE;
use IEEE.std_logic_1164.all;
entity DFC is
port(
clk :in std_logic;
reset :in std_logic;
d :in std_logic;
crc :out std_logic;
q :out std_logic
);
end DFC;
architecture rtl of DFC is
begin
process(clk, reset, d)
begin
if(reset = '1')then
q <= '0';
crc<= '0';
elsif (clk'event and clk='1') then
q <= d;
crc <= d;
end if;
end process;
end rtl;
Thanks all for the aswers.
Gabriele.
Edit: I added all the LFSR code and the DFC code.
Your question is incomplete because it does not have a minimal reproductible code. In other word, it is hard to help you.
Prior to VHDL-2008:
You cannot perform such action : d => din xor q_s(Nbit-1) because this line is seen as an operation and that is not possible in an instantiation of an entity or a component.
(like in this post for example: https://electronics.stackexchange.com/questions/184893/warning-actual-for-formal-port-a-is-neither-a-static-name-nor-a-globally-stati)
However, there is a way to work around that, you have to create a new signal
Notice that when you use your code, the error should be something like: Actual for formal port a is neither a static name nor a globally static expression
With VHDL-2008:
If look in the norm: http://www.fis.agh.edu.pl/~skoczen/hdl/ieee_std/ieee1076-2008.pdf
You can find on paragraph 6.5.6.3 Port clauses:
If a formal port of mode in is associated with an expression that is not globally static (see 9.4.1) and the
formal is of an unconstrained or partially constrained composite type requiring determination of index
ranges from the actual according to the rules of 5.3.2.2, then the expression shall be one of the following:
The name of an object whose subtype is globally static
An indexed name whose prefix is one of the members of this list
A slice name whose prefix is one of the members of this list and whose discrete range is a globally static discrete range
An aggregate, provided all choices are locally static and all expressions in element associations are expressions described in this list
A function call whose return type mark denotes a globally static subtype
A qualified expression or type conversion whose type mark denotes a globally static subtype
An expression described in this list and enclosed in parentheses
In other word, in VHDL-2008, the code you provided should work.
About your initialization problem, it is unclear, what signals/varibles are not initialized ? The best you can do is, if your first question is well answered by this post, then accept it has a solution or edit your question for more clarity. Then ask an other question in an other thread about the initialization problem. You can also post your question on Electronics Stackexchange
I tried implementing a fir filter in VHDL but during the first three clocks I get no output and the error at 0 ps, Instance /filter_tb/uut/ : Warning: There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)..
Source file (I also have 2 other files for D Flip-Flops):
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
entity filter is
port ( x: in STD_LOGIC_VECTOR(3 downto 0);
clk: in STD_LOGIC;
y: out STD_LOGIC_VECTOR(9 downto 0));
end filter;
architecture struct of filter is
type array1 is array (0 to 3) of STD_LOGIC_VECTOR(3 downto 0);
signal coef : array1 :=( "0001", "0011", "0010", "0001");
signal c0, c1, c2, c3: STD_LOGIC_VECTOR(7 downto 0):="00000000";
signal s0, s1, s2, s3: STD_LOGIC_VECTOR(3 downto 0) :="0000";
signal sum: STD_LOGIC_VECTOR(9 downto 0):="0000000000";
component DFF is
Port ( d : in STD_LOGIC_VECTOR(3 downto 0);
clk : in STD_LOGIC;
q : out STD_LOGIC_VECTOR(3 downto 0));
end component;
component lDFF is
Port ( d : in STD_LOGIC_VECTOR(9 downto 0);
clk : in STD_LOGIC;
q : out STD_LOGIC_VECTOR(9 downto 0));
end component;
begin
s0<=x;
c0<=x*coef(0);
DFF1: DFF port map(s0,clk,s1);
c1<=s1*coef(1);
DFF2: DFF port map(s1,clk,s2);
c2<=s2*coef(2);
DFF3: DFF port map(s2,clk,s3);
c3<=s3*coef(3);
sum<=("00" & c0+c1+c2+c3);
lDFF1: lDFF port map(sum,clk,y);
end struct;
Testbench:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use ieee.std_logic_unsigned.all;
ENTITY filter_tb IS
END filter_tb;
ARCHITECTURE behavior OF filter_tb IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT filter
PORT(
x : IN STD_LOGIC_VECTOR(3 downto 0);
clk : IN std_logic;
y : OUT STD_LOGIC_VECTOR(9 downto 0)
);
END COMPONENT;
--Inputs
signal x : STD_LOGIC_VECTOR(3 downto 0) := (others => '0');
signal clk : std_logic := '0';
--Outputs
signal y : STD_LOGIC_VECTOR(9 downto 0);
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: filter PORT MAP (
x => x,
clk => clk,
y => y
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc1: process
begin
x<="0001";
wait for 10ns;
x<="0011";
wait for 10ns;
x<="0010";
wait for 10ns;
--x<="0011";
end process;
END;
Output:
If anyonce could help, I'd appreciate it. I think it has something to do with the inital values of the signals c_i and s_i but I'm not too sure.
Your FIR filter contains flip-flops. These flip-flops have no reset input and so power up in an unknown state. You simulator models this by initialising the flip-flops' outputs to "UUUU" (as the are four bits wide). A 'U' std_logic value represents and uninitialised value.
So, your code behaves as you ought to expect. If you're not happy with that behaviour, you need to add a reset input and connect it to your flip-flops.
You have build a series of three register making up a cascade of registers.
You have not provided a reset so the register contents will be Unknown. You use the registers for calculations without any condition. Thus you arithmetic calculations will see the Unknown values and fail as you have seen.
The first (simplest) solution would be to add a reset. But that is not the best solution. You will no longer get warnings but the first three cycles of your output will be based on the register reset value not of your input signal.
If you have a big stream and don't care about some incorrect values in the first clock cycle you can live with that.
The really correct way would be to have a 'valid' signal transported along side your data. You only present the output data when there is a 'valid'. This is the standard method to process data through any pipeline hardware structure.
By the way: you normally do not build D-ffs yourself. The synthesizer will do that for you. You just use a clocked process and process the data vectors in it.
I have some questions. If I add a reset pin, when will I toggle it from 1 to 0? How can I create this circuit without explicitly using D-ffs?
You make a reset signal in the same way as you make your clock.
As to D-registers: they come out if you use the standard register VHDL code:
reg : process (clk,reset_n)
begin
// a-synchronous active low reset
if (reset_n='0') then
s0 <= "0000";
s1 <= "0000";
s2 <= "0000";
elsif (rising_edge(clk)) then
s0 <= x;
s1 <= s0;
s2 <= s1;
....
(Code entered as-is, not checked for syntax or typing errors)
I'm reasonably new to vhdl and wondering what the best way is to manage the following situation / pattern:
Say I have an entity A whose architecture instantiates a component B. I would then like to reuse A but this time instantiate a component C in the place of B. C has a completely different functionality to B. B and C may have different sized ports, however the functionality of A is such that it can handle the different port sizes, using, say, generics and generate statements. Essentially A is like a container for either component B, C or maybe D, E, F etc. It maybe performs some logic/buffering on the inputs and outputs of B, C etc. in a way that is common for all these components.
I have read about configurations and my understanding is that I can instantiate a component in A (call it Z), and then link it's entity to different architectures using configurations. It seems not many people use this feature of vhdl.
Are configurations the right way to go for this situation?
Ideally, I would like all of the parameters in the design to depend ultimately on the architecture chosen for Z so that the architecture dictates the port sizes of the entity its linked to (Z), and in turn the port sizes of Z dictate the parameters of A and finally these parameters dictate the port sizes of A. Is this possible?
(I am using 'parameterisation' in the general sense to mean a way of configuring a design. Generics, packages, 'range attributes etc would all be examples of parameterisation)
A pseudocode example of what I mean is below. The values in capitals should depend on the architecture chosen for Z.
entity A is
port
(
clk : in std_logic;
reset : in std_logic;
inputs : in std_logic_vector(SOME_WIDTH_A_IN - 1 downto 0);
outputs : out std_logic_vector(SOME_WIDTH_A_OUT - 1 downto 0);
);
end A;
architecture A_arch of A is
component Z
port
(
clock : in std_logic;
inputs : std_logic_vector(SOME_WIDTH_Z_IN - 1 downto 0);
ouputs : std_logic_vector(SOME_WIDTH_Z_OUT - 1 downto 0)
);
end component;
begin
for i in 1 to SOME_VALUE generate
-- whatever logic/buffering we want to perform on the inputs
end generate;
for i in 1 to SOME_VALUE generate
-- whatever logic/buffering we want to perform on the outputs
end generate;
instance: Z
port map(
clock => clk,
inputs => --output of logic/buffering above
outputs => -- input of logic/buffering above
);
end A_arch;
I may be thinking about this the wrong way - Essentially I would like to avoid having to copy/paste the 'container' entity A to work with different components B, C etc. What is the best way to do this?
It seems that you want your components B,C,D, etc... to do exactly the same except for different port sizes. The best approach to do this is with GENERIC. Let's say your other entity (let's call it INNER_ENTITY) is configurable n-bit wide double flip flop (can be used to resolve metastability).
Here is the example code for OUTER_ENTITY and INNER_ENTITY:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity OUTER_ENTITY is
port (
CLK : in std_logic;
RST : in std_logic;
PORT_A : in std_logic_vector(6 downto 0);
PORT_B : in std_logic_vector(13 downto 0);
SUM_A_B : out std_logic_vector(13 downto 0)
);
end entity;
architecture RTL_OUTER_ENTITY of OUTER_ENTITY is
signal PORT_A_INNER : std_logic_vector(6 downto 0);
signal PORT_B_INNER : std_logic_vector(13 downto 0);
component INNER_ENTITY
generic (PORT_SIZE : integer);
port (
CLK : in std_logic;
RST : in std_logic;
PORT_IN : in std_logic_vector(PORT_SIZE - 1 downto 0);
PORT_OUT : out std_logic_vector(PORT_SIZE - 1 downto 0);
);
end component INNER_ENTITY;
begin
SUM_A_B <= PORT_A_INNER + PORT_B_INNER;
INNER_7_BIT : INNER_ENTITY
generic map (PORT_SIZE => 7)
port map (
CLK => CLK,
RST => RST,
PORT_IN => PORT_A,
PORT_OUT => PORT_A_INNER
);
INNER_14_BIT : INNER_ENTITY
generic map (PORT_SIZE => 14)
port map (
CLK => CLK,
RST => RST,
PORT_IN => PORT_B,
PORT_OUT => PORT_B_INNER
);
end RTL_OUTER_ENTITY;
entity INNER_ENTITY
generic (PORT_SIZE : integer);
port (
CLK : in std_logic;
RST : in std_logic;
PORT_IN : in std_logic_vector(PORT_SIZE - 1 downto 0);
PORT_OUT : out std_logic_vector(PORT_SIZE - 1 downto 0);
);
end entity;
architecture RTL_INNER_ENTITY of INNER_ENTITY is
signal PORT_X : std_logic_vector(PORT_SIZE - 1 downto 0);
begin
process(CLK, RST)
begin
if RST = '1' then
PORT_OUT <= (OTHERS => '0');
PORT_X <= (OTHERS => '0');
elsif rising_edge(CLK) then
PORT_OUT <= PORT_X;
PORT_X <= PORT_IN;
end if;
end process;
end RTL_INNER_ENTITY;
Please note that I did not compile this code so it might have some minor syntax errors but it should give you an overview to how GENERICs might be used to do what you want.
I am using modelsim for simulating a pseudo-random pattern generator using the below code. The problem is when i force the data_reg signal to a seed value (ex: 0001010101101111) the data_out shows the same value instead of a random value. i will really appreciate any help i cud get on this one.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity dff is
Port ( CLK : in std_logic;
RSTn : in std_logic;
D : in std_logic;
Q : out std_logic);
end dff;
architecture Behavioral of dff is
begin
process(CLK)
begin
if CLK'event and CLK='1' then
if RSTn='1' then
Q <= '1';
else
Q <= D;
end if;
end if;
end process;
end Behavioral;
VHDL CODE FOR PRBS Generator using LFSR:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity lfsr is
Port ( CLK : in STD_LOGIC;
RSTn : in STD_LOGIC;
data_out : out STD_LOGIC_VECTOR (15 downto 0));
end lfsr;
architecture Behavioral of lfsr is
component dff
Port ( CLK : in std_logic;
RSTn : in std_logic;
D : in std_logic;
Q : out std_logic);
end component;
signal data_reg : std_logic_vector(15 downto 0);
signal tap_data : std_logic;
begin
process(CLK)
begin
tap_data <= (data_reg(1) xor data_reg(2)) xor (data_reg(4) xor
data_reg(15));
end process;
stage0: dff
port map(CLK, RSTn, tap_data, data_reg(0));
g0:for i in 0 to 14 generate
stageN: dff
port map(CLK, RSTn, data_reg(i), data_reg(i+1));
end generate;
data_out <= data_reg after 3 ns;
end Behavioral;
First off. In your LFSR you have a process sensitive to CLK which should only be combinational:
process(CLK) -- Not correct
-- Change to the following (or "all" in VHDL-2008)
process(data_reg)
You could also just implement it as a continuous assignment outside of a formal process which is functionally the same in this case.
When you force data_reg to a value you are overriding the normal signal drivers instantiated in the design. In the GUI the force command defaults to "Freeze". Once that is in place, the drivers can't update data_reg because the freeze force is dominant until you cancel it. In the force dialog select the "Deposit" kind to change the state without overriding the drivers on subsequent clocks.
The Modelsim documentation has this to say about the different force kinds:
freeze -- Freezes the item at the specified value until it is forced again or until it is unforced with a noforce command.
drive -- Attaches a driver to the item and drives the specified value until the item is forced again or until it is unforced with a noforce command. This option is illegal for unresolved signals.
deposit -- Sets the item to the specified value. The value remains until there is a subsequent driver transaction, or until the item is forced again, or until it is unforced with a noforce command
Note: While a lot of instructional materials (unfortunately) demonstrate the use of the std_logic_arith and std_logic_unsigned libraries, these are not actual IEEE standards and shouldn't be used in standard conformant VHDL. Use numeric_std instead or, in your case, just eliminate them since you aren't using any arithmetic from those libraries.
I've made a dual port register bank in VHDL, and I want to test it to make sure it works. How would I go about doing this? I know what I want to do (set register 2 to be a constant, read out of it in test program, write to register 3 and read it back out and see if I have the same results).
Only thing is, I'm new to VHDL, so I don't know if there's a console or how a test program is structured or how to instantiate the register file, or even what to compile it in (I've been using quartus so far).
Here's my register file:
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
-- Register File
entity RF is
port(
signal clk, we: in std_logic;
signal ImmediateValue : in std_logic_vector(15 downto 0);
signal RegisterSelectA, RegisterSelectB : in integer range 0 to 15;
signal AOut, BOut : out std_logic_vector(15 downto 0)
);
end RF
architecture behavior of RF is
array std_logic_vector_field is array(15 downto 0) of std_logic_vector(15 downto 0);
variable registers : std_logic_vector(15 downto 0);
process (clk, we, RegisterSelectA, RegisterSelectB, ImmediateValue)
wait until clk'event and clk = '1';
registers(RegisterSelectA) := ImmediateValue when we = '1';
AOut <= registers(RegisterSelectA);
BOut <= registers(RegisterSelectB);
end process;
end behavior;
First of all, if you are new to VHDL design, you might be best off starting with a tutorial on the web, or grabbing a book like "The Designer's Guide to VHDL".
Anyway, just like a software design, to test a VHDL design, you have to write some test code. In hardware design, usually these tests are unit-test like, but are often called "testbenches".
For the design you've given, you'll need to create something like this:
library ieee.std_logic_1164.all;
library ieee.numeric_std.all;
entity test_RF is
end entity;
architecture test of test_RF is
signal clk, we: std_logic;
signal ImmediateValue : std_logic_vector(15 downto 0);
signal RegisterSelectA, RegisterSelectB : integer range 0 to 15;
signal AOut, BOut : std_logic_vector(15 downto 0)
begin
-- Instantiate the design under test
u_RF : entity work.RF
port map (
clk => clk,
we => we,
ImmediateValue => ImmediateValue,
RegisterSelectA => RegisterSelectA,
RegisterSelectB => RegisterSelectB,
AOut => AOut,
BOut => BOut
);
-- create a clock
process is
begin
clk <= '0';
loop
wait for 10 ns;
clk <= not clk;
end loop;
end process;
-- create one or more processes to drive the inputs and read the outputs
process is
begin
wait until rising_edge(clk);
-- do stuff
-- use assert to check things
-- etc
end process;
end architecture;