How to run VHDL Components in a sequential fashion? - components

I'm making a simple TicTacToe game (computer vs user) in VHDL and the code is almost finished, but there is something that I can't figure out how to handle it.
Overall there are three main modules, computer move based on the current grid, grid status that takes in which cell to be filled either by computer or by user, a main module that retrieves the grid from the grid module and handle these components as well as the user move.
So, in this main module, I have a Component that sends the move (either by computer or user) to the grid module and in return updates its current grid Signal in this main module, then the second component (computer move) takes in the grid status (which is the Signal) and make a move based on that. Therefore, this also needs to get sent to the grid module for it to be updated. However, this doesn't really work in action when it comes to functioning in this order.
In a nutshell, my question is, how may I go about updating this main Signal in the order of the Components execution or more generally, how may I have a Signal be updated by a Component that needs to become the input of another Component respectively?
Thanks for your help.
Edit
Here is part of the main module code
ENTITY currentstate IS
PORT (to_occupy_cell : IN TO_SELECT; --user choice
start : IN STD_LOGIC; --initialize the grid
by_user : IN STD_LOGIC; --how to fill the grid (X or O)
difficulty : IN STD_LOGIC; --difficulty
winner_state : OUT INTEGER RANGE 0 to 2; --who is the winner?
currentgrid : OUT GRID (1 TO 3, 1 TO 3)); --outputs status of the grid after compmove to be displayed
END currentstate;
---------------------------------
ARCHITECTURE statearch OF currentstate IS
SIGNAL comp_occupy : TO_SELECT;
SIGNAL grid_status : GRID (1 TO 3, 1 TO 3);
COMPONENT grid IS -------saves the grid status
PORT (to_occupy_cell : IN TO_SELECT; start : IN STD_LOGIC; by_user : IN STD_LOGIC; currentgrid : OUT GRID (1 TO 3, 1 TO 3));
END COMPONENT;
COMPONENT compmove IS
PORT (current : IN GRID (1 TO 3, 1 TO 3); dif : IN STD_LOGIC; compsel : OUT TO_SELECT);
END COMPONENT;
BEGIN
U1: grid PORT MAP (to_occupy_cell, start, by_user ,grid_status);
U2: compmove PORT MAP (grid_status, difficulty, comp_occupy);
Here is the grid module
ENTITY grid IS
PORT (to_occupy_cell : IN TO_SELECT; --user choice
start : IN STD_LOGIC; --initialize the grid
by_user : IN STD_LOGIC; --how to fill the grid ( X or O)
currentgrid : OUT GRID (1 TO 3, 1 TO 3)); --outputs status of the grid after compmove to be displayed
END grid;
---------------------------------
ARCHITECTURE gridstatus OF grid IS
BEGIN
PROCESS (to_occupy_cell, start)
VARIABLE temp_grid : GRID (1 TO 3, 1 TO 3);
BEGIN
IF (start = '1' AND start'EVENT) THEN
temp_grid := (others => (others=>0));
END IF;
IF (by_user = '1') THEN
temp_grid(to_occupy_cell(0), to_occupy_cell(1)) := 1;
ELSIF (by_user = '0') THEN
temp_grid(to_occupy_cell(0), to_occupy_cell(1)) := 2;
END IF;
currentgrid <= temp_grid;
END PROCESS;
END gridstatus;
And entity of the computer move module
---------------------------------
ENTITY compmove IS
PORT(current : IN GRID (1 TO 3, 1 TO 3); --takes in the grid status
dif : IN STD_LOGIC; --difficulty
compsel : OUT TO_SELECT);
END compmove;
---------------------------------
So, what happens is that, the Signal grid_status should automatically be updated first by the user move and then when it is updated it gets piped into the compmove module for the computer to decide which cell to fill. Afterwards, the grid_status should get updated again. Also, '1' is the user move, '2' is the computer move in the grid.
Hope this clears what I'm after.
(image referenced from link added)
EDIT 2:
Thanks to the help of David and fru1tbat I could actually get it to work! Turns out I had missed making compmove sensitive to grid_status.
However, now it is only working for the first round but not the second round if the user selects another cell. Below are the updated codes:
Main module (currentstate)
ENTITY currentstate IS
PORT (to_occupy_cell : IN TO_SELECT; --user choice
start : IN STD_LOGIC; --initialize the grid
by_user : IN STD_LOGIC; --how to fill the grid ( X or O)
difficulty : IN STD_LOGIC; --difficulty
winner_state : OUT INTEGER RANGE 0 to 2); --who is the winner?
END currentstate;
---------------------------------
ARCHITECTURE statearch OF currentstate IS
SIGNAL occupy_to_grid : TO_SELECT;
SIGNAL comp_occupy : TO_SELECT;
SIGNAL user_move : STD_LOGIC;
SIGNAL grid_status : GRID (1 TO 3, 1 TO 3);
COMPONENT grid_ IS -------saves the grid status
PORT (to_occupy_cell : IN TO_SELECT; start : IN STD_LOGIC; by_user : IN STD_LOGIC; currentgrid : OUT GRID (1 TO 3, 1 TO 3));
END COMPONENT;
COMPONENT compmove IS
PORT (current : IN GRID (1 TO 3, 1 TO 3); by_user : IN STD_LOGIC; dif : IN STD_LOGIC; compsel : OUT TO_SELECT);
END COMPONENT;
BEGIN
U1: grid_ PORT MAP (occupy_to_grid, start, user_move,grid_status);
U2: compmove PORT MAP (grid_status, user_move, difficulty, comp_occupy);
PROCESS(comp_occupy, to_occupy_cell)
BEGIN
IF to_occupy_cell'EVENT THEN
occupy_to_grid <= to_occupy_cell;
user_move <= by_user;
END IF;
IF comp_occupy'EVENT THEN
occupy_to_grid <= comp_occupy;
user_move <= '0';
END IF;
END PROCESS;
END statearch;
The grid_ module
ENTITY grid_ IS
PORT (to_occupy_cell : IN TO_SELECT; --user choice
start : IN STD_LOGIC; --initialize the grid
by_user : IN STD_LOGIC; --how to fill the grid ( X or O)
currentgrid : OUT GRID (1 TO 3, 1 TO 3)); --outputs status of the grid after compmove to be displayed
END grid_;
---------------------------------
ARCHITECTURE gridstatus OF grid_ IS
BEGIN
PROCESS (to_occupy_cell, start)
VARIABLE temp_grid : GRID (1 TO 3, 1 TO 3);
BEGIN
IF (start = '1' AND start'EVENT) THEN
temp_grid := (others => (others=>0));
END IF;
IF (by_user = '1') THEN
temp_grid(to_occupy_cell(0), to_occupy_cell(1)) := 1;
ELSIF (by_user = '0') THEN
temp_grid(to_occupy_cell(0), to_occupy_cell(1)) := 2;
END IF;
currentgrid <= temp_grid;
END PROCESS;
END gridstatus;
Initial part of compmove
ENTITY compmove IS
PORT(current : IN GRID (1 TO 3, 1 TO 3); --takes in the grid status
by_user : IN STD_LOGIC; --to only gets triggered when user selects a cell
dif : IN STD_LOGIC; --difficulty
compsel : OUT TO_SELECT);
END compmove;
---------------------------------
ARCHITECTURE comparch OF compmove IS
BEGIN
PROCESS(by_user, current)
VARIABLE tempsel : TO_SELECT := (0,0);
VARIABLE occ_count : INTEGER := 0;
VARIABLE unocc : INTEGER := 0;
BEGIN
IF (dif = '0' AND current'EVENT AND by_user = '1') THEN
--------------bunch of codes here
It is almost there, I believe just a small change perhaps in the sensitivity list of compmove would do the trick for it to retrieve the updated grid_status correspondingly, because currently after the first round it doesn't take in the updated grid_status and comp_occupy remains unchanged!

You appear to be missing by_user from the process sensitivity list in grid:
process (to_occupy_cell, start) -- Add by_user to sensitivity list
variable temp_grid : grid (1 to 3, 1 to 3);
begin
if (start = '1' and start'event) then
temp_grid := (others => (others=>0));
end if;
if (by_user = '1') then
temp_grid(to_occupy_cell(0), to_occupy_cell(1)) := 1;
elsif (by_user = '0') then
temp_grid(to_occupy_cell(0), to_occupy_cell(1)) := 2;
end if;
currentgrid <= temp_grid;
end process;
The only thing that fit from your description was a missing event trigger the process. The idea being by_user isn't concurrent with any other input.
I also found a name conflict between grid in the component declaration in currentstate and the undeclared package containing the type declaration for type grid with two different VHDL analyzers. (After making up a package and type declarations for to_select and grid).
Addendum
I added a test bench, and also hooked up grid_status to the returned currentgrid in currentstate so it would show up at the top level.
library ieee;
use ieee.std_logic_1164.all;
use work.foobat.all;
entity test is
end entity;
architecture foo of test is
component currentstate is
port (
to_occupy_cell: in to_select; --user choice
start: in std_logic; --initialize the grid
by_user: in std_logic; --how to fill the grid (x or o)
difficulty: in std_logic; --difficulty
winner_state: out integer range 0 to 2; --who is the winner?
currentgrid: out grid (1 to 3, 1 to 3)
); --outputs status of the grid after compmove to be displayed
end component;
signal to_occupy_cell: to_select;
signal start: std_logic := '0';
signal by_user: std_logic := '1';
signal difficulty: std_logic := '0';
signal winner_state: integer range 0 to 2;
signal currentgrid: grid(1 to 3, 1 to 3);
begin
DUT:
currentstate
port map (
to_occupy_cell => to_occupy_cell,
start => start,
by_user => by_user,
difficulty => difficulty,
winner_state => winner_state,
currentgrid => currentgrid -- grid_status
);
STIMULUS:
process
begin
wait for 1 sec;
to_occupy_cell <= (2,2); -- center
start <= '1'; -- write 1 to gridstatus(2,2);
wait for 1 sec;
to_occupy_cell <= (1,1); -- corner
start <= '0'; -- no separate delta cycle event
wait for 1 sec;
wait;
end process;
end architecture;
So the two sets of grid values show below are grid_status (surfaced) and current on the compmove port. From what I can tell, grid_status gets to compmove.
This was done with ghdl and gtkwave. ghdl handles array signals in waveforms. The waveform trace image is larger than it will likely appear in your browser, you can open it in a separate tab/window or otherwise view it larger.
The values shown for the two versions grid_status/current appear identical.
Note there are three events on grid_status, the initial event which writes to leftmost row and column in the grid. I'm not sure why to_occupy_cell doesn't show up properly in the waveform, it doesn't show up as an array but does show the events. It's likely a result of how I declared the to_select type.
The initial or default transaction, the start'event and start = '1' transaction and to_occupy_cell transition (concurrent with start = 0).
Anyway, the point is that grid_status gets to compmove.

Your process that writes to the grid_status signal only accepts input from the user (comp_occupy doesn't connect to anything in your main module) so how can the computer update the grid with its move? What you seem to need is an input (or set of inputs) to the grid module that connects to comp_occupy, and a modified process in gridstatus which monitors both players and updates the grid from either source.
(edit)
On further consideration, I realize your intent may be to have a single input to the grid module which adds a move for either player. You appear to want to use events on by_user to update the grid, but I don't see the logic that switches by_user to create the sequence. You seem to need something like (in your main component):
process (to_occupy_cell, comp_occupy)
begin
if by_user = '1' then
occupy_to_grid <= to_occupy_grid;
else
occupy_to_grid <= comp_occupy;
end if;
by_user <= not by_user; -- on input from either source, alternate user for next input
end process;
Then map occupy_to_grid to grid instead of to_occupy_cell. This assumes that the new value of both 'occupy' signals is assigned on the same delta (or else by_user will flip back and forth unexpectedly), so if that's not the case, you will need to modify accordingly.
Let me know if this is close to what you're looking for.

Related

Initializing registers

I have a very simple synchronous circuit that is supposed to blink an LED:
module Blinker where
import Clash.Prelude
import Data.Word
{-# NOINLINE topEntity #-}
{-# ANN topEntity
(Synthesize
{ t_name = "blinkerTop"
, t_inputs = [PortName "CLK_32MHZ", PortName "RESET"]
, t_output = PortName "LED"
}) #-}
topEntity
:: Clock System Source
-> Reset System Asynchronous
-> Signal System Bit
topEntity = exposeClockReset $ tickTock 32000000
tickTock :: (HiddenClockReset domain gated synchronous) => Word32 -> Signal domain Bit
tickTock n = mealy step (False, 0) (pure ())
where
step (s, k) () =
let k' = k + 1
finished = k' == n
s' = if finished then not s else s
k'' = if finished then 0 else k'
in ((s', k''), if s' then high else low)
Since it doesn't work when I upload it to a real FPGA board, I thought I'd try it in Xilinx's simulator, with the following testbench:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY testbench IS
END testbench;
ARCHITECTURE behavior OF testbench IS
COMPONENT blinkerTop
PORT(
CLK_32MHZ : IN std_logic;
RESET : IN std_logic;
LED : OUT std_logic
);
END COMPONENT;
signal CLK_32MHZ : std_logic := '0';
signal RESET : std_logic := '0';
signal LED : std_logic;
constant CLK_32MHZ_period : time := 31.2 ns;
BEGIN
uut: blinkerTop PORT MAP (
CLK_32MHZ => CLK_32MHZ,
RESET => RESET,
LED => LED
);
CLK_32MHZ_process :process
begin
CLK_32MHZ <= '0';
wait for CLK_32MHZ_period/2;
CLK_32MHZ <= '1';
wait for CLK_32MHZ_period/2;
end process;
END;
In the simulator, this matches the real life FPGA board's behaviour: the LED signal stays low.
I looked at the generated VHDL and this is what it looks like:
-- Automatically generated VHDL-93
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.ALL;
use std.textio.all;
use work.all;
use work.blinkertop_types.all;
entity blinkerTop is
port(-- clock
CLK_32MHZ : in std_logic;
-- asynchronous reset: active high
RESET : in std_logic;
LED : out std_logic);
end;
architecture structural of blinkerTop is
signal \#tup_app_arg\ : unsigned(31 downto 0);
signal \s'\ : boolean;
signal \#s'_case_alt\ : boolean;
signal s : boolean;
signal \#finished_case_alt\ : boolean;
signal \#k'_case_alt\ : unsigned(31 downto 0);
signal ds : blinkertop_types.tup2;
signal \#finished_app_arg\ : signed(63 downto 0);
signal x : unsigned(63 downto 0);
signal x_0 : blinkertop_types.tup2;
signal \x#\ : unsigned(63 downto 0);
signal k : unsigned(31 downto 0);
signal \#w\ : unsigned(63 downto 0);
begin
LED <= '1' when \s'\ else
'0';
\#tup_app_arg\ <= resize(to_unsigned(0,64),32) when \#finished_case_alt\ else
\#k'_case_alt\;
\s'\ <= \#s'_case_alt\ when \#finished_case_alt\ else
s;
\#s'_case_alt\ <= false when s else
true;
s <= ds.tup2_sel0;
\#finished_case_alt\ <= tagToEnum(\#finished_app_arg\);
\#w\ <= (\x#\ + to_unsigned(1,64));
\#k'_case_alt\ <= resize((resize(\#w\(31 downto 0),64)),32);
-- register begin
blinkertop_register : process(CLK_32MHZ,RESET)
begin
if RESET = '1' then
ds <= ( tup2_sel0 => false, tup2_sel1 => resize(to_unsigned(0,64),32) )
-- pragma translate_off
after 1 ps
-- pragma translate_on
;
elsif rising_edge(CLK_32MHZ) then
ds <= x_0
-- pragma translate_off
after 1 ps
-- pragma translate_on
;
end if;
end process;
-- register end
\#finished_app_arg\ <= to_signed(1,64) when x = to_unsigned(32000000,64) else to_signed(0,64);
x <= resize(\#k'_case_alt\,64);
x_0 <= ( tup2_sel0 => \s'\
, tup2_sel1 => \#tup_app_arg\ );
\x#\ <= resize(k,64);
k <= ds.tup2_sel1;
end;
I noticed that the internal state is not initialized, only assigned on reset. So this gave me an idea to add a reset process to the testbench:
stim_proc: process
begin
RESET <= '1';
wait for 100 ns;
RESET <= '0';
wait;
end process;
With this change, afterwards I see LED starting to blink in the simulator. [*]
That takes care of the simulation; but how would I ensure a similar reset signal on the real board?
[*] For the simulation, of course, I have increased the frequency from 32,000,000 cycles to just 100 cycles; otherwise I'd have to run the simulator for ages just to see the first transition.
One solution is to create a power-on-reset sequence in your FPGA logic. This can be implemented as a counter, and asserting reset as long as the counter value is below some constant. When the counter exceeds the constant value, deassert the reset.

How to use conditional assignment when portmapping

I am trying to create a very simple calculator with the use of an adder and subtractor as components. i want the results to be displayed on seven segment displays. The problem is i dont know how to select addition or subtraction using add_sub.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY CONVERTOR IS
PORT (
A,B :IN BIT;
CIN,ADD_SUB :IN BIT;
cout,carryborrow :OUT BIT
);
END CONVERTOR;
ARCHITECTURE CONVERTOR_ARCH OF CONVERTOR IS
COMPONENT SUBTRACTOR_ASSIGNMENT IS
PORT (
A1,B1 :IN STD_LOGIC;
CIN1 :IN STD_LOGIC;
diff1,borrow1 :OUT STD_LOGIC
);
END COMPONENT;
COMPONENT ADDER_ASSIGNMENT IS
PORT (
A2,B2 :IN STD_LOGIC;
CIN2 :IN STD_LOGIC;
sum_2,cout2 :OUT STD_LOGIC
);
END COMPONENT;
SIGNAL E,F,G,H,P,Q,R,S: STD_LOGIC;
BEGIN
E <= A WHEN add_sub = '1' ELSE '0';
F <= B WHEN add_sub = '1' ELSE '0';
G <= CIN WHEN add_sub = '1' ELSE '0';
H <= A WHEN add_sub = '0' ELSE '0';
I <= B WHEN add_sub = '0' ELSE '0';
J <= CIN WHEN add_sub = '0' ELSE '0';
AD1: SUBTRACTOR_ASSIGNMENT PORT MAP(E,F,G,cout,carryborrow);
AD2: SUBTRACTOR_ASSIGNMENT PORT MAP(E,F,G,cout,carryborrow);
AD3: SUBTRACTOR_ASSIGNMENT PORT MAP(E,F,G,cout,carryborrow);
AD4: SUBTRACTOR_ASSIGNMENT PORT MAP(E,F,G,cout,carryborrow);
SB1: ADDER_ASSIGNMENT PORT MAP(H,I,J,cout,carryborrow);
SB1: ADDER_ASSIGNMENT PORT MAP(H,I,J,cout,carryborrow);
SB1: ADDER_ASSIGNMENT PORT MAP(H,I,J,cout,carryborrow);
SB1: ADDER_ASSIGNMENT PORT MAP(H,I,J,cout,carryborrow);
END CONVERTOR_ARCH;
Can you give us an error message you are getting, or the output? Based on what you are saying, it looks like you are trying to use "ADD_SUB" in your port to switch between addition and subtraction.
Also worth noting: do you want your design to be clocked? Right now, it doesn't look like you have a clock going into your port. If you wanted to update your display synchronously, you would need to add in a clock by using something like:
if (rising_edge(my_clock)) then
-- make the magic happen
end if;
Did you draw a picture of your hardware? You need multiplexors on the outputs of the Adder and Subtractor, but it is ok to connect your A, B, CIN to both your adder and subtractor.
Make sure to mind your types. If you are using std_ulogic, then use it everywhere and not type bit.

How to use two switches in vhdl

I want to control the value of a variable using two switches. One for incrementing the value, whereas the other one for decrementing the value. How should i shange this code.
error says that the variable counting is unsynthesisable.
I have tried a lot but could not figure out what exactly the problem is.
ERROR:Xst:827 - line 34: Signal counting0 cannot be synthesized, bad synchronous description. The description style you are using to describe a synchronous element (register, memory, etc.) is not supported in the current software release.
library IEEE;
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.ALL;
entity counts is
port(
btn_up : in std_logic;
reset : IN STD_LOGIC;
btn_dn : in std_logic;
counted : out std_logic_vector(8 downto 0)
);
end entity counts;
architecture behaviour of counts is
signal counter : std_logic_vector(8 downto 0);
begin
btupprocess : process(btn_up,reset,counter)
variable counting : unsigned(8 downto 0);
begin
counting := unsigned(counter);
if(reset = '1') then
counting := (others => '0');
elsif (rising_edge(btn_up)) then
if(counting > 399) then
counting := counting - 1;
else
counting := counting + 1;
end if;
end if;
counter <= std_logic_vector(counting);
end process;
btndnprocess : process(btn_dn,counter)
variable counting : unsigned(8 downto 0);
begin
counting := unsigned(counter);
if (falling_edge(btn_dn)) then
if(counting < 200) then
counting := counting + 1;
else
counting := counting - 1;
end if;
end if;
counter <= std_logic_vector(counting);
end process;
counted <= counter;
end behaviour;
Although in some cases it is possible to drive a signal from two different processes, there are better approaches in this case.
A possible solution to your problem is:
add a clock input to your entity; you should probably use a synchronous design
rewrite your architecture to use three processes, with each process driving a single signal:
one process will debounce and detect a rising edge on btn_up; this process will generate the signal btn_up_rising_edge
one process will debounce and detect a rising edge on btn_dn; this process will generate the signal btn_dn_rising_edge
a third process will read btn_up_rising_edge and btn_dn_rising_edge, and increment or decrement the count as appropriate
in all three processes, your sensitiviy list should contain clock and reset only
You can find an example of an edge detector with a debouncer here: https://electronics.stackexchange.com/questions/32260/vhdl-debouncer-circuit

ps/2 keyboard interface VHDL

Alright so I'm trying to implement a keyboard controller for use with an altera DE2 FPGA board, and am having some issues. I have ran this code in the quartus simulator and everything seems to be doing what I think it should be doing. However, when I try to program it onto the FPGA, nothing works. I have targeted it down to the way I'm simulating the ps/2 clock and the system clock doesn't appear to be how they are actually running.
I simulated the system clock at 50 mhz, 20ns period, and the ps2clock with a 90ns period. When setting the ps2data, to random values throughout the simulation, the correct bits are loaded into the 8 bit scan code. The problem is that when programmed to the board, the state machine never leaves the idle state. The state machine should leave the idle state on the falling edge of the ps2 clock when the data bit is zero, which seems to never happen. I have the ps2data and ps2clock pins connected to the correct inputs, but can't seem to figure out the problem.
I didn't add the top level entity that tests this, but it simply takes the output keyCode and sends it to one of the 7seg displays. I feel like the answer to this has something to do with the ps2clock, im just not sure what exactly.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity keyboard is
Port ( Clk : in std_logic; --system clock
ps2Clk : in std_logic; --keyboard clock
ps2Data : in std_logic; --keyboard data
reset : in std_logic; --system reset
keyReady : out std_logic;
DoRead : in std_logic; -- when to read
keyCode : out std_logic_vector(7 downto 0);
pFalling : out std_logic; --debugging
pFixedClk : out std_logic_vector(1 downto 0); --debugging
divClock_out : out std_logic; --debugging
clockCount_out : out std_logic_vector(9 downto 0); --debugging
testDiv_out : out std_logic;
bitCount_out : out std_logic_vector(3 downto 0);
shiftIn_out : out std_logic_vector(8 downto 0)); --debugging
end keyboard;
architecture Behavioral of keyboard is
component div_counter is
Port(clk, reset : in std_logic;
Q : out std_logic_vector(9 downto 0));
end component div_counter;
signal shiftIn : std_logic_vector(8 downto 0); -- shifted in data
signal ps2fixedClock : std_logic_vector(1 downto 0); -- 2 bit shift register
signal divClock : std_logic ; -- main clock/512
signal clockCount : std_logic_vector(9 downto 0); -- debugging
signal ps2falling : std_logic ;
signal bitCount : std_logic_vector(3 downto 0);
signal keyReady_sig : std_logic;
type state_type is (idle, shift, ready);
signal state : state_type;
begin
keyReady <= keyReady_sig;
-------------------------------
--- counter to divide the main clock by 512
-------------------------------
counter : div_counter
Port map(clk => Clk,
reset => reset,
Q => clockCount);
clockCount_out <= clockCount;
divided_clock : process (clockCount)
begin
if clockCount = "1000000001" then
divClock <= '1';
else
divClock <= '0';
end if;
end process divided_clock;
testDiv_out <= divClock;
------------------------------------
------ 2 bit shift register to sync clocks
------------------------------------
ps2fixed_Clock : process (reset, divClock)
begin
if reset = '1' then
ps2fixedClock <= "00";
elsif (divClock'event and divClock = '1') then
ps2fixedClock(0) <= ps2fixedClock(1);
ps2fixedClock(1) <= ps2Clk;
end if;
end process ps2fixed_Clock;
pFixedClk <= ps2fixedClock;
-----------------------------------
-------- edge detector
-----------------------------------
process (ps2fixedClock)
begin
if ps2fixedClock = "01" then
ps2falling <= '1';
else
ps2falling <= '0';
end if;
end process;
pFalling <= ps2falling;
bitCount_out <= bitCount;
--------------------------------
------- state machine
--------------------------------
state_machine : process (divClock, reset)
begin
if (reset = '1') then
state <= idle;
bitCount <= "0000";
shiftIn <= (others => '0');
keyCode <= (others => '0');
keyReady_sig <= '0';
elsif (divClock'event AND divClock = '1') then
if DoRead='1' then
keyReady_sig <= '0';
end if;
case state is
when idle =>
bitCount <= "0100";
if ps2falling = '1' and ps2Data = '0' then
state <= shift;
end if;
when shift =>
if bitCount >= 9 then
if ps2falling = '1' then -- stop bit
keyReady_sig <= '1';
keyCode <= shiftIn(7 downto 0);
state <= idle;
end if;
elsif ps2falling='1' then
bitCount <= bitCount + 1;
shiftIn(7 downto 0) <= shiftIn(8 downto 1);
shiftIn(8) <= ps2Data;
end if;
when others =>
state <= idle;
end case;
end if;
end process;
shiftIn_out <= shiftIn;
end Behavioral;
Coming back to answer this a bit later....
It turns out the reason why this wasn't working was because I was using a usb -> ps2 adapter and not an original ps2 connector keyboard.
you try to sync the ps2clock to your divClock. however, divClock is an enable signal and not a clock. it is active not very often.
I suggest that you use clk in ps2fixed_Clock process
ps2fixed_Clock : process (reset, clk)
begin
if reset = '1' then
ps2fixedClock <= "00";
elsif (rising_edge(clk)) then
ps2fixedClock(0) <= ps2fixedClock(1);
ps2fixedClock(1) <= ps2Clk;
end if;
end process ps2fixed_Clock;
also you should use clk in your state_machine process
state_machine : process (clk, reset)
begin
if (reset = '1') then
...
elsif (rising_edge(clk)) then
...
if you want to use a clock divider (divided_clock process), you can generate an enable signal (as you did) and use it after you synchronized the clocks, e.g. in the state machine!

VHDL - Making a clock from another module's output signal

I am modifying a simple keyboard interface I found on the net to my use. The idea is whenever there is a new scancode, it will make the output named "Scan_Dav" go high, and then go low. So when I direct Scan_Dav to another module as a clock, that module's clock will have a rising edge whenever a new ScanCode is pressed. Is there any error in my way of thinking? Because I tried it and directed the scancode and scan_dav to the rest of my project -which writes letters side by side with the given scancodes and shows them on seven segment display- the displayed text had 2 of each character ( i.e. when I write FLY the text was like FFLLYY). If there is no errors, I will share my code and ask you why it is not working. Thanks :)
EDIT: This is where the shifting is done according to values of Scan_Dav
signal bytes : std_logic_vector(63 downto 0);
signal Scan_Dav_Sync: std_logic_vector(1 downto 0):="00";
signal Previous_Scan_Dav: std_logic:='0';
begin
process (clk) begin --, Scan_Dav) begin
if rising_edge(clk) then
Scan_Dav_Sync(0) <= Scan_Dav;
Scan_Dav_Sync(1) <= Scan_Dav_Sync(0);
Previous_Scan_Dav <= Scan_Dav_Sync(1);
if (Previous_Scan_Dav = '0') and (Scan_Dav_Sync(1) = '1') then
bytes <= bytes (bytes'high-8 downto 0) & Data_in;
end if;
end if;
end process;
This is where Scan_Dav comes from, the code is taken from here:
(You may ignore the filtering part)
Architecture Behavioral of KeyboardController is
signal PS2_Datr : std_logic;
subtype Filter_t is std_logic_vector(7 downto 0);
signal Filter : Filter_t;
signal Fall_Clk : std_logic;
signal Bit_Cnt : unsigned (3 downto 0);
signal Scan_DAVi : std_logic;
signal S_Reg : std_logic_vector(8 downto 0);
signal PS2_Clk_f : std_logic;
Type State_t is (Idle, Shifting);
signal State : State_t;
signal Scan_Code : std_logic_vector(7 downto 0);
signal Flag : std_logic:='0';
begin
process (Clk,Reset)
begin
if Reset='1' then
PS2_Datr <= '0';
PS2_Clk_f <= '0';
Filter <= (others=>'0');
Fall_Clk <= '0';
elsif rising_edge (Clk) then
PS2_Datr <= PS2_Data and PS2_Data; -- also turns 'H' into '1'
Fall_Clk <= '0';
Filter <= (PS2_Clk and PS2_CLK) & Filter(Filter'high downto 1);
if Filter = Filter_t'(others=>'1') then
PS2_Clk_f <= '1';
elsif Filter = Filter_t'(others=>'0') then
PS2_Clk_f <= '0';
if PS2_Clk_f = '1' then
Fall_Clk <= '1';
end if;
end if;
end if;
end process;
-- This simple State Machine reads in the Serial Data
-- coming from the PS/2 peripheral.
process(Clk,Reset)
begin
if Reset='1' then
State <= Idle;
Bit_Cnt <= (others => '0');
S_Reg <= (others => '0');
Scan_Code <= (others => '0');
Scan_Out <= (others => '0');
Scan_Davi <= '0';
elsif rising_edge (Clk) then
-- if Scan_Davi = '1' then
-- Scan_Davi <= '0';
-- end if;
case State is
when Idle =>
Bit_Cnt <= (others => '0');
-- note that we dont need to clear the Shift Register
if Fall_Clk='1' and PS2_Datr='0' then -- Start bit
State <= Shifting;
end if;
when Shifting =>
if Bit_Cnt >= 9 then
if Fall_Clk='1' then -- Stop Bit
Scan_Code <= S_Reg(7 downto 0);
if (Flag = '1' and Scan_Code /= "11110000") then
--to ignore makecode
Scan_Out <= Scan_Code;
Flag <= '0';
Scan_Davi <= '1';
end if;
if (Flag = '0' and Scan_Code = "11110000") then
--to ignore F0
Flag <= '1';
Scan_Davi <= '0';
end if;
State <= Idle;
end if;
elsif Fall_Clk='1' then
Bit_Cnt <= Bit_Cnt + 1;
S_Reg <= PS2_Datr & S_Reg (S_Reg'high downto 1); -- Shift right
end if;
when others => -- never reached
State <= Idle;
end case;
end if;
end process;
Scan_DAV <= Scan_DAVi;
end Behavioral;
UPDATE: The only problem that remains is the delayed display and shifting of the letter and the text. While writing VHDL, I get nothing after pressing V, then I get V when I press H and it goes like that. The last letter does not appear until another key is pressed.It seems to be an issue about Scan_Dav, yet I can not resolve what it is. Any help will be appreciated.
Driving a clock input from logic output is generally bad practice (and some FPGA fabrics will not allow it at all). Clocks run best when sourced from dedicated clock logic inside the part, and good designs should minimize the number of clocks. Ideally you'd have only one, but that's not always possible.
Instead of running a clock input from logic, consider running everything off of one clock and use "enables" to activate the logic only when needed. In this case, you would detect the rising-edge transition of scan_dav inside of the downstream module and only react when that transition occurs. The detection logic would run off of the same clock as the scan_dav module.
I don't think this explains why you're seeing double characters, you would need to post some code to analyze. However, I would recommend that you re-tool to not drive clocks from logic.
If I see it right you avoid the F0 when you release the Key but you do not filter the second scancode.
It's always like this
Scancode --- press Key
F0 --- relesase Key
Scancode
on some Keys (e.g ALT GR) you can get an E0 too.
It not complete description but the most importand thinks are shown.
http://en.wikipedia.org/wiki/Scancode
This would lead to the descripted problem. FLY -> FFLLYY.

Resources