I've been trying to write some code for a lab i need to do this week but ran into the error mentioned in the title (image below). The code just needs to cycle new inputs through 4 registers and checking to see which is the largest and smallest of the set. The following code is what I was using when i got the errors;
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity max_min is
port(
din : in std_logic_vector(3 downto 0);
reset : in std_logic;
clk : in std_logic;
sel : in std_logic_vector(1 downto 0);
max_out : out std_logic_vector(3 downto 0);
min_out : out std_logic_vector(3 downto 0);
reg_out : out std_logic_vector(3 downto 0)
);
end max_min ;
architecture arch of max_min is
signal R0,R1,R2,R3 : std_logic_vector(3 downto 0);
begin
--Reset and register cycle
process(clk,reset)
begin
if(reset = '1') then
R0 <= "1000";
R1 <= "1000";
R2 <= "1000";
R3 <= "1000";
max_out <= "0000";
min_out <= "0000";
elsif(clk'event and clk = '1') then
if(R0 /= din) then
R3 <= R2;
R2 <= R1;
R1 <= R0;
R0 <= din;
end if;
end if;
end process;
--Greater Than logic
process(clk)
begin
if(clk'event and clk = '1') then
if(R0 >= R1 and R0 >= R2 and R0 >= R3) then
max_out <= R0;
elsif(R1 >= R0 and R1 >= R2 and R1 >= R3) then
max_out <= R1;
elsif(R2 >= R0 and R2 >= R1 and R2 >= R3) then
max_out <= R2;
elsif(R3 >= R0 and R3 >= R1 and R3 >= R2) then
max_out <= R3;
end if;
end if;
end process;
--Less Than logic
process(clk)
begin
if(clk'event and clk = '1') then
if(R0 <= R1 and R0 <= R2 and R0 <= R3) then
min_out <= R0;
elsif(R1 <= R0 and R1 <= R2 and R1 <= R3) then
min_out <= R1;
elsif(R2 <= R0 and R2 <= R1 and R2 <= R3) then
min_out <= R2;
elsif(R3 <= R0 and R3 <= R1 and R3 <= R2) then
min_out <= R3;
end if;
end if;
end process;
--Register Select
process(clk,sel)
begin
if(clk'event and clk = '1') then
case sel is
when "00" =>
reg_out <= R0;
when "01" =>
reg_out <= R1;
when "10" =>
reg_out <= R2;
when "11" =>
reg_out <= R3;
when others =>
reg_out <= "0000";
end case;
end if;
end process;
end arch;
The following is the set of errors i got when running the above code in Precision RTL;
I'm not very experienced with VHDL yet, so i'm not sure what these errors mean or what i may have done wrong. The code didn't seem to have any errors when i ran it through Modelsim.
Problem solved. I had max_out and min_out in two separate processes. Once i merged them all into one process it fixed itself.
Thank you to all the commenters for their advice.
Related
I am trying to do an "add and shift multiplier (sequential)" and I am having problems on the final simulation, the value on the output goes always wrong. I've used a state machine logic to make the control block of the partial sums.
When I make 1 x 1 the output goes wrong (for all products goes wrong) :
Output Error on VWF File
This error appears for all multiplicand and multiplier inputs.
I am using the following code to make the sums:
library IEEE;
use IEEE.std_logic_1164.all;
entity adder_8bits is
port (
cin: in STD_LOGIC;
a,b: in STD_LOGIC_VECTOR(7 DOWNTO 0);
s: out STD_LOGIC_VECTOR(8 DOWNTO 0)
);
end adder_8bits;
architecture arch_1 of adder_8bits is
begin
process(a,b,cin)
variable soma:std_logic_vector(8 downto 0);
variable c:std_logic;
begin
c := cin;
for i in 0 to 7 loop
soma(i) := a(i) xor b(i) xor c;
c := (a(i) and b(i)) or ((a(i) xor b(i)) and c);
end loop;
s(7 downto 0) <= soma(7 downto 0);
s(8) <= c;
end process;
end arch_1;
A 8 bit adder to sum the partial results.
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity sum_register is
port (
i_DIN : in UNSIGNED(8 DOWNTO 0);
i_LOAD : in STD_LOGIC;
i_CLEAR : in STD_LOGIC;
i_SHIFT : in STD_LOGIC;
i_CLK : in STD_ULOGIC;
o_DOUT : buffer UNSIGNED(15 downto 0)
);
end sum_register;
architecture arch_1 of sum_register is
begin
process(i_CLK)
begin
IF rising_edge(i_CLK) THEN
IF (i_CLEAR = '1') THEN
o_DOUT <= "0000000000000000";
ELSIF (i_LOAD = '1') THEN
o_DOUT(15 downto 7) <= i_DIN;
ELSIF (i_SHIFT = '1') THEN
IF (i_DIN(8) = '1') THEN
o_DOUT <= o_DOUT SRL 1;
END IF;
END IF;
END IF;
end process;
end arch_1;
A sum register to get the actual sum value and shift before the other sum.
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.std_logic_unsigned.ALL;
use IEEE.std_logic_arith.ALL;
ENTITY controller IS
PORT (
i_CLK : IN STD_ULOGIC;
i_START : IN STD_LOGIC;
i_MLTPLR : IN STD_LOGIC_VECTOR(7 downto 0);
o_MDLD : OUT STD_LOGIC;
o_MRLD : OUT STD_LOGIC;
o_RSLD : OUT STD_LOGIC;
o_RSCLR : OUT STD_LOGIC;
o_RSSHR : OUT STD_LOGIC
);
END controller;
ARCHITECTURE arch_1 OF controller IS
TYPE state_type IS (s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18);
SIGNAL stateT : state_type;
BEGIN
PROCESS(i_CLK)
BEGIN
IF rising_edge(i_CLK) THEN
IF (i_START = '0') THEN
stateT <= s0;
ELSE
CASE stateT IS
when s0 => if (i_START = '1') then
stateT <= s1;
end if;
when s1 => stateT <= s2;
when s2 => if (i_MLTPLR(0) = '1') then
stateT <= s3;
else
stateT <= s4;
end if;
when s3 => stateT <= s4;
when s4 => if (i_MLTPLR(1) = '1') then
stateT <= s5;
else
stateT <= s6;
end if;
when s5 => stateT <= s6;
when s6 => if (i_MLTPLR(2) = '1') then
stateT <= s7;
else
stateT <= s8;
end if;
when s7 => stateT <= s8;
when s8 => if (i_MLTPLR(3) = '1') then
stateT <= s9;
else
stateT <= s10;
end if;
when s9 => stateT <= s10;
when s10 => if (i_MLTPLR(4) = '1') then
stateT <= s11;
else
stateT <= s12;
end if;
when s11 => stateT <= s12;
when s12 => if (i_MLTPLR(5) = '1') then
stateT <= s13;
else
stateT <= s14;
end if;
when s13 => stateT <= s14;
when s14 => if (i_MLTPLR(6) = '1') then
stateT <= s15;
else
stateT <= s16;
end if;
when s15 => stateT <= s16;
when s16 => if (i_MLTPLR(7) = '1') then
stateT <= s17;
else
stateT <= s18;
end if;
when s17 => stateT <= s18;
when s18 => stateT <= s0;
END CASE;
END IF;
END IF;
END PROCESS;
o_MDLD <= '1' when (stateT = s1) else '0';
o_MRLD <= '1' when (stateT = s1) else '0';
o_RSCLR <= '1' when (stateT = s1) else '0';
o_RSLD <= '1' when (stateT = s3 or stateT = s5 or
stateT = s7 or stateT = s9 or
stateT = s11 or stateT = s13 or
stateT = s15 or stateT = s17) else '0';
o_RSSHR <= '1' when (stateT = s4 or stateT = s6 or
stateT = s8 or stateT = s10 or
stateT = s12 or stateT = s14 or
stateT = s16 or stateT = s18) else '0';
END arch_1;
A state machine controller to control the inputs signal from de sum register.
I am using a BDF file to connect all the blocks, the only difference from the schematic below is that in the adder block has a carry in input.
The clock of all blocks are in the same pin.
Controller simulation
Anyone have any idea what is causing this error?
When implementing your answer:
architecture arch_1 of sum_register is
begin
process(i_CLK)
begin
IF rising_edge(i_CLK) THEN
IF (i_CLEAR = '1') THEN
o_DOUT <= "0000000000000000";
ELSIF (i_LOAD = '1') THEN
o_DOUT(15 downto 8) <= i_DIN;
ELSIF (i_SHIFT = '1') THEN
o_DOUT <= o_DOUT SRL 1;
END IF;
END IF;
end process;
end arch_1;
what happens when you multiply 255 x 255?
Your product is 1 (which would be correct if this were a signed multiply, you specified unsigned multiplier and multiplicand, where the correct answer would be 65025 ("1111111000000001"). Because you have separate load and shift operations you need to save that discarded carry and use it on a shift in. And because you can have successive multiplier bits that are '0' you need to clear that carry after it's used in a shift instruction (defaulting to the expected sign, which is '0' for unsigned multiplies).
You can do that with your original 9 bit path for the adder_8bits sum and saving the carry:
architecture foo of sum_register is
signal carry: std_logic;
begin
process (i_clk)
begin
if rising_edge(i_clk) then
if i_clear = '1' then
o_dout <= (others => '0');
carry <= '0';
elsif i_load = '1' then
o_dout(15 downto 8) <= i_din (7 downto 0);
carry <= i_din(8);
elsif i_shift = '1' then
o_dout <= carry & o_dout(15 downto 1);
carry <= '0'; -- expected sign for multiply result
end if;
end if;
end process;
end architecture;
Note that it's cleared when consumed, requiring a preceding load to interject carry = '1'.
And this contrivance could go away if you have two a load-and-shift load and a load instruction instead of a load instruction and shift instruction. It would require switching from a Moore state machine to a Mealy state machine and reduce the number of states.
You're controller, a Moore state machine can traverse 16 states both shifting and loading for a multiplier of "11111111", a Mealy machine could do that in 8 states with the shift-and-load and shift operations in sum_register.
And the sum_register would look something like:
architecture fum of sum_register is
begin
process (i_clk)
begin
if rising_edge(i_clk) then
if i_clear = '1' then
o_dout <= (others => '0');
elsif i_load_shift = '1' then
o_dout(15 downto 7) <= i_din & o_dout (6 downto 1);
elsif i_shift = '1' then
o_dout <= '0' & o_dout(15 downto 1); -- '0' expected result sign
end if;
end if;
end process;
end architecture;
for a 9 bit sum from adder_8bits. Note the i_load signal is renamed to i_load_shift and controller state machine would need to be re-written as a Mealy machine issuing either i_load_shift = '1' or i_shift = '1' and the other '0' depending on whether the evaluated multiplier bit is a '1' or a '0'.
Note there are plenty of hints here how to signed multiplies even though you declared the multiplier, multiplicand and product as unsigned.
The problem was in the sum_register, i was sending the carry out bit of the adder to the sum register, so this makes the output goes wrong, i just take out the carry out from the byte sent to the sum register.
s <= soma;
and variable soma from the adder was changed to 8 bits:
variable soma:std_logic_vector(7 downto 0);
The sum register was changed to receive only 8 bits from the adder:
architecture arch_1 of sum_register is
begin
process(i_CLK)
begin
IF rising_edge(i_CLK) THEN
IF (i_CLEAR = '1') THEN
o_DOUT <= "0000000000000000";
ELSIF (i_LOAD = '1') THEN
o_DOUT(15 downto 8) <= i_DIN;
ELSIF (i_SHIFT = '1') THEN
o_DOUT <= o_DOUT SRL 1;
END IF;
END IF;
end process;
end arch_1;
With this changes the simulation goes ok!
I build a 4 bit sequence detector with a 16-bit input.
I wanna now how often the sequence appears in the 16 bits.
For that I use this code:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
ENTITY seqdec IS
PORT ( X: IN std_logic_vector(15 DOWNTO 0);
CLK: IN std_logic;
RESET:IN std_logic;
LOAD: IN std_logic;
Y: OUT std_logic);
END seqdec;
ARCHITECTURE SEQ OF seqdec IS
TYPE statetype IS (s0, s1, s2, s3, s4);
SIGNAL state, next_state: statetype;
SIGNAL counter: std_logic_vector(3 DOWNTO 0) :="0000" ;
SIGNAL temp: std_logic_vector(15 DOWNTO 0);
SIGNAL so: std_logic;
BEGIN
STATE_AKT: PROCESS (CLK, RESET)
BEGIN
IF RESET = '1' THEN
state <= s0 ;
counter <= (OTHERS => '0') ;
ELSIF CLK = '1' AND CLK'event THEN
state <= next_state ;
END IF;
END PROCESS STATE_AKT;
PISO: PROCESS (CLK, LOAD, X)
BEGIN
IF (LOAD = '1') THEN
temp(15 DOWNTO 0) <= X(15 DOWNTO 0);
ELSIF (CLK'event and CLK='1') THEN
so <= temp(15) ;
temp(15 DOWNTO 1) <= temp(14 DOWNTO 0);
temp(0) <= '0';
END IF;
END PROCESS PISO;
STATE_CAL: PROCESS (so,state)
BEGIN
CASE state IS
WHEN s0 => IF so = '0' THEN next_state <= s0 ;
ELSE next_state <= s1 ;
END IF;
WHEN s1 => IF so = '0' THEN next_state <= s1;
ELSE next_state <= s2 ;
END IF;
WHEN s2 => IF so = '0' THEN next_state <= s3 ;
ELSE next_state <= s2 ;
END IF;
WHEN s3 => IF so = '0' THEN next_state <= s0 ;
ELSE next_state <= s4 ;
END IF;
WHEN s4 => IF so = '0' THEN next_state <= s0;
ELSE next_state <= s2 ;
END IF;
WHEN OTHERS => NULL;
END CASE;
END PROCESS STATE_CAL;
STATE_Y: PROCESS (state)
BEGIN
CASE state IS
WHEN s4 =>
Y <= '1';
counter <= counter + '1';
WHEN OTHERS => Y <= '0' ;
END CASE;
END PROCESS STATE_Y;
END SEQ;
But neither my counter reset nor my incrementation of counter is working.
The rest is working perfect and fine.
Has somebody a hint or an idea for me?
The programm is now working fine in ModelSim, but I struggle with getting it on the board.
I simulated it several times in ModelSim, with different parameters and it works fine, so the functional part is fine.
My code looks now this way:
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
ENTITY seqdec IS
PORT ( X: IN std_logic_vector(15 DOWNTO 0);
CLK: IN std_logic;
RESET: IN std_logic;
LOAD: IN std_logic;
DIGIT: OUT std_logic_vector(6 DOWNTO 0) := "1111110";
COUT: OUT std_logic_vector(2 DOWNTO 0);
Y: OUT std_logic);
END seqdec;
ARCHITECTURE SEQ OF seqdec IS
TYPE statetype IS (s0, s1, s2, s3, s4);
SIGNAL state: statetype;
SIGNAL next_state: statetype:=s0;
SIGNAL counter: std_logic_vector(2 DOWNTO 0) :="000" ;
SIGNAL temp: std_logic_vector(15 DOWNTO 0);
SIGNAL so: std_logic := 'U';
-------------------Aktualisierung des Zustandes--------------------------------
BEGIN
STATE_AKT: PROCESS (CLK, RESET)
BEGIN
IF RESET = '1' THEN
state <= s0;
ELSIF CLK = '1' AND CLK'event THEN
state <= next_state ;
END IF;
END PROCESS STATE_AKT;
---------------------Counter---------------------------------------------------
COUNT: PROCESS (state, RESET)
BEGIN
IF (RESET = '1') THEN
counter <= (OTHERS => '0');
ELSIF (state = s4) THEN
counter <= counter + '1';
COUT <= counter;
END IF;
END PROCESS COUNT;
-------------------PiSo für die Eingabe des zu Prüfenden Vektors---------------
PISO: PROCESS (CLK, LOAD, X)
BEGIN
IF (LOAD = '1') THEN
temp(15 DOWNTO 0) <= X(15 DOWNTO 0);
ELSIF (CLK'event and CLK='1') THEN
so <= temp(15);
temp(15 DOWNTO 1) <= temp(14 DOWNTO 0);
temp(0) <= '0';
END IF;
END PROCESS PISO;
-------------------Zustandsabfrage und Berechnung------------------------------
STATE_CAL: PROCESS (so,state)
BEGIN
CASE state IS
WHEN s0 => IF so = '0' THEN next_state <= s0 ;
ELSIF (so = '1') THEN next_state <= s1 ;
END IF;
WHEN s1 => IF so = '0' THEN next_state <= s1;
ELSIF (so = '1') THEN next_state <= s2 ;
END IF;
WHEN s2 => IF so = '0' THEN next_state <= s3 ;
ELSIF (so = '1') THEN next_state <= s2 ;
END IF;
WHEN s3 => IF so = '0' THEN next_state <= s0 ;
ELSIF (so = '1') THEN next_state <= s4 ;
END IF;
WHEN s4 => IF so = '0' THEN next_state <= s0;
ELSIF (so = '1') THEN next_state <= s2 ;
END IF;
WHEN OTHERS => NULL;
END CASE;
END PROCESS STATE_CAL;
-------------------Ausgang-----------------------------------------------------
STATE_Y: PROCESS (state)
BEGIN
CASE state IS
WHEN s4 =>
Y <= '1';
WHEN OTHERS => Y <= '0' ;
END CASE;
END PROCESS STATE_Y;
-------------------7 Segment---------------------------------------------------
SEVEN_SEG: PROCESS (counter, CLK)
BEGIN
IF (RESET = '1') THEN
DIGIT <= "1111110";
END IF;
CASE counter IS
WHEN "000" => DIGIT <= "1111110";
WHEN "001" => DIGIT <= "0110000";
WHEN "010" => DIGIT <= "1101101";
WHEN "011" => DIGIT <= "1111001";
WHEN "100" => DIGIT <= "0110011";
WHEN "101" => DIGIT <= "1011011";
WHEN OTHERS => NULL;
END CASE;
END PROCESS SEVEN_SEG;
END SEQ;
When i put it on the board the 7-segment will show a "3".
I would assume, as the functional part seems to be good,that it has to do somethink with the timings, but i can't find any solution to it. If some experience VHDL-programmer could give me a new hint that would be great.
Best regards
Adrian
Hi I am a new Xilinx user and been having trouble with how to write stimulus/simulate in a test bench. My output(Kd) isn't giving me any sensible values and gives 'u' for the first few clock cycles before moving and staying at '1' throughout.
Not sure if I have written the correct stimulus but hoping someone would help me out here!
My VHDL code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity codeFig2b is
Port ( R0 : in STD_LOGIC;
R1 : in STD_LOGIC;
R2 : in STD_LOGIC;
R3 : in STD_LOGIC;
Kd : out STD_LOGIC;
clock : in STD_LOGIC);
end codeFig2b;
architecture Behavioral of codeFig2b is
signal Qa, Qb: STD_LOGIC;
begin
process(clock, R0, R1, R2, R3)
begin
if clock = '1' and clock'event then
Qa <= (R0 or R1 or R2 or R3) or (Qa and Qb);
Qb <= Qa;
end if;
end process;
Kd <= Qa and Qb;
end Behavioral;
My 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.numeric_std.ALL;
ENTITY codeFig2b_test IS
END codeFig2b_test;
ARCHITECTURE behavior OF codeFig2b_test IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT codeFig2b
PORT(
R0 : IN std_logic;
R1 : IN std_logic;
R2 : IN std_logic;
R3 : IN std_logic;
Kd : OUT std_logic;
clock : IN std_logic
);
END COMPONENT;
--Inputs
signal R0 : std_logic := '0';
signal R1 : std_logic := '0';
signal R2 : std_logic := '0';
signal R3 : std_logic := '0';
signal clock : std_logic := '0';
--Outputs
signal Kd : std_logic;
-- Clock period definitions
constant clock_period : time := 100 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: codeFig2b PORT MAP (
R0 => R0,
R1 => R1,
R2 => R2,
R3 => R3,
Kd => Kd,
clock => clock
);
-- Clock process definitions
clock_process :process
begin
clock <= '0';
wait for clock_period/2;
clock <= '1';
wait for clock_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
wait for 100 ns;
R0 <= '0';
R1 <= '0';
R2 <= '0';
R3 <= '0';
wait for 100 ns;
R0 <= '0';
R1 <= '0';
R2 <= '0';
R3 <= '1';
wait for 100 ns;
R0 <= '0';
R1 <= '0';
R2 <= '1';
R3 <= '0';
wait for 100 ns;
R0 <= '0';
R1 <= '0';
R2 <= '1';
R3 <= '1';
wait for 100 ns;
R0 <= '0';
R1 <= '1';
R2 <= '0';
R3 <= '0';
wait for 100 ns;
R0 <= '0';
R1 <= '1';
R2 <= '0';
R3 <= '1';
wait for 100 ns;
R0 <= '0';
R1 <= '1';
R2 <= '1';
R3 <= '0';
wait for 100 ns;
R0 <= '0';
R1 <= '1';
R2 <= '1';
R3 <= '1';
wait for 100 ns;
R0 <= '1';
R1 <= '0';
R2 <= '0';
R3 <= '0';
wait for 100 ns;
R0 <= '1';
R1 <= '0';
R2 <= '0';
R3 <= '1';
wait for 100 ns;
R0 <= '1';
R1 <= '0';
R2 <= '1';
R3 <= '0';
wait for 100 ns;
R0 <= '1';
R1 <= '0';
R2 <= '1';
R3 <= '1';
wait for 100 ns;
R0 <= '1';
R1 <= '1';
R2 <= '0';
R3 <= '0';
wait for 100 ns;
R0 <= '1';
R1 <= '1';
R2 <= '0';
R3 <= '1';
wait for 100 ns;
R0 <= '1';
R1 <= '1';
R2 <= '1';
R3 <= '0';
wait for 100 ns;
R0 <= '1';
R1 <= '1';
R2 <= '1';
R3 <= '1';
wait for clock_period*10;
-- insert stimulus here
wait;
end process;
END;
This can be answered without simulating. Kd's output will go to a '1' and stay there.
process(clock, R0, R1, R2, R3)
begin
if clock = '1' and clock'event then
Qa <= (R0 or R1 or R2 or R3) or (Qa and Qb);
Qb <= Qa;
end if;
end process;
Kd <= Qa and Qb;
Qa goes high for any of R0, R1, R2 or R2 or (Qa and Qb);
So once Qa and Qb goes high Qa stays high.
Qb goes high one clock after the first occurrence of Qa going high.
The way this happens is o consecutive '1' inputs on any of R0, R1, R2 or R3.
You clock period is 100 ns and your stimulus interval is too.
You have no stimulus following the first clock where all of R0, R1, R2 and R3 are all low at the same time to demonstrate.
Unfortunately the waveform image on your Xilinx post (iSIM output Unintialised, doesn't change states.) doesn't show QA and Qb to see that they both go high and stay there:
(clickable)
When you add them this point comes through:
clickable)
What you built is a sequential logic, meaning that the outputs depend on the previous hystory of the inputs/outputs. In your case we have Qa, and Qb which is the last value of Qa.
Keeping this in mind, the approach you have used in the testbench is not optimal, because you are trying every combination of the inputs without taking into account that the last Qa is actually important.
This is what happens:
Start : Qa = U Qb = U => Kb = U
Inputs 1: Qa = 1 Qb = U => Kb = U
Inputs 2: Qa = 1 Qb = 1 => Kb = 1
Inputs 3: Qa = 1 Qb = 1 => Kb = 1
Inputs 4: Qa = 1 Qb = 1 => Kb = 1
....
As soon as one of the Rs goes high, Qa is high. Given the order of your combinations of inputs, there is no case where Qa goes low again.
This means that after the second input combination, Qb gets a known value and Kb goes high.
Sensitivity list
This is not part of the answer but it's a consideration on the code you have written: you have put on the sensitivity list R0, R1, R2, R3 but, given what you have written after that, this is not necessary.
The process does something only if
if clock'event and clock = 1 then
this means that any event on the Rs are ignored. I'm sure that the synthetizer actually realizes that and ignores it, but it's a good practice to set a proper sensitivity list and, when possible, only use clocked processes for sequential logic and finite state machines.
I also suggest that you use the more readable rising_edge(clock) and falling_edge(clock) functions:
process(clock)
begin
if rising_edge(clock) then
Qa <= R0 or R1 or R2 or R3 or (Qa and Qb);
Qb <= Qa;
end if;
end process;
Signals and processes
Another thing you should know is how the process work: you are not assigning new values to the signals, but rather planning values for them. If you reprogram a certain signal you are just overwriting the previous planning, and the first value is never assigned. The values are finally assigned at the end of the process.
Here is a simple example:
-- Let's assume A = 0 and B = 0 at startup
clocked_process : process(clk)
begin
if rising_edge(clk) then
A <= '1';
B <= A;
A <= '0';
end if;
end process;
At the end B is still 0, this because A = 0 for the whole process and only gets a planned value of 1, actually never assigned because it is overwritten before the end of the process (in this specific case the synthetizer will ignore A <= '1' for the implementation).
Overwriting the planned value can be used to simplify the logic: what I usually do is setting some default values and then overwriting them only when I need to.
So, instead of writing
...
case A is
when "00" =>
B <= '0';
when "01" =>
B <= '0';
when "10" =>
B <= '0';
when "11" =>
B <= '1';
end case;
...
I write this (I may retain the case structure if I need it for other signals, typically in Finite State Machines):
...
B <= '0';
if A = "11" then
B <= '1';
end if;
...
For this simple examples the synthetizer may be able to infer the semplification. However, you should get used to think in logic level ports because the same thing written in two equivalent ways from a behavioral point of view, is actually implemented differently.
Please help me with checking this code for correcting error using hamming code in VHDL. I have being able to detect error but not correct it.
I have three modules my encoder, decoder and an error injector. I have a feeling it my decoder that is having issues. Below is my decoder code
library ieee;
use ieee.std_logic_1164.all;
entity hamdec8 is
port(
datain: in std_logic_vector (7 downto 0);
parin : in std_logic_vector(4 downto 0);
Dataout : out std_logic_vector(7 downto 0);
Parout : out std_logic_vector(4 downto 0);
NE : out std_logic;
DED : out std_logic;
SEC : out std_logic
);
Constant MaskP1 : std_logic_vector(7 downto 0) := "01011011";
Constant MaskP2 : std_logic_vector(7 downto 0) := "01101101";
Constant MaskP3 : std_logic_vector(7 downto 0) := "10001110";
Constant MaskP4 : std_logic_vector(7 downto 0) := "11110000";
end hamdec8;
architecture beh of hamdec8 is
signal synd : std_logic_vector(4 downto 1);
signal P0 : std_logic;
signal din1, din2, din3, din4 : std_logic_vector(7 downto 0); --to hold datain AND maskp
begin
process(Datain, Parin)
begin
NE <= '1';
DED <= '0';
SEC <= '0';
Dataout <= Datain;
Parout <= Parin;
P0 <= (Parin(0) XOR Parin(1) XOR Parin(2) XOR Parin(3) XOR
Parin(4) XOR Datain(0) XOR Datain(1) XOR Datain(2) XOR
Datain(3) XOR Datain(4) XOR Datain(5) XOR Datain(6) XOR
Datain(7));
din1 <= Datain AND MaskP1;
Synd(1) <= din1(0) XOR din1(1) XOR din1(2) XOR din1(3) XOR
din1(4) XOR din1(5) XOR din1(6) XOR din1(7) XOR Parin(1);
din2 <= Datain AND MaskP2;
Synd(2) <= din2(0) XOR din2(1) XOR din2(2) XOR din2(3) XOR
din2(4) XOR din2(5) XOR din2(6) XOR din2(7) XOR Parin(2);
din3 <= Datain AND MaskP3;
Synd(3) <= din3(0) XOR din3(1) XOR din3(2) XOR din3(3) XOR
din3(4) XOR din3(5) XOR din3(6) XOR din3(7) XOR Parin(3);
din4 <= Datain AND MaskP4;
Synd(4) <= din4(0) XOR din4(1) XOR din4(2) XOR din4(3) XOR
din4(4) XOR din4(5) XOR din4(6) XOR din4(7) XOR Parin(4);
if (synd = "0000") then
IF (P0 = '0') then
--Dataout <= Datain;
--NE <= '1';
--DED <= '0';
--SEC <= '0';
--Parout <= Parin;
null;
elsif (P0 = '1') then --single error
NE <= '0';
DED <= '0';
SEC <= '1';
case synd is
when "0000" => Parout(0) <= NOT Parin(0);
when "0001" => Parout(1) <= NOT Parin(1);
when "0010" => Parout(2) <= NOT Parin(2);
when "0011" => Dataout(0) <= NOT Datain(0);
when "0100" => Parout(3) <= NOT parin(3);
when "0101" => Dataout(1) <= NOT Datain(1);
when "0110" => Dataout(2) <= NOT Datain(2);
when "0111" => Dataout(3) <= NOT Datain(3);
when "1000" => parout(4) <= parin(4);
when "1001" => Dataout(4) <= NOT Datain(4);
when "1010" => Dataout(5) <= NOT Datain(5);
when "1011" => Dataout(6) <= NOT Datain(6);
when "1100" => Dataout(7) <= NOT Datain(7);
when others =>
Parout <= parin;
Dataout <= Datain;
end case;
Dataout <= "00000000";
Parout <= "00000";
end if;
elsif (P0 = '0') then
if (synd /= "0000") then
NE <= '0';
DED <= '1';
SEC <= '0';
Dataout <= "00000000";
Parout <= "00000";
end if;
end if;
end process;
end beh;
Thank you
The correction logic implemented in the case statement is only reached when the syndrome is "0000" and the overall parity is '1'. That doesn't cover all the other possible syndrome values. The indentation of the single-error elsif makes this confusing. You need to rework the nested if statements so that correction is applied for all syndromes.
Your signals P0, synd, din1, din2, din3, din4 should be declared as variables in the process or you should extract the xor calculation from process.
Second variant with extracted xor calculation, extended sensitivity list and fixed code indentation:
library ieee;
use ieee.std_logic_1164.all;
entity hamdec8 is
port (
datain: in std_logic_vector (7 downto 0);
parin : in std_logic_vector(4 downto 0);
Dataout : out std_logic_vector(7 downto 0);
Parout : out std_logic_vector(4 downto 0);
NE : out std_logic;
DED : out std_logic;
SEC : out std_logic
);
end hamdec8;
architecture beh of hamdec8 is
Constant MaskP1 : std_logic_vector(7 downto 0) := "01011011";
Constant MaskP2 : std_logic_vector(7 downto 0) := "01101101";
Constant MaskP3 : std_logic_vector(7 downto 0) := "10001110";
Constant MaskP4 : std_logic_vector(7 downto 0) := "11110000";
signal synd : std_logic_vector(4 downto 1);
signal P0 : std_logic;
signal din1, din2, din3, din4 : std_logic_vector(7 downto 0); --to hold datain AND maskp
begin
P0 <= Parin(0) XOR Parin(1) XOR Parin(2) XOR Parin(3) XOR Parin(4) XOR
Datain(0) XOR Datain(1) XOR Datain(2) XOR Datain(3) XOR Datain(4) XOR
Datain(5) XOR Datain(6) XOR Datain(7);
din1 <= Datain AND MaskP1;
din2 <= Datain AND MaskP2;
din3 <= Datain AND MaskP3;
din4 <= Datain AND MaskP4;
Synd(1) <= din1(0) XOR din1(1) XOR din1(2) XOR din1(3) XOR
din1(4) XOR din1(5) XOR din1(6) XOR din1(7) XOR Parin(1);
Synd(2) <= din2(0) XOR din2(1) XOR din2(2) XOR din2(3) XOR
din2(4) XOR din2(5) XOR din2(6) XOR din2(7) XOR Parin(2);
Synd(3) <= din3(0) XOR din3(1) XOR din3(2) XOR din3(3) XOR
din3(4) XOR din3(5) XOR din3(6) XOR din3(7) XOR Parin(3);
Synd(4) <= din4(0) XOR din4(1) XOR din4(2) XOR din4(3) XOR
din4(4) XOR din4(5) XOR din4(6) XOR din4(7) XOR Parin(4);
process(Datain, Parin, synd, P0)
begin
NE <= '1';
DED <= '0';
SEC <= '0';
Dataout <= Datain;
Parout <= Parin;
if (synd = "0000") then
IF (P0 = '0') then
--Dataout <= Datain;
--NE <= '1';
--DED <= '0';
--SEC <= '0';
--Parout <= Parin;
null;
elsif (P0 = '1') then --single error
NE <= '0';
DED <= '0';
SEC <= '1';
case synd is
when "0000" => Parout(0) <= NOT Parin(0);
when "0001" => Parout(1) <= NOT Parin(1);
when "0010" => Parout(2) <= NOT Parin(2);
when "0011" => Dataout(0) <= NOT Datain(0);
when "0100" => Parout(3) <= NOT parin(3);
when "0101" => Dataout(1) <= NOT Datain(1);
when "0110" => Dataout(2) <= NOT Datain(2);
when "0111" => Dataout(3) <= NOT Datain(3);
when "1000" => parout(4) <= parin(4);
when "1001" => Dataout(4) <= NOT Datain(4);
when "1010" => Dataout(5) <= NOT Datain(5);
when "1011" => Dataout(6) <= NOT Datain(6);
when "1100" => Dataout(7) <= NOT Datain(7);
when others => null;
end case;
--Dataout <= "00000000"; -- these lines override all calculations
--Parout <= "00000"; -- from previous case statement
end if;
elsif (P0 = '0') then
if (synd /= "0000") then
NE <= '0';
DED <= '1';
SEC <= '0';
Dataout <= "00000000";
Parout <= "00000";
end if;
end if;
end process;
end beh;
What's up with this code?
IF (P0 = '0') then
-- commented out stuff
[...]
null;
elsif (P0 = '1') then --single error
[...]
end if;
Why not just use:
if p0 = '1' then
[...]
end if;
or at least
if p0 = '0' then
[stuff for when p0 is '0']
else
[stuff for when p0 is not '0']
end if;
I've written code for a binary divider that takes in an 8 bit dividend, 3 bit divisor, and gives a 5 bit quotient (3 bit remainder). I've literally spent hours trying to fix a bug that gives incorrect results but I haven't been able to identify it. Any help would be GREATLY appreciated! I basically get wrong answers for my inputs but I can't figure out why. There is a bus that takes in values and on the first clock cycle where st is 1, the dividend register is loaded. On the second clock cycle after, the divisor register is loaded and the calculation is made for the next three clock cycles.
The V signal is the output to signify that an overflow has occured (the result can't be fit into the five bits of the quotient), my st is the start signal to start the process, sh is the shift signal for the shift register, su is the subtract signal for the subtractor.
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_ARITH.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity Divider is
Port (bus_in: in std_logic_vector(8 downto 0);
St, Clk, reset: in std_logic;
Quotient: out std_logic_vector(4 downto 0);
Remainder: out std_logic_vector(2 downto 0);
v: out std_logic);
end Divider;
architecture Behavioral of Divider is
signal State, NextState: integer range 0 to 5;
signal C, Ld1, Ld2, Su, Sh: std_logic;
signal Divisor: std_logic_vector(2 downto 0);
signal Subout: std_logic_vector(3 downto 0);
signal Dividend: std_logic_vector(8 downto 0);
begin
Subout <= Dividend(8 downto 5) - ('0' & divisor);
C <= not Subout (3);
Remainder <= Dividend(7 downto 5);
Quotient <= Dividend(4 downto 0);
State_Graph: process (State, St, C)
begin
Ld1 <= '0';
Ld2<='0';
v <= '0';
Sh <= '0';
Su <= '0';
case State is
when 0 =>
if (St = '1') then
Ld1 <= '1';
NextState <= 1;
else
NextState <= 0;
end if;
when 1 =>
if (St = '1') then
Ld2 <= '1';
NextState <= 2;
else
Ld2<='1';
NextState <= 2;
end if;
when 2 =>
if (C = '1') then
v <= '1';
NextState <= 0;
else
Sh <= '1';
NextState <= 3;
end if;
when 3 | 4 =>
if (C = '1') then
Su <= '1';
NextState <= State;
else
Sh <= '1';
NextState <= State + 1;
end if;
when 5 =>
if (C = '1') then
Su <= '1';
end if;
NextState <= 0;
end case;
end process State_Graph;
Update: process (Clk)
begin
if Clk'event and Clk = '1' then
State <= NextState;
--if Load = '1' then
-- Dividend <= '0' & bus_in;
--end if;
if Ld1 = '1' then
Dividend <= '0'&Bus_in(7 downto 0);
end if;
if Ld2 = '1' then
Divisor <= Bus_in(2 downto 0);
end if;
if Su = '1' then
Dividend(8 downto 5) <= Subout;
Dividend(0) <= '1';
end if;
if Sh = '1' then --94
Dividend <= Dividend(7 downto 0) & '0';
end if;
end if;
end process update;
end Behavioral;
Here's my input and outputs:
[Signals]: http://imgur.com/fqfiYJZ 1
The picture shows that my registers for the divisor and dividend is loading correctly. So I think the issue is with the actual division code. The state machine also seems to be working correctly.
Don't write this yourself. You are re-inventing the wheel.
Either write q <= a / b;
or use an IP core from your FPGA vendor.