Create "Init" and "End" SIGNAL for module in VHDL - vhdl

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity struture_test is
Port ( clk : in STD_LOGIC;
rst : in STD_LOGIC;
Init : in STD_LOGIC;
i_ia : in STD_LOGIC_VECTOR (11 downto 0);
i_ib : in STD_LOGIC_VECTOR (11 downto 0);
end_s : out std_logic;
result : out STD_LOGIC_VECTOR (11 downto 0));
end struture_test;
architecture Behavioral of struture_test is
signal en_sn : std_logic := '0';
begin
PROCESS (clk,rst)
variable acc : signed (23 downto 0) ;
variable x : signed (35 downto 0) ;
begin
if (rst = '0') then
result <= (others => '0');
end_s <= '0';
elsif (rising_edge (clk)) then
if ((Init) = '1') then
acc := signed (i_ia)*signed (i_ib);
x := acc * signed (i_ia);
result <= std_logic_vector (x(23 downto 12));
end_s <= '1';
else
end_s <= '0';
end if;
end if;
end process;
end Behavioral;
Hi everyone
I have a project which includes some blocks. The blocks link each other through Init or End Signal. It means that The End signal of one Block is connected to Init signal of the following block.
I'm confused about that Does the above code make a good Init and a End signal ?
If I change my code and convert it into Pipelined structure to operate with the higher frequency clock. The variables convert into the signals
PROCESS (clk,rst)
signal acc : signed (23 downto 0) ;
signal x : signed (35 downto 0) ;
begin
if (rst = '0') then
result <= (others => '0');
end_s <= '0';
elsif (rising_edge (clk)) then
if ((Init) = '1') then
acc <= signed (i_ia)*signed (i_ib);
x <= acc * signed (i_ia);
result <= std_logic_vector (x(23 downto 12));
end_s <= '1';
else
end_s <= '0';
end if;
end if;
end process;
How to create Init and End signal in this case? The block illustrates in the picture

The idea is good, but the code is wrong. In addition it has some bad coding smells.
Basic rules:
Do not use asynchronous resets.
You can not declare signals in processes. Process allow variable declarations; architectures allow signal declarations.
Each signal assignment in a clock process creates a flip-flop / delay of one clock cycle. So it's 3 clock cycles delay in total, but you end signal is only delayed by one cycle.
Do not enable pipelined operations. Use a delayed chain of valid bits.
Do not reset pipeline results, because underlying hardware resources like DSP (multiplication) units do not support resets.
Changed code:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity struture_test is
port (
clk : in std_logic;
rst : in std_logic;
Init : in std_logic;
i_ia : in std_logic_vector(11 downto 0);
i_ib : in std_logic_vector(11 downto 0);
end_s : out std_logic;
result : out std_logic_vector(11 downto 0) := (others => '0');
);
end entity;
architecture rtl of struture_test is
signal ValidChain : std_logic_value(2 downto 0) := (others => '0');
signal ia_delayed : signed(i_ia'range) := (others => '0');
signal acc : signed(23 downto 0) := (others => '0');
signal x : signed(35 downto 0) := (others => '0');
begin
process(clk)
begin
if rising_edge(clk) then
ValidChain <= ValidChain(ValidChain'high - 1 downto ValidChain'low) & Init;
acc <= signed(i_ia) * signed(i_ib);
ia_delayed <= signed(i_ia);
x <= acc * ia_delayed;
result <= std_logic_vector(x(23 downto 12));
end if;
end process;
end_s <= ValidChain(ValidChain'high);
end architecture;
Please note: Signal i_ia used in the 2nd multiplication needs to be delayed by one cycle, otherwise you would mix ia values from different pipeline cycles.

Related

How to fill a vector bit by bit

I have a 12 bits vector called RDIBits and a in std_logic called InUartToUart. My question is: every time the clock goes to '1', i receive a bit in InUartToUart, and i want to concat all the 12 bits that i will receive in the RDIBits vector. Basically, its a serial communication, thats why i receive 1 bit each time. Is there any simple way to do this? Something similar to RDIBits += InUartToUart in JAVA.
I would code this slightly differently. Maybe consider this.
Sorry about the formatting, Im new to this site. I have also shown how you can initialise the variable.
signal RDIBits : std_logic_vector(11 downto 0) := (Others => '0');
...
process(clk)
begin
if ( rising_edge(clk) ) then
RDIBits(11 downto 1) <= RDIBits(10 downto 0);
RDIBits(0) <= InUartToUart;
end if;
end process;
I added some more things, like the entity, the IOs and a counter for the output register.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
ENTITY my_uart IS
PORT(
clk : IN std_logic; -- system clock
rst : IN std_logic; -- reset high active
---------------------------------------------
InUartToUart : IN std_logic;
DataOut : OUT std_logic_vector(11 downto 0)
);
END ENTITY;
ARCHITECTURE struct OF my_uart IS
signal RDIBits : std_logic_vector(11 downto 0);
signal counter : integer range 0 to 12;
begin
calc_proc: process(clk, rst)
begin
if (rst = '1') then
RDIBits <= (others => '0');
counter <= 0;
elsif ( rising_edge(clk) ) then
if (counter < 12) then
RDIBits <= RDIBits(10 downto 0) & InUartToUart;
counter <= counter + 1;
elsif (counter = 12) then
DataOut <= RDIBits;
counter <= 0;
end if;
end if;
end process;
END STRUCT;
This is a typical shift register application. For example:
signal RDIBits : std_logic_vector(11 downto 0);
...
process(clk)
begin
if ( rising_edge(clk) ) then
RDIBits <= RDIBits(10 downto 0) & InUartToUart;
end if;
end process;

Why is this Shift Register not loading properly in VHDL?

I have a custom designed shift register that has as input DL(leftmost input), DR(rightmost), CLR that clears and loads DR, S that shifts right and W that loads leftmost. After testing it, the rightmost is being loaded but not the left. I have reread the code multiple times, but I can't figure out what is wrong. Here's the code:
library IEEE;
use IEEE.std_logic_1164.all;
entity shiftregister is
port (
CLK, CLR: in STD_LOGIC;
S: in STD_LOGIC; --Shift right
W: in STD_LOGIC; --Write
Cin: in STD_LOGIC; --possible carry in from the addition
DL: in STD_LOGIC_VECTOR (7 downto 0); --left load for addition result
DR: in STD_LOGIC_VECTOR (7 downto 0); --right load for initial multiplier
Q: out STD_LOGIC_VECTOR (15 downto 0)
);
end shiftregister ;
architecture shiftregister of shiftregister is
signal IQ: std_logic_vector(15 downto 0):= (others => '0');
begin
process (CLK)
begin
if(CLK'event and CLK='1') then
if CLR = '1' then
IQ(7 downto 0) <= DR; --CLR clears and initializes the multiplier
IQ(15 downto 8) <= (others => '0');
else
if (S='1') then
IQ <= Cin & IQ(15 downto 1);
elsif (W='1') then
IQ(15 downto 8) <= DL;
end if;
end if;
end if;
end process;
Q<=IQ;
end shiftregister;
Waveform
TestBench
library IEEE;
use IEEE.std_logic_1164.all;
entity register_tb is
end register_tb;
architecture register_tb of register_tb is
component shiftregister is port (
CLK, CLR: in STD_LOGIC;
S: in STD_LOGIC; --Shift right
W: in STD_LOGIC; --Write
Cin: in STD_LOGIC; --possible carry in from the addition
DL: in STD_LOGIC_VECTOR (7 downto 0); --left load for addition result
DR: in STD_LOGIC_VECTOR (7 downto 0); --right load for initial multiplier
Q: out STD_LOGIC_VECTOR (15 downto 0)
);
end component;
signal CLK: std_logic:='0';
signal CLR: std_logic:='1';
signal Cin: std_logic:='0';
signal S: std_logic:='1';
signal W: std_logic:='0';
signal DL, DR: std_logic_vector(7 downto 0):="00000000";
signal Q: std_logic_vector(15 downto 0):="0000000000000000";
begin
U0: shiftregister port map (CLK, CLR, S, W, Cin, DL,DR,Q);
CLR <= not CLR after 20 ns;
CLK <= not CLK after 5 ns;
W <= not W after 10 ns;
DL <= "10101010" after 10 ns;
DR <= "00110011" after 10 ns;
end register_tb;
Your simulation shows that your S input is always high. The way you have your conditions setup, this means that the last elsif statement will not execute because S has priority over W. If you want your write to have priority over your shift operation, you should switch your conditions
if (W='1') then
IQ(15 downto 8) <= DL;
elsif (S='1') then
IQ <= Cin & IQ(15 downto 1);
end if;
Based on your comment for the desired behaviour, you could do something like this:
if (S='1' and W='1') then
IQ <= Cin & DL & IQ(7 downto 1);
elsif (W='1') then -- S=0
IQ(15 downto 8) <= DL;
elsif (S='1') then -- W=0
IQ <= Cin & IQ(15 downto 1);
end if; -- W=0 & S=0
Some improvements:
(1) Remove all signal but CLK from sensitivity list. Your process has no async signals, so only clock is needed in sensitivity list.
process(CLK)
(2) Assign zero only to the required bits -> question of taste ;)
IQ(7 downto 0) <= DR; --CLR clears and initializes the multiplier
IQ(15 downto 8) <= (others => '0');
(3) A elsif statement can clarify the assignment precedence:
if (S='1') then
IQ <= Cin & IQ(15 downto 1);
elsif (W='1') then
IQ(15 downto 8) <= DL;
end if;
(4) Line Q <= IQ; produces a second 16-bit register. I think this is not intended. Move this line outside of the process.

State_Machine VHDL Code, can you please check why it doesn't work ! it synthesises ok

i have an assignment to write a state machine in VHDL to take control of a small built MC ( consists of 4 flip-flops,2 MUX4to1, MUX1to4, ROM, ALU,Inport ).
i have written different codes and tried several methods however simulating it shows no results, i get 'U' for results.
Code below, please check for obvious errors which I've probably missed.
i think the problem is that the stjatemachine doesn't transition through the states or doesn't execute the code inside each state.
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date: 07:48:47 10/26/2014
-- Design Name:
-- Module Name: STATE_MACHINE - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.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 STATE_MACHINE is
port (
--General Ports
CLK : in STD_LOGIC;
Re_Run_Programme : in STD_LOGIC;
--Process A parts
Programme_Start : in STD_LOGIC;
Data_From_ROM : in STD_LOGIC_VECTOR(7 downto 0);
ADDR_To_ROM : out STD_LOGIC_VECTOR (5 downto 0);
Programme_Status: out STD_LOGIC;
EN_OUT : out STD_LOGIC;
--Process B Part
--Process C Parts
MUX_FF_Select : out STD_LOGIC_VECTOR (1 downto 0);
MUX1_Select : out STD_LOGIC_VECTOR(1 downto 0);
MUX2_Select : out STD_LOGIC_VECTOR(1 downto 0);
ALU_Select : out STD_LOGIC_VECTOR(1 downto 0);
EN_A_Ports : out STD_LOGIC;
EN_B_Ports : out STD_LOGIC;
BUS_Select : out STD_LOGIC_VECTOR (1 downto 0);
Reset : out STD_LOGIC
);
end STATE_MACHINE;
architecture Behavioral of STATE_MACHINE is
type State_Type is (State_A,State_B,State_C,State_D);
signal State,Next_State : State_Type;
signal Counter : STD_LOGIC_VECTOR(5 downto 0);
--signal MO_A : STD_LOGIC;
--signal MO_B : STD_LOGIC;
--signal MO_C : STD_LOGIC;
--signal MO_D : STD_LOGIC;
signal FF_Instruction : STD_LOGIC_VECTOR (7 downto 0); -- 00
signal MUX_ALU_Instruction : STD_LOGIC_VECTOR (7 downto 0); -- 01
signal BUS_A_B_Ports_Instruction : STD_LOGIC_VECTOR (7 downto 0); -- 10
signal Reset_Instruction : STD_LOGIC_VECTOR (7 downto 0);
signal FF_Path : STD_LOGIC;
signal MUX_ALU_Path : STD_LOGIC;
signal BUS_A_B_Ports_Path : STD_LOGIC;
signal Reset_Path : STD_LOGIC;
signal EN_OUT_reg : STD_LOGIC;
--signal Next_Call : STD_LOGIC_VECTOR (7 downto 0);
signal Instruction_Finder : STD_LOGIC_VECTOR (7 downto 0);
signal Instruction_Identifier : STD_LOGIC_VECTOR(7 downto 0);
signal Instruction : STD_LOGIC_VECTOR(7 downto 0);
signal Call_Next_Instruction : STD_LOGIC_VECTOR(5 downto 0);
begin
FF_Instruction <= "00000000";
MUX_ALU_Instruction <= "01000000";
BUS_A_B_Ports_Instruction <= "10000000";
Reset_Instruction <= "11000000";
Instruction_Finder <= "11000000";
Counter <= "000000";
Call_Next_Instruction <= "000000";
--Re Run the programme
Process(CLK)
begin
if rising_edge(CLK) then
if (Re_Run_Programme = '1') then
State <= State_A;
-- MO_A <= '0';
else
State <= Next_State;
end if;
end if;
end Process;
--next state
Process(CLK,State)
begin
Next_State <= State;
case State is
--#### STATE A #####
when State_A =>
--if falling_edge(CLK) then
ADDR_To_ROM <= Call_Next_Instruction;
--EN_OUT <= '1';
--if falling_edge (CLK) then
--Instruction <= DATA_From_ROM;
--end if;
Next_State <= State_B;
--end if;
--#### STATE B #####
when State_B =>
EN_OUT <= '1';
Instruction <= DATA_From_ROM;
Instruction_Identifier <= (Instruction and Instruction_Finder);
case (Instruction_Identifier) is
when "00000000" => FF_Path <= '1';
when "01000000" => MUX_ALU_Path <= '1';
when "10000000" => BUS_A_B_Ports_Path <= '1';
when "11000000" => Reset_Path <= '1';
when others => null;
end case;
Next_State <= State_C after 40ns;
--#### STATE C #####
when State_C =>
--########
if ((FF_Path = '1') and (Counter = 2)) then
MUX_FF_Select <= "00";
end if;
if ((FF_Path = '1') and (Counter = 4)) then
MUX_FF_Select <= "00" after 20ns;
end if;
--########
if (falling_edge(CLK) and (MUX_ALU_Path = '1')) then
MUX1_Select <= "00";
MUX2_Select <= "00";
end if;
--########
if ( rising_edge(CLK) and BUS_A_B_Ports_Path = '1') then
if Counter = 1 then
BUS_Select <= "01";
end if;
if Counter = 3 then
BUS_Select <= "10";
end if;
EN_A_Ports <= '1';
EN_B_Ports <= '1';
end if;
--########
if ( rising_edge(CLK) and Reset_Path = '1') then
Reset <= '1';
end if;
Next_State <= State_D after 60ns;
--#### STATE D #####
when State_D =>
EN_OUT <= '0';
Counter <= Counter + 1;
if Counter > 5 then
Next_State <= State_D;
end if;
Call_Next_Instruction <= Counter;
Next_State <= State_A;
end case;
end process;
end Behavioral;
github link to code: https://github.com/quasarMind/StateMachine.git
Besides comments by Bill Lynch and Brian Drummond addressing synthesis eligibility a reason why the model gets all 'U's appears to revolve around multiple drivers for
Instruction_Finder, Counter and Call_Next_Instruction. One driver is initialized the other delivering all 'U's, the two resolve to all 'U's.
For purposes of simulating to see what your state machine actually does (and sidestepping the issue of synthesis), set default values for these three signals in their declarations and comment out the additional concurrent signal assignment statements, e.g.:
signal Counter : STD_LOGIC_VECTOR(5 downto 0) := (others => '0');
signal Instruction_Finder : STD_LOGIC_VECTOR (7 downto 0) := "11000000";
signal Call_Next_Instruction : STD_LOGIC_VECTOR(5 downto 0) := (others => '0');
-- Instruction_Finder <= "11000000";
-- Counter <= "000000";
-- Call_Next_Instruction <= "000000";
Most synthesis vendors will honor default values for signals for FPGA targets, otherwise you can add a reset.

Program Counter's Increment Won't Work

Everything works but the increment function. It can increment from 0 to 1, 1 to 2, and then from 2 it goes to "1111111111". I'm stumped.
Variables:
D_IN: Data in
PC_OE: Active high. Drives PC_TRI output.
PC_LD: Active high synchronously loads D_IN into PC.
PC_INC: Active high synchronously increments value in PC.
RST: Active high asyncronous reset.
PC_COUNT: Current value in PC. Address.
PC_TRI: Current value in the PC under tri-state control. When PC_OE = '1', PC_TRI <=
PC_COUNT, else high impedance.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
entity ProgramCounter is
Port ( D_IN : in STD_LOGIC_VECTOR (9 downto 0);
PC_OE : in STD_LOGIC;
PC_LD : in STD_LOGIC;
PC_INC : in STD_LOGIC;
RST : in STD_LOGIC;
CLK : in STD_LOGIC;
PC_COUNT : out STD_LOGIC_VECTOR (9 downto 0);
PC_TRI : out STD_LOGIC_VECTOR (9 downto 0));
end ProgramCounter;
architecture Behavioral of ProgramCounter is
signal s_COUNT : STD_LOGIC_VECTOR (9 downto 0);
begin
s_COUNT <= "0000000000";
proc: process(RST, CLK, PC_LD, D_IN, s_COUNT, PC_INC, PC_OE)
begin
if (RST = '1') then
s_COUNT <= "0000000000";
elsif (rising_edge(CLK)) then
if (PC_LD = '1') then
s_COUNT <= D_IN;
elsif (PC_INC = '1') then
s_COUNT <= s_COUNT + 1;
else
end if;
else
end if;
if (PC_OE = '1') then
PC_TRI <= s_COUNT;
else
PC_TRI <= "ZZZZZZZZZZ";
end if;
PC_COUNT <= s_COUNT;
end process proc;
end Behavioral;
The comment of QuantumRipple is very useful
begin
--s_COUNT <= "0000000000";
...
I tried to comment such line and it worked.
Try to do this, and make RST before start to count
Please try this way and let me know, i corrected your code but I can't try it :
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
entity ProgramCounter is
Port ( D_IN : in STD_LOGIC_VECTOR (9 downto 0);
PC_OE : in STD_LOGIC;
PC_LD : in STD_LOGIC;
PC_INC : in STD_LOGIC;
RST : in STD_LOGIC;
CLK : in STD_LOGIC;
PC_COUNT : out STD_LOGIC_VECTOR (9 downto 0);
PC_TRI : out STD_LOGIC_VECTOR (9 downto 0));
end ProgramCounter;
architecture Behavioral of ProgramCounter is
signal s_COUNT : STD_LOGIC_VECTOR (9 downto 0);
begin
proc: process(RST, CLK)
begin
if (RST = '1') then
s_COUNT <= "0000000000";
elsif (rising_edge(CLK)) then
if (PC_LD = '1') then
s_COUNT <= D_IN;
elsif (PC_INC = '1') then
s_COUNT <= s_COUNT + 1;
else
end if;
else
end if;
end process;
PC_TRI <= s_COUNT when (PC_OE = '1') else (others => 'Z');
PC_COUNT <= s_COUNT;
end Behavioral;

Why does VHDL shift register need 2 clock rising_edge to shift?

I'm trying to make a 8-bit shift register using D flipflop.
The problem is that when simulating it takes two clock rising edges for the register to shift, one for the D input to change, the other for the Q to change. I don't know why.
entity Registry_8 is
port (input : in std_logic;
output : out std_logic;
clk : in std_logic;
clear : in std_logic;
load : in std_logic;
LR : in std_logic;
pIn : in std_logic_vector (7 downto 0);
pOut : out std_logic_vector (7 downto 0);
shift : in std_logic);
end Registry_8;
architecture Behavioral of Registry_8 is
component D_flipflop
port(D, clk, clear, preset : in std_logic;
Q, Q_b : out std_logic);
end component;
signal D, Q : std_logic_vector (7 downto 0);
begin
GEN_FLIP :
for i in 0 to 7 generate
D_i : D_flipflop port map(clk => clk, preset => '0', clear => clear, D => D(i), Q => Q(i));
end generate GEN_FLIP;
process (clk, load, LR, shift)
begin
if (load = '1')
then D <= pIn;
end if;
if (clk'event and clk = '1' and shift = '1')
then
if (LR = '0')
then D(7 downto 0) <= Q(6 downto 0) & input;
output <= Q(7);
else
D(7 downto 0) <= input & Q(7 downto 1);
output <= Q(0);
end if;
end if;
end process;
pOut <= Q;
end Behavioral;
In the process, there is clock edge sensitive condition with the expression:
clk'event and clk = '1'
The process thereby implements an additional level of sequential logic (flip
flops), but you probably wanted to create a process for purely combinatorial
design, like:
process (all) is
begin
if (load = '1') then
D <= pIn;
end if;
if shift = '1' then
if (LR = '0') then
D(7 downto 0) <= Q(6 downto 0) & input;
output <= Q(7);
else
D(7 downto 0) <= input & Q(7 downto 1);
output <= Q(0);
end if;
end if;
end process;
Note that VHDL-2008 all is used as sensitivity list above, to automatically
include all signals used in a process for combinatorial design.

Resources