VHDL internal signal to change output - not working? - output

I have this PC module, very simple (Code at the end). I first generate some input signal port_int and at the end of the process say pc_out <= port_int. My goal is to either increment or add or subtract from PC, depending on input signals.
In the simulation, the internal port_int signal works fine, but pc_out doesn't. Why is this happening? Look at the simulation:
Look how port_int changes as it should, while pc_out is late. Later in the simulation, pc_out gets even worse, changing irregularly, not even just being late.
What am I doing wrong? Is there another way to change pc_out? Bcoz you can't change out signals, and I've been told that inout is extremely bad practice..
Here's the code:
entity PC is
Port ( clk : in STD_LOGIC;
enable : in STD_LOGIC;
reset : in STD_LOGIC;
pc_out : out STD_LOGIC_VECTOR (3 downto 0);
data : in STD_LOGIC_VECTOR (3 downto 0); -- jump value
zero : in STD_LOGIC; -- jump condition
jmp_en : in STD_LOGIC; -- jump enable
jmp_dir : in STD_LOGIC; -- jump direction
ctrl_en : out STD_LOGIC); -- output signal
end PC;
architecture Behavioral of PC is
type state_type is (s0, s1, s2, s3);
signal reg_state, next_state : state_type;
signal port_int : std_logic_vector(3 downto 0);
begin
state_transition: process(clk, reset)
begin
if (reset = '1') then
reg_state <= s0;
elsif(rising_edge(clk)) then
reg_state <= next_state;
end if;
end process;
next_state_logic: process(reg_state, enable)
begin
case reg_state is
when s0 =>
if(enable = '1') then
next_state <= s2;
else
next_state <= s1;
end if;
when s1 =>
if(enable = '1') then
next_state <= s2;
else
next_state <= s1;
end if;
when s2 =>
next_state <= s3;
when s3 =>
if(enable = '1') then
next_state <= s2;
else
next_state <= s1;
end if;
end case;
end process;
output_logic: process(reg_state, zero, jmp_en, jmp_dir, data)
begin
case reg_state is
when s0 =>
pc_out <= "0000";
port_int <= "0000";
ctrl_en <= '0';
when s1 =>
ctrl_en <= '0';
when s2 =>
if(zero = '1' and jmp_en = '1' and jmp_dir = '1')then
port_int <= port_int + data; -- jump forward
elsif(zero = '1' and jmp_en = '1' and jmp_dir = '0')then
port_int <= port_int - data; -- jump backward
else -- nije ispunjen uslov skoka
port_int <= port_int + '1'; -- increment PC
end if;
pc_out <= port_int;
when s3 =>
ctrl_en <= '1';
end case;
end process;
end Behavioral;
EDIT:
When I import the module in a whole processor, this happens:
the same pc_out signal acts strangely, adn all the inputs are the same. I use the pc_out signal just in one place, to select memory.
Why isn't it behaving normally? What could have caused this?

The second process (output_logic: process), which computes the output values, has some problems.
First, recall that it implements a combinational circuit (therefore, memoryless), so equations like port_int <= port_int + data can only be computed if the value of port_int is stored somewhere. By the way, after fixing the code, you can drop the internal signal port_int and use pc_out directly.
Second, being this process a combinational circuit, its full truth table must be specified; otherwise, latches will be inferred. Note, for example, that only the value of ctrl_en is specified in state s1. You must either specify all output values (same list) in all states or, equivalently, you can make a list of output values before the case statements, so the compiler will use them as default values when the values are not explicitly declared.

If I understand what you're trying to do correctly, you just need a single statement outside the process blocks:
pc_out <= port_int;
Take all other statements assigning something to pc_out out of your design. I think you're getting tripped up by the <= operator, which waits until the next simulation delta to actually update the signal driver.

Related

Declaring multiple cases with the same function?

I am a beginner to VHDL, started coding for a class I am in. I am working on a digital-alarm-bike lock, I am trying to find an efficient way to call this code, but I am currently getting a syntax error.
PROCESS (Clk, H)
BEGIN
CASE current_state IS
WHEN s0,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s63=>
IF H = "0" THEN
current_state <= s0;
END If;
WHEN s12,s13,s14,s15,s16,s17,s18,s19,s20,s21,s22,s23,s24,s25,s26,s27,s28,s29,s30,s31,s32,s33,s34,s35,s36,s37,s38,s39,s40,s41,s42,s43,s44,s45,s46,s47,s48,s49,s50,s51,s52,s53,s54,s55,s56,s57,s58,s59,s60,s61,s62=>
IF H = "0" THEN
current_state <= s52;
Elsif (rising_edge(Clk) THEN
current_state <= next_state;
END IF;
END CASE
END PROCESS;
Basically, those are state types, and I want to basically call all those states, and check them for the value of H, and certain condition will be called. However, I am getting this error:
ERROR:HDLParsers:164 - "(Directory///)" Line 50. parse error, unexpected COMMA, expecting PIPE or ROW
I can't use a comma, but does any experienced VHDL code know how to work around this so we do not have to explicitly repeat the code for each s-state?
If you'd looked a little harder, you could have found
WHEN s0 to s11|s63 =>
...
WHEN s12 to s62 =>
...
I found the solution for my own question hahaha.
There is a "pipe" symbol that allows for this operation.
PROCESS (Clk, H)
BEGIN
CASE current_state IS
WHEN s0|s1|s2|s3|s4|s5|s6|s7|s8|s9|s10|s11|s63=>
IF H = '0' THEN
current_state <= s0;
END If;
WHEN s12|s13|s14|s15|s16|s17|s18|s19|s20|s21|s22|s23|s24|s25|s26|s27|s28|s29|s30|s31|s32|s33|s34|s35|s36|s37|s38|s39|s40|s41|s42|s43|s44|s45|s46|s47|s48|s49|s50|s51|s52|s53|s54|s55|s56|s57|s58|s59|s60|s61|s62=>
IF H = '0' THEN
current_state <= s52;
Elsif (rising_edge(Clk)) THEN
current_state <= next_state;
END IF;
END CASE;
END PROCESS;

Vhdl Multiplier usage too low

My design utilizes the Spartan 3E XC35100E device. I can use a total of 4 MUX. However, despite using 3 * signs and a FFT block (which also uses 3 MUX), the design summary specifies that I only use 1 MUX. Even when I use CLB logic in place of MUX for the FFT block, the design summary is the same.
Implementation and simulation are able to take place without any problems. So, why is the number of MUX I use so low? Any help would be greatly appreciated.
relevant libraries, port maps and signal declarations are excluded for brevity.
process (clk)
variable fsm : integer range 0 to 3:= 0;
variable i : integer range 0 to 127:= 0;
begin
if rising_edge(clk) then
if fsm = 0 then
tasiyici <= STD_LOGIC_VECTOR(to_signed(sample_1(i)* sample_2(i) , 16));
--sample1 and sample 2 are arrays with constant values
fsm := fsm +1;
elsif fsm = 1 then
wea_select <= '0';
wea_ram<= "1";
ram_write <= '0';
dina <= STD_LOGIC_VECTOR(tasiyici(15 downto 8));
mult_out<= STD_LOGIC_VECTOR(tasiyici(15 downto 8));
fsm := fsm +1;
elsif fsm = 2 then
address_write <= std_logic_vector(unsigned(addra) + 1);
wea_ram<= "0";
i := i+1 ;
if i=128 then
fsm:=3;
ram_write <= '1';
wea_select <= '1';
else
fsm := 0;
end if;
end if;
end if;
end process;
----FFT process---
process(clk)
variable fsm : integer range 0 to 7:= 0;
variable i : integer range 0 to 128;
variable counter : integer range 0 to 2:= 0;
variable j : integer range 0 to 512;
begin
if rising_edge(clk) then
if fsm = 0 then -- ram_write is control
if ram_write = '1' then
wea_fft <= "0";
fsm:= 1;
end if;
elsif fsm = 1 then --process start (pulse)
start <= '1';
fwd_inv_we <= '1';
fsm := fsm +1;
elsif fsm = 2 then
start <= '0';
fwd_inv_we <= '0';
fsm := fsm +1;
elsif fsm =3 then --128 cycle send data from douta to xn_re
if i= 128 then
fsm := fsm +1;
else
xn_re <= douta;
address_read <= std_logic_vector(unsigned(addra) + 1);
i:=i+1;
fsm := 3;
end if;
elsif fsm =4 then --all data sent. process complete
if done = '1' then --wait for done finish 3 clk cycle, then unload
if counter= 2 then
fsm := fsm +1;
else
counter := counter +1;
fsm :=4;
end if;
end if;
elsif fsm =5 then
counter := 0;
unload <= '1';
fsm := fsm +1;
fft_data_ready <= "1";
wea_fft<= "1";
elsif fsm =6 then --wait 512 clk cycle to read all outputs
unload <= '0';
wea_fft<= "0";
if dv = '1' then
fft_output <= std_logic_vector(signed(xk_re(15 downto 4))*signed(xk_re(15 downto 4))
+signed(xk_im(15 downto 4))*signed(xk_im(15 downto 4)));
if j=512 then
fsm:=fsm+1;
else
j:=j+1;
fsm:=6;
end if;
else
fsm:=6;
end if;
end if;
end if;
end process;
It seems like your design has simply been optimized.
You should check the RTL that is synthesized to check that your design has been synthesized the way that you wanted

MYSQL trigger with if statements

I can't seem to make this trigger work.
CREATE TRIGGER class_check BEFORE INSERT ON Category
DECLARE x VARCHAR(1);
SET x = (SELECT Type1 FROM Category);
IF (x<>'A') THEN
CALL `'ERROR'`;
END IF;
IF (NEW.MxLen > 3 AND x ='M') THEN
CALL `'ERROR LENGTH MUST BE LESS THAN 3 FOR M CLASS LICENSE'`;
ELSEIF (NEW.MxLen > 5 AND x ='G') THEN
CALL `'ERROR LENGTH MUST BE LESS THAN 5 FOR G CLASS LICENSE'`;
ELSEIF (NEW.MxLen > 30) THEN
CALL `'ERROR LENGTH MUST BE LESS THAN 30 FOR A,B,C,D,E CLASS LICENSE'`;
END IF;
The trigger above doesn't work the way i want it to and I can't seem to find the problem.
Basically, I want it to check if the type1 in the Category table is Not A then shoot an error. Everytime I try to add A, it will still shoot the error.
Any help would be appreciated. I have the same for BEFORE UPDATE as well.
The backticks are escaping the name of whatever is between them, saying that it is an identifier. I doubt that you actually have any identifiers with these names. Just use the single quotes for the strings:
Normally, call would have stored procedure name after it. I am guessing that you really want signal to raise an error:
CREATE TRIGGER class_check BEFORE INSERT ON Category
DECLARE x VARCHAR(1);
SET x = (SELECT Type1 FROM Category);
IF (x <> 'A') THEN
SIGNAL '45000' SET MESSAGE_TEXT = 'ERROR';
END IF;
IF (NEW.MxLen > 3 AND x ='M') THEN
SIGNAL '45000' SET MESSAGE_TEXT = 'ERROR LENGTH MUST BE LESS THAN 3 FOR M CLASS LICENSE';
ELSEIF (NEW.MxLen > 5 AND x ='G') THEN
SIGNAL '45000' SET MESSAGE_TEXT = 'ERROR LENGTH MUST BE LESS THAN 5 FOR G CLASS LICENSE';
ELSEIF (NEW.MxLen > 30) THEN
SIGNAL '45000' SET MESSAGE_TEXT = 'ERROR LENGTH MUST BE LESS THAN 30 FOR A,B,C,D,E CLASS LICENSE';
END IF;
Also, it is not clear what this line does:
SET x = (SELECT Type1 FROM Category);
It is likely to return an error if more than one row is in Category.

VHDL 4-bit binary divider

I am trying to make a binary divider to be part of a calculator using VHDL, I have written the code that I think should work but have been stuck for hours, can someone please help me.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Div is
Port ( Ain : in STD_LOGIC_VECTOR (3 downto 0);
Bin : in STD_LOGIC_VECTOR (3 downto 0);
Q : out STD_LOGIC_VECTOR (3 downto 0);
R : out STD_LOGIC_VECTOR (3 downto 0));
end Div;
architecture Behavioral of Div is
Signal Atemp : Std_Logic_Vector (3 downto 0);
begin
Proc1: Process (Ain,Bin, Atemp)
variable cnt : STD_LOGIC_Vector(3 downto 0);
begin
if (Ain < Bin) then
cnt := "0000";
Atemp <= Ain;
elsif (Ain = Bin) then
cnt := "0001";
elsif (Ain > Bin) then
cnt := "0001";
Atemp <= (Ain - Bin);
while (Atemp >= Bin) loop
if(Atemp >=Bin) then
Atemp <= (Atemp - Bin);
cnt := cnt + "0001";
end if;
end loop;
end if;
Q <= cnt;
R <= Atemp;
end process Proc1;
end Behavioral;
In the iteration part of the divide process, when Ain > Bin, the assign
Atemp <= (Ain - Bin) is always performed, even if the iteration should be
completed. Process that assign to a signal also in the sensitivity list, is
hard to get right.
The code may be updated with Atemp as a variable instead, some other
simplifications with removal of unrequired code, and adding value for remainder
when Ain = Bin, resulting in architecture as:
architecture Behavioral of Div is
begin
Proc1 : process (Ain, Bin) is
variable cnt : std_logic_vector(3 downto 0);
variable Atemp : std_logic_vector(3 downto 0);
begin
if (Ain < Bin) then
cnt := "0000";
Atemp := Ain;
elsif (Ain = Bin) then
cnt := "0001";
Atemp := (others => '0'); -- Added to give correct remainder
elsif (Ain > Bin) then
cnt := "0001";
Atemp := (Ain - Bin);
while (Atemp >= Bin) loop
-- Removed trivial true if statement, since condition identical to condition in while
Atemp := (Atemp - Bin);
cnt := cnt + "0001";
end loop;
end if;
Q <= cnt;
R <= Atemp;
end process Proc1;
end Behavioral;
The inner process statements may actually be reduced to:
cnt := "0000";
Atemp := Ain;
while (Atemp >= Bin) loop
Atemp := (Atemp - Bin);
cnt := cnt + "0001";
end loop;
Q <= cnt;
R <= Atemp;
Whether this will synthesize to the required frequency with the unrolled
while is another question, that depends on the target frequency and
technology.
An alternative solution, given the short Ain and Bin, is to implement the
divider using a constant lookup table, with address as Ain & Bin and output
of Q & R. This will evaluate in fixed time, and synthesis is very likely to
reduce considerably if made as combinatorial logic.
Last comment is that you may also want to handle division by zero, when Bin
is zero.
To prevent mistakes, it is advisable to use explicitly the type unsigned or signed when implementing arithmetic circuits. The numeric_std package contains the following arithmetic operators for these types: +, -, *, /, abs, rem, mod.
Below is a suggested code (for unsigned division). Note that some lines in the arch can be eliminated, but were used to make the code more "didactic".
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity divider is
generic (size: natural := 4);
port (
A: in std_logic_vector(size-1 downto 0);
B: in std_logic_vector(size-1 downto 0);
Q: out std_logic_vector(size-1 downto 0);
R: out std_logic_vector(size-1 downto 0));
end entity;
architecture direct of divider is
signal Auns, Buns, Quns, Runs: unsigned(size-1 downto 0);
begin
--Convert inputs to unsigned:
Auns <= unsigned(A);
Buns <= unsigned(B);
--Do the division:
Quns <= Auns/Buns;
Runs <= Auns rem Buns; --Or: Runs <= Auns - resize(Quns*Buns, size);
--Covert results to std_logic_vector:
Q <= std_logic_vector(Quns);
R <= std_logic_vector(Runs);
end architecture

Synthesis warning in VHDL multiplier code

When I synthesize this 32-bit multiplier code, I do not get any errors, just warnings that my input is not used and is assigned but not used. My code is this:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity multiplier is
Port ( multiplicand : in STD_LOGIC_VECTOR(31 downto 0);
multiply : in STD_LOGIC_VECTOR(31 downto 0);
clk : in STD_LOGIC;
product : out STD_LOGIC_VECTOR(63 downto 0));
end multiplier;
architecture Behavioral of multiplier is
component adder32bit is
port(addone, addtwo : in STD_LOGIC_VECTOR(31 downto 0);
sum : out STD_LOGIC_VECTOR(31 downto 0);
cout : out STD_LOGIC);
end component;
signal tempsum : STD_LOGIC_VECTOR(31 downto 0);
signal preg : STD_LOGIC_VECTOR(63 downto 0);
signal start : STD_LOGIC := '1';
signal tempcout : STD_LOGIC;
signal counter : integer := 1;
begin
addN: adder32bit port map(multiplicand, preg(63 downto 32), tempsum, tempcout);
process(clk)
begin
if(rising_edge(clk)) then
if(start = '1') then
if(counter = 1) then
preg <= "00000000000000000000000000000000" & multiply;
end if;
if(preg(0) = '1') then
preg(63 downto 32) <= tempsum;
preg <= tempcout & preg(63 downto 1);
else
preg <= '0' & preg(63 downto 1);
end if;
counter <= counter + 1;
if(counter = 33) then
product <= preg;
start <= '0';
counter <= 1;
end if;
end if;
end if;
end process;
end Behavioral;
When I run the simulation, no matter what my two inputs are (multiplicand and multiply) the output will be like this: "0000...UUUUUUU"
Any suggestions as to what I should do here?
One way to initialise preginvolves just a minor change to your code...
if(counter = 1) then
preg <= "00000000000000000000000000000000" & multiply;
else
if(preg(0) = '1') then ...
end if;