mboost-dp1

VHDL - Hvad er en latch??


Gå til bund
Gravatar #1 - Qw_freak
22. dec. 2010 21:17
Hey gutter, er der en den forklare hvad der menes med en latch??

jeg får denne warning:
WARNING:Xst:737 - Found 32-bit latch for signal <q>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
Gravatar #2 - tazimn
22. dec. 2010 21:26
Gravatar #3 - Qw_freak
22. dec. 2010 23:07
tazimn (2) skrev:
Kunne det være det her?


Nej, ikke så vidt jeg kan se..
Gravatar #4 - Emil Melgaard
24. dec. 2010 07:33
#3:

Jo, det er det.

Advarslen betyder at synthesizeren må indsætte nogle latches (hukommelsesenheder) for q nogle steder hvor du ikke selv har bedt om det.

Det skyldes som regel at du ikke har lavet et ordentligt flip-flop register til q, eller at du bruger et signal som om det var en variabel i et programmeringssporg.

Du kan evt. poste din kode, så kan det være jeg kan se hvad der er galt.
Gravatar #5 - Qw_freak
26. dec. 2010 12:57
Emil Melgaard (4) skrev:
Det skyldes som regel at du ikke har lavet et ordentligt flip-flop register til q, eller at du bruger et signal som om det var en variabel i et programmeringssporg.


Det er rigtigt at jeg har oprettet q som en variabel i et almindeligt programmeringssprog, ved ikke hvordan man skal sætte sådan en flipflop op...

Kode:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY PS_2_to_lcd IS
PORT ( clk, reset: IN STD_LOGIC;
Ok : IN STD_LOGIC;
Data : OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
Start : OUT STD_LOGIC;
RS : OUT STD_LOGIC;
ps2d, ps2c: in std_logic;
rx_en: in std_logic
);

END PS_2_to_lcd;

ARCHITECTURE Behavioral OF PS_2_to_lcd IS

-- Values of every state for initializing the display listed in an array.

TYPE init_values IS ARRAY(0 TO 18) OF STD_LOGIC_VECTOR (7 DOWNTO 0);
CONSTANT Initialize: init_values :=
("00000000",
"00111100",
"00000001",
"10010111",
"00000010",
"00010100",
"00000011",
"10100000",
"00000100",
"00000000",
"00001000",
"00000000",
"00001001",
"00000000",
"00001010",
"00000000",
"00001011",
"00000000",
"00001100");

--Valures of RS for initializing the display listed in an array.
TYPE read_states IS ARRAY(0 TO 18) OF STD_LOGIC;
CONSTANT Read_State: read_states :=
('1',
'0',
'1',
'0',
'1',
'0',
'1',
'0',
'1',
'0',
'1',
'0',
'1',
'0',
'1',
'0',
'1',
'0',
'1');

-- Signals for the initialize statemachine
TYPE state_type IS (ini_collect, ini_send, key_collect, key_send);
SHARED VARIABLE q: INTEGER := 0;
SIGNAL state_reg, state_next: state_type;
SIGNAL Key: STD_LOGIC_VECTOR(7 DOWNTO 0);

-- Signals for the PS/2 reader statemachine

type rx_statetype is (idle, dps, load);
signal rx_state_reg, rx_state_next: rx_statetype;
signal filter_reg, filter_next: std_logic_vector(7 downto 0);
signal f_ps2c_reg,f_ps2c_next: std_logic;
signal b_reg, b_next: std_logic_vector(10 downto 0);
signal n_reg,n_next: unsigned(3 downto 0);
signal fall_edge: std_logic;
SIGNAL rx_done_tick: std_logic;
SIGNAL dout: std_logic_vector(7 downto 0);

BEGIN

-- FSM state register

PROCESS(clk, reset)
BEGIN
IF reset='1' THEN
state_reg <= ini_collect;
-- q := "0";
ELSIF (clk'event AND clk = '1') THEN
state_reg <= state_next;
END IF;
END PROCESS;

-- FSM control path next-state logic.

PROCESS(state_reg, Ok, Key, rx_done_tick)
BEGIN
Start <= '0';
state_next <= state_reg;
CASE state_reg IS
WHEN ini_collect =>
Data <= Initialize(q);
RS <= Read_State(q);
state_next <= ini_send;

WHEN ini_send =>
Data <= Initialize(q);
RS <= Read_State(q);
Start <= '1';
IF (Ok = '1') THEN
IF (q <= 17) THEN
q :=q+1;
state_next <= ini_collect;
ELSIF (q = 18) THEN
q := 18;
state_next <= key_collect;
ELSE q := 18;
END IF;
END IF;

WHEN key_collect =>
IF (rx_done_tick = '1') THEN
Data <= Key;
RS <= '0';
state_next <= key_send;
END IF;

WHEN key_send =>
Data <= Key;
RS <='0';
Start <= '1';
IF (Ok = '1') THEN
state_next <= ini_collect;
END IF;

END CASE;
END PROCESS;



Som det ses bruger jeg 'q' til at tælle pladsen i mine arrays op med en.


Nogen forslag til hvordan jeg "flipflopper" q? :)
Gravatar #6 - Emil Melgaard
26. dec. 2010 14:17
Problemet er denne her linje:

q :=q+1;

I VHDL sker tingene ikke kun én gang, så med ovenstående linje vil du tælle q op så hurtigt den kan få signalet igennem ALU'en så længe den er i state ini_send.

For at gøre q til en flip-flop (register), kan du kan gøre det samme som du gør med state. Dvs. du laver "q_reg" og "q_next" i stedet for "q".

I din state register process tilføjer du linjen "q_reg := q_next;" der hvor du også har "state_reg <= state_next;", og så sørger du for at alle de steder du læser q bruger du q_reg, og alle de steder hvor du sætter q bruger du q_next.

Linjen fra før kommer så til at blive:

q_next := q_reg;

Så bliver q kun talt op når den clock'er.
Gravatar #7 - Qw_freak
26. dec. 2010 21:28
jeg får den samme varning om:

Key:
WARNING:Xst:737 - Found 8-bit latch for signal <Key>. Latches may be generated from incomplete case or if statements. 


Data
WARNING:Xst:737 - Found 8-bit latch for signal <Data>. Latches may be generated from incomplete case or if statements.


Rs
WARNING:Xst:737 - Found 1-bit latch for signal <RS>. Latches may be generated from incomplete case or if statements.


Kan du se hvad der gør at de kommer?

q kan jeg godt se, men ikke de tre andre...
Gravatar #8 - Emil Melgaard
27. dec. 2010 07:57
Key: Så vidt jeg kan se, giver du aldrig key en værdi. Mangler der noget kode?

Data og Rs:

Når den er i tilstand key_collect er det ikke altid Data og Rs får en værdi. Det skal du sørge for at de altid får.

Muligvis bør du også lave en "when others" til din case hvor du giver dem en værdi, men det er jeg ikke helt sikker på om er nødvendigt.

Alternativt kan du give dem en default værdi i starten af process'en, som du gør med "Start".
Gravatar #9 - Qw_freak
27. dec. 2010 10:43
Der mangler noget kode, men deri indgår kun Key som får værdien fra et tastaturtryk VIA PS/2 porten på mit Spartan3E, der er dog ingen andre warnings som impliceres af det stykke kode...
Gravatar #10 - Qw_freak
29. dec. 2010 16:35
Nyt problem... hvad Sker der lige for det, denne error poppede op lige pludslig mens jeg rettede det med q tællen. hvad er der galt?

ERROR:Xst:800 - "C:/Users/steven/Desktop/ASC1/VHDL/LCD_Driver/Init.vhd" line 266: Multi-source on Integers in Concurrent Assignment.


Hele koden:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

ENTITY PS_2_to_lcd IS
PORT ( clk, reset: IN STD_LOGIC;
Ok : INOUT STD_LOGIC;
Data : OUT STD_LOGIC_VECTOR (7 DOWNTO 0);
Start : OUT STD_LOGIC;
RS : OUT STD_LOGIC;
ps2d, ps2c: in std_logic; -- key data, key clock
rx_en: in std_logic
);

END PS_2_to_lcd;

ARCHITECTURE Behavioral OF PS_2_to_lcd IS
--=======================================================================
-- Values of every state for initializing the display listed in an array.
--=======================================================================
TYPE init_values IS ARRAY(0 TO 18) OF STD_LOGIC_VECTOR (7 DOWNTO 0);
CONSTANT Initialize: init_values :=
("10000000",
"00111100",
"00000001",
"10010111",
"00000010",
"00010100",
"00000011",
"10100000",
"00000100",
"00000000",
"00001000",
"00000000",
"00001001",
"00000000",
"00001010",
"00000000",
"00001011",
"00000000",
"00001100");

--=======================================================================
--Valures of RS for initializing the display listed in an array.
--=======================================================================
TYPE read_states IS ARRAY(0 TO 18) OF STD_LOGIC;
CONSTANT Read_State: read_states :=
('1',
'0',
'1',
'0',
'1',
'0',
'1',
'0',
'1',
'0',
'1',
'0',
'1',
'0',
'1',
'0',
'1',
'0',
'1');
--=======================================================================
-- Signals for the initialize statemachine
--=======================================================================
TYPE state_type IS (ini_collect, ini_send, key_collect, key_send);
SHARED VARIABLE q_reg, q_next: INTEGER RANGE 0 to 18 := 0;
SIGNAL state_reg, state_next: state_type;
SIGNAL Key: STD_LOGIC_VECTOR(7 DOWNTO 0);
--=======================================================================
-- Signals for the PS/2 reader statemachine
--=======================================================================
type rx_statetype is (idle, dps, load);
signal rx_state_reg, rx_state_next: rx_statetype;
signal filter_reg, filter_next: std_logic_vector(7 downto 0);
signal f_ps2c_reg,f_ps2c_next: std_logic;
signal b_reg, b_next: std_logic_vector(10 downto 0);
signal n_reg,n_next: unsigned(3 downto 0);
signal fall_edge: std_logic;
SIGNAL rx_done_tick: std_logic;
SIGNAL dout: std_logic_vector(7 downto 0);
--=======================================================================
-- Signal for the Counter to OK
--=======================================================================
SIGNAL count_next, count_reg: std_logic_vector(25 downto 0);

BEGIN
--=======================================================================
-- FSM state register
--=======================================================================
PROCESS(clk, reset)
BEGIN
IF reset='1' THEN
state_reg <= ini_collect;
q_reg := 0;
ELSIF (clk'event AND clk = '1') THEN
state_reg <= state_next;
q_reg := q_next;
END IF;
END PROCESS;
--=======================================================================
-- FSM control path next-state logic.
--=======================================================================

PROCESS(state_reg, Ok, Key, rx_done_tick)
BEGIN
Start <= '0';
state_next <= state_reg;
CASE state_reg IS
WHEN ini_collect =>

Data <= Initialize(q_reg);
RS <= Read_State(q_reg);
state_next <= ini_send;

WHEN ini_send =>
Data <= Initialize(q_reg);
RS <= Read_State(q_reg);
Start <= '1';
IF (Ok = '1') THEN
IF (q_reg <= 17) THEN
q_next:= q_reg+1;
state_next <= ini_collect;
ELSIF (q_reg = 18) THEN
q_reg := 18;
state_next <= key_collect;
ELSE q_reg := 18;
END IF;
END IF;

WHEN key_collect =>
Data <= Initialize(q_reg);
RS <= Read_State(q_reg);
IF (rx_done_tick = '1') THEN
Data <= Key;
RS <= '0';
state_next <= key_send;
END IF;

WHEN key_send =>
Data <= Key;
RS <='0';
Start <= '1';
IF (Ok = '1') THEN
state_next <= ini_collect;
END IF;

END CASE;
END PROCESS;

--=======================================================================
-- PS/2 Keyboard reading part.
--=======================================================================

PROCESS (clk, reset)
begin
if reset='1' then
filter_reg <= (others=>'0');
f_ps2c_reg <= '0';
elsif (clk'event and clk='1') then
filter_reg <= filter_next;
f_ps2c_reg <= f_ps2c_next;
end if;
end process;

filter_next <= ps2c & filter_reg(7 downto 1);
f_ps2c_next <= '1' when filter_reg="11111111" else
'0' when filter_reg="00000000" else
f_ps2c_reg;
fall_edge <= f_ps2c_reg and (not f_ps2c_next);

--=======================================================================
-- fsmd to extract the 8-bit data registers
--=======================================================================
process (clk, reset)
begin
if reset='1' then
rx_state_reg <= idle;
n_reg <= (others=>'0');
b_reg <= (others=>'0');
count_reg <= (others => '0');
elsif (clk'event and clk='1') then
rx_state_reg <= rx_state_next;
n_reg <= n_next;
b_reg <= b_next;
if (Ok = '1') then
count_reg <= (others => '0');
else count_reg <= count_next;
end if;
end if;
end process;
--=======================================================================
-- next-state logic
--=======================================================================
process(rx_state_reg,n_r eg,b_reg,fall_edge,rx_en,ps2d)
begin
rx_done_tick <='0';
rx_state_next <= rx_state_reg;
n_next <= n_reg;
b_next <= b_reg;
case rx_state_reg is
when idle =>
if fall_edge='1' and rx_en='1' then
-- shift in start bit
b_next <= ps2d & b_reg(10 downto 1);
n_next <= "1001";
rx_state_next <= dps;
end if;
when dps => -- 8 danmnmnmnmnnmnta + 1 pairty + 1 stop
if fall_edge='1' then
b_next <= ps2d & b_reg(10 downto 1);
if n_reg = 0 then
rx_state_next <=load;
else
n_next <= n_reg - 1;
end if;
end if;
when load =>
-- 1 extra clock to complete the last shift
rx_state_next <= idle;
rx_done_tick <='1';
end case;
end process;

count_next <= count_reg + 1;
-- Ok <= '1' WHEN count_reg="10111110101111000010000000" ELSE '0';
Ok <= '1' WHEN count_reg="00000000000000000000000011" ELSE '0';

--=======================================================================
-- output
--=======================================================================
dout <= b_reg(8 downto 1); -- data bits
Key <= dout;

END Behavioral;
Gravatar #11 - Emil Melgaard
30. dec. 2010 08:23

ELSIF (q_reg = 18) THEN
q_reg := 18;
state_next <= key_collect;
ELSE q_reg := 18;


Du må ikke sætte q_reg direkte til en værdi. Du skal bruge q_next.
Gravatar #12 - Qw_freak
30. dec. 2010 18:24
hvorfor må jeg ikke det??
Gravatar #13 - Emil Melgaard
30. dec. 2010 20:39
Fordi når du clock'er vil du sætte q_reg til 2 forskellige værdier samtidig.

Variable fungerer på samme måde som signaler. Tænk på det som ledninger du omdirigerer; hvis du sætter 2 ledninger der hver har en værdi sammen, hvad vil resultatet så blive?
Gå til top

Opret dig som bruger i dag

Det er gratis, og du binder dig ikke til noget.

Når du er oprettet som bruger, får du adgang til en lang række af sidens andre muligheder, såsom at udforme siden efter eget ønske og deltage i diskussionerne.

Opret Bruger Login