Writing a code for a CRC using D-FlipFlop in VHDL - vhdl

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

Related

Vhdl Parallel or Serial-in/ Parallel-out register

I want to build a n bits register which can take both serial or parallel input depending of a bit SERIAL. And always parallel output. See my code below. My issue is that I need to use a If statement to choose my input (parallel or serial) (which must be inside a process) and I also need a for generate statement because I work with generic n bit register (which cannot be done inside a process) to build the n D-Flipflop.
I was thinking to use for loop instead of for i ..generate but I need to use that i as index.
Does anyone know how to fix my code? The main issue is that using serial input, the flipflop are connected in series while parallel input, the flipflops are independent. And I don't know how to model that proprely.
Thank you
-- Parallel or Serial-in / Parallel-out n bits register
library ieee;
use ieee.std_logic_1164.all;
entity PSIPOreg is
generic(n: integer);
port(RST, Clk_reg, enable, SERIAL: in std_logic;
Din_P: in std_logic_vector(n-1 downto 0);
Din_S: in std_logic;
Qout: out std_logic_vector(n-1 downto 0));
end PSIPOreg;
architecture bhv of PSIPOreg is
component D_FlipFlop
port(D, Clk, reset, EN : in std_logic;
Q : out std_logic);
end component;
signal parallel_data : std_logic_vector(0 to n-1) := (others =>'0');
signal temp_input: std_logic_vector(0 to n-1) := (others =>'0');
begin
Qout <= parallel_data;
process(SERIAL, Clk_reg, enable, RST)
begin
if(SERIAL = '0') then -- PIPO register
temp_input <= Din_P;
gen_reg: for i in 0 to n-1 generate
regx: D_FlipFlop port map(D => temp_input(i), Clk => Clk_reg, reset => RST, EN => enable, Q => Qout(i));
end generate gen_reg;
elsif(SERIAL = '1') then -- SIPO register
temp_input(0) <= Din_S;
shift_reg: for i in 0 to n-1 generate
begin
dff_lsb: if i = 0 generate
begin
dff: D_FlipFlop port map(D => temp_input(0), Clk => Clk_reg, reset => RST, EN => enable, Q => parallel_data(i));
--Qout(i) <= parallel_data(i);
end generate dff_lsb;
dff_mid: if((i>0) and (i<(n-1))) generate
begin
dff: D_FlipFlop port map(D => parallel_data(i-1), Clk => Clk_reg, reset => RST, EN => enable, Q => parallel_data(i));
--Qout(i) <= parallel_data(i);
end generate dff_mid;
dff_msb: if i = n-1 generate
begin
dff: D_FlipFlop port map(D => parallel_data(i-1), Clk => Clk_reg, reset => RST, EN => enable, Q => Qout(i));
end generate dff_msb;
end generate shift_reg;
end if;
end process;
end bhv;

How to create port map that maps a single signal to 1 bit of a std_logic_vector?

I am designing some hardware using VHDL. My design requires the use of a 12-bit ripple counter that will utimately get connected as shown in the schematic screenshot below.
I found an existing entity & architecture for a ripple counter from online that I have decided should be suitable for my design. Here it is, in case it is useful in helping answer my question.
entity ripple_counter is
generic (
n : integer := 12
);
port (
clk : in std_logic;
clear : in std_logic;
dout : out std_logic_vector(n-1 downto 0)
);
end ripple_counter;
architecture behavioral of ripple_counter is
signal clk_i, q_i : std_logic_vector(n-1 downto 0);
begin
clk_i(0) <= clk;
clk_i(n-1 downto 1) <= q_i(n-2 downto 0);
gen_cnt: for i in 0 to n-1 generate
dff: process(clear, clk_i)
begin
if (clear = '1') then
q_i(i) <= '1';
elsif (clk_i(i)'event and clk_i(i) = '1') then
q_i(i) <= not q_i(i);
end if;
end process dff;
end generate;
dout <= not q_i;
end behavioral;
One will see that the ripple counter entity uses a n-bit (12-bit in this case) std_logic_vector for it's output. But, only two of the Q* outputs get connected. The ripple counter's component and port map declarations have been created as follows. Note that u22d_out, u21b_out and, u26_q12_out are all signals that have been defined in the same structural architecture as the ripple counter's component and port map. Also, q10 is an output of the system.
component ripple_counter is
generic (
n : integer := 12
);
port (
clk : in std_logic;
clear : in std_logic;
dout : out std_logic_vector(n-1 downto 0)
);
end component;
u26: ripple_counter port map (
clk => u22d_out,
clear => u21b_out,
dout(11) => u26_q12_out,
dout(9) => q10
);
When I attempt to run my design I get the following errors...
Error: [42972]: "c:/somefilepath/somefilename.vhd", line 493: Incomplete sub-element association for formal dout
Error: [42604]: "c:/somefilepath/somefilename.vhd", line 489: Port and Port Map does not match
Error: [40008]: HDL analysis failed.
Line 493 is the line that reads dout(9) => q10.
Line 489 is the line that reads u26: ripple_counter port map.
I am unsure if this is a syntax error or if it is a functional issue. How can I map specific bits of a vector to a single signal?
As suggested by Brian D in the comments...the port map association was incomplete. Here is an updated version of the port map.
u26: ripple_counter port map (
clk => u22d_out,
clear => u21b_out,
dout(11) => u26_q12_out,
dout(10) => open,
dout(9) => q10,
dout(8 downto 0) => open
);

how to update the output on the rising edge of the clock in structural VHDL code?

I have this very simple 16-bit and gate written in structural form in VHDL:
The files are uploaded here.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity and_16bit is
Port (
A : in std_logic_vector(15 downto 0);
B : in std_logic_vector(15 downto 0);
Clk : in STD_LOGIC;
--Rst : in STD_LOGIC;
C : out std_logic_vector(15 downto 0) );
end and_16bit;
architecture Behavioral of and_16bit is
component and_1bit is
Port (
A : in std_logic;
B : in std_logic;
C : out std_logic );
end component;
signal s : std_logic_vector(15 downto 0);
begin
ands: for i in 15 downto 0 generate
and_1bit_x: and_1bit port map (A => A(i), B => B(i), C => s(i));
end generate;
process(Clk)
begin
if rising_edge(Clk) then
C <= s;
end if;
end process;
end Behavioral;
In order to update the output in the rising edge of the clock, I have defined this "s" signal. I wonder if this is the correct way to update the output in structural VHDL codes? what should I do to scape the unknown output for the first output?
Any comments will be a great help.
It's better to put the sequential process into a submodule and instantiate it in the top-level (and_16bit). Then your top-level will be more structural.
You can have one instance for each bit as you did for and_1bit.
For example, this module is a 1-bit register.
entity dff_1bit is
Port (
D : in std_logic;
Clk : in std_logic;
Q : out std_logic );
end dff_1bit;
architecture Behavioral of dff_1bit is
begin
process(Clk)
begin
if rising_edge(Clk) then
Q <= D;
end if;
end process;
end Behavioral;
Then you can instantiate it in and_16bit, inside the same generate block.
dff_1bit_x: dff_1bit port map (D => s(i), Clk => Clk, Q => C(i));

test bench multiple architectures

sorry I'm new to this website, but I have been searching for answers for almost 2 days straight.
I am new to vhdl, and an assignment has asked to make a simple 16-bit ALU. This ALU needs 2 architectures: the behavioral, as well as the RTL design. I have the code for that complete as far as I am concerned.
What I cannot figure out is how to write a test bench that will allow me to run the simulation for both architectures in modelsim. I have both files (test bench and ALU) which compile fine, however I get errors in the simulation saying that "uninitialized inout port has no driver"
I'm not sure what code to show for this problem so I'll just show you the beginning of my TB.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
ENTITY tb IS
END tb;
ARCHITECTURE behavior OF tb IS
signal Clk,Res : std_logic := '0';
signal A,B : signed(15 downto 0) := (others => '0');
signal R1, R2 : signed(31 downto 0) := (others => '0');
signal Op : unsigned(2 downto 0) := (others => '0');
constant Clk_period : time := 10 ns;
component ALU_16_First
port(A, B: signed(15 downto 0):=(others => '0'); R: inout signed(31 downto 0):= (others => '0'); Op: in unsigned(2 downto 0) := (others => '0'); Clk, Res: Std_logic);
end component ALU_16_First;
component ALU_16_RTL
port(A, B: in signed(15 downto 0):= (others => '0');
R: inout signed(31 downto 0):= (others => '0'); Op: in unsigned(2 downto 0) := (others => '0'); Clk, Res: Std_logic);
end component ALU_16_RTL;
for ALU_Behaviorial: ALU_16_First use entity work.simple_alu(Behavioral);
for ALU_RTL: ALU_16_RTL use entity work.simple_alu(RTL);
BEGIN
-- Instantiate the Unit Under Test (UUT)
ALU_Behaviorial : ALU_16_First PORT MAP (
A,
B,
R1,
Op,
Clk,
Res
);
ALU_RTL: ALU_16_RTL PORT MAP (
A,
B,
R2,
Op,
Clk,
Res
);
I'm basically desperate to get this done on time.
Thanks.
It looks fine other than the R port being inout (as Russell noted). If for some reason you need the R port to be bi-directional, make sure to assign it to 'Z' during appropriate times in the testbench:
testProc : process
begin
...
R <= (others => 'Z') ;
In the future, you can save your self some time by using a direct entity instantiation in place of the component declaration, configuration specification, and component instantiation:
ALU_Behaviorial : use work.simple_alu(Behavioral)
PORT MAP (
A => A_tb,
B => B_tb,
R => R1_tb,
Op => Op_tb,
Clk => Clk_tb,
Res => Res_tb
);
If you stay with component declaration, there is no need to create separate component names for each of the models. It is your configuration specification that is associating the architecture name with the entity.
I recommend that you forget about configuration specifications and use direct entity instantiation for simple cases and configuration declarations for more complex cases.
I recommend using explicit port mapping to make it completely clear what's going on in your component instantiations. So for example:
ALU_Behaviorial : ALU_16_First PORT MAP (
A => A_tb,
B => B_tb,
R1 => R1_tb,
Op => Op_tb,
Clk => Clk_tb,
Res => Res_tb
);
_tb signals are your test bench signals. Now, ensure that your inputs to your components (A_tb, B_tb, R1_tb, Op_tb, Clk_tb, Res_tb) are being driven by your test bench architecture. Where is your test bench driving these inputs?
Also, Is there a good reason why you chose to make R1 an "inout"? Could you just make it an out? It might be a bit easier for you.

Implementing an Accumulator in VHDL

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!

Resources