library IEEE;
use IEEE.STD_Logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity DotMartixDisplay is
port(
reset:in std_logic;--重置,球拍位置 s0
clk:in std_logic; --球拍移动的 敏感 信号
lbt:in std_logic; --球拍移动的控制信号,为1时向p3状态(点阵的右边)靠近,反之向p0
SClk:Buffer std_Logic; --SWitch,切换 当前 点阵 显示 内容 的 敏感 信号
CClk:in std_logic; --球位置计算 敏感信号
row:out std_logic_vector(0 to 15);
lin:out std_logic_vector(0 to 15)
);
end entity;
architecture bhv of DotMartixDisplay is
--球拍
type BoardPosition is (p0,p1,p2,p3);--从左到右,每四个点构成一个状态
signal BdPs: BoardPosition; --球拍的位置信号量
--球
Signal HisBaPsR: Integer Range 0 To 15:=0;--历史坐标 初始在最左下脚
Signal HisBaPsL: Integer Range 0 To 15:=0;
Signal CurBaPsR: Integer Range 0 To 15:=1;--当前坐标 (1,1)位置
Signal CurBaPsL: Integer Range 0 To 15:=1;
Signal NexBaPsR,NexBaPsL: Integer Range 0 To 15;--下一步坐标
Signal DisplayBoard:Std_logic:='0'; --现在显示球的位置吗 ?不是则显示 球拍
Signal ToNext:Std_Logic:='0';--现在跳 到 下 一步 吗 ?否则 计算下一步 还
Signal WinScore: Integer Range 0 to 9:=0; --击中球的次数
--Signal LosScore: Integer Range 0 to 9:=0; --未击中球次数
Constant Tun:integer :=2; --CClk 对 SClk的倍数
begin
Div_clk: --使用分频器获得点阵上对输出 球拍/球 状态切换的敏感信号 。默认是Tun-1(1倍),即在第一次CCLK时计算下一个移动点,下一个CCLK时进行移动
Process(CCLk)
variable cnt:integer range 0 to 2048:=0;
begin
if rising_edge(CClk) then
if (cnt <Tun) then
SClk <='1';
cnt:=cnt+1;
elsif (cnt <Tun+Tun) then
SClk <='0';
cnt:=cnt+1;
else
cnt:=0;
end if;
end if;
end Process;
ButtonDown:--按下球拍 控制键
process(clk,reset)
begin
if reset='1' then BdPs <=p0;--球拍的初始位置
elsif rising_edge(clk) then --上升沿
if lbt='1' then
if BdPs=p1 then BdPs <=p0;
elsif BdPs=p2 then BdPs <=p1;
elsif BdPs=p3 then BdPs <=p2;
end if ;
else
if BdPs=p2 then BdPs <=p3;
elsif BdPs=p1 then BdPs <=p2;
elsif BdPs=p0 then BdPs <=p1;
end if ;
end if;
end if;
end Process;
---接上
ShowB:
process(SClk)
begin
if rising_edge(SClk) then
if DisplayBoard='1' then --显示球拍位置
case BdPs is
when p0 =>
row <="0111111111111111";
lin <="1111000000000000";
when p1 =>
row <="0111111111111111";
lin <="0000111100000000";
when p2 =>
row <="0111111111111111";
lin <="0000000011110000";
when p3 =>
row <="0111111111111111";
lin <="0000000000001111";
end case;
DisplayBoard <='0';
else --显示球的位置
case CurBaPsR is --设置行信息
when 1 =>
row <="1011111111111111";
when(...省略,针对CurBaPsR的其他15种可能取值控制点阵的行电平高低)
end case;
case CurBaPsL is
when 0 =>
lin <="1000000000000000";
when(...省略,针对CurBaPsL的其他15种可能取值控制点阵的列电平高低)
end case;
DisPlayBoard <='1';
end if;
end if;
end process;
NexBaPs:--计算球的位置
process(CClk) --问题代码可能就这段,球在(0,0)位置不动,不移动到下一个点
begin
if rising_edge(CClk) then
if ToNext='0' then --上升沿 ,计算下一个位置
if CurBaPsL=0 or CurBaPsL =15 then --碰到左右两边 的 墙壁
NexBaPsR <=CurBaPsR+(CurBaPsR-HisBaPsR);
NexBaPsL <=HisBaPsL;
elsif CurBaPsR=15 then --碰 到 顶端 的 墙壁
NexBaPsL <= CurBaPsL+(CurBaPsL-HisBaPsL);
NexBaPsR <=HisBaPsR;
elsif CurBaPsR =0 then ---到达低端
if (
(CurBaPsL <4 and BdPs=p0) or
(CurBaPsL>3 and CurBaPsL <8 and BdPs=p1) or
(CurBaPsL>7 and CurBaPsL <12 and BdPs=p2) or
(CurBaPsL>11 and CurBaPsL <16 and BdPs=p3) ) then ---球拍击中球 了
---计算下一个 位置
NexBaPsR <=CurBaPsR+(CurBaPsR-HisBaPsR);
NexBaPsL <=CurBaPsL+(CurBaPsL-HisBaPsL);
end if;
else --在平常 运动范围 内
NexBaPsR <= CurBaPsR+(CurBaPsR-HisBaPsR);
NexBaPsL <= CurBaPsL+(CurBaPsL-HisBaPsL);
end if ;
ToNext <='1';
else
HisBaPsL <=CurBaPsL;
HisBaPsR <=CurBaPsR;
CurBaPsL <=NexBaPsL;
CurBaPsR <=NexBaPsR;
ToNext <='0';
end if ;
end if ;
end process;
end architecture bhv;