当前位置:   article > 正文

【tusterのFPGA作业教程】第四章:实验3——俄罗斯方块的旋转测试与动作(1)

【tusterのFPGA作业教程】第四章:实验3——俄罗斯方块的旋转测试与动作(1)

任务1:I型模块的逆时针旋转测试与动作

        1. 完成实验表格

        本实验的解决关键在于能否正确填写下发的实验表格。如果能理解表格中填写的各位置函数关系并在代码相应位置对应更改,就可以轻松完成所有实验内容。

        上图为下发的实验表格,经观察可知:示例的I型模块旋转过程分为四个form,每旋转90°为一个form,依次对应“00”“01”“10”“11”状态。旋转前组成I型模块的四个点阵由数字1-4表示,旋转后的I型模块位置用〇表示,旋转过程中的阻挡位置用×表示。旋转中心用带圈的数字③表示。每个点阵由两个坐标函数pnx, pny表示。坐标原点位于点阵屏的左上角,即从左往右,八列点阵的坐标分别为000, 001, 010, 011, 100, 101, 110, 111,从上往下,八行点阵的坐标分别为000, 001, 010, 011, 100, 101, 110, 111(注意是从0开始,0代表第一行,这里非常重要!!!)同时,表中还给出了旋转中心的坐标限制"000"<p3y<"110",即点阵3需要保证位于第二行至第六行。
        旋转过程中,测试空位和测试阻挡的坐标均由原始点阵坐标导出。以forms="00"点“4”上方的阻挡为例(下图标红×),其坐标可由点“4”写出,由于其与“4”位于同一列,故横坐标相同,其位于“4”上方一个单位,故纵坐标为p4y-1。因此此阻挡的坐标可表示为p4x, p4y-1。

        旋转后的坐标由对应的点坐标导出。以forms="00"点“1”为例,其逆时针旋转90°后位置见下图标红〇。与原坐标相比,向右移动两个单位,向下移动两个单位。故其旋转后坐标可表示为p1x+2, p1y+2。

        综上,我们可以补全表1,得到以下完整表格。

 2. 理解表格中坐标如何在代码中实现

        本实验的主要控制过程代码在模块ctrl_Irotate.vhd中给出,故我们可以研究此模块代码,来分析如何实现模块的旋转功能。通过观察给出的代码,我们可以发现影响模块旋转功能的代码主要有以下几个部分组成:

        2.1 test_n函数

  1. when test_n=>
  2. case next_n is--共4种测试项
  3. when"00"=>--测试旋转
  4. forms<="00";--I型模块,p1 p2 p3 p4
  5. --
  6. --
  7. --p1 p2 p3 p4,左上,第三行
  8. p1x<="000";p2x<="001";p3x<="010";p4x<="011";
  9. p1y<="010";p2y<="010";p3y<="010";p4y<="010";
  10. p5x<="111";p5y<="010";
  11. when"01"=>--测试边界
  12. forms<="00";
  13. --
  14. --p1 p2 p3 p4,左上角,第2
  15. p1x<="000";p2x<="001";p3x<="010";p4x<="011";
  16. p1y<="001";p2y<="001";p3y<="001";p4y<="001";
  17. p5x<="110";p5y<="111";
  18. when"10"=>--测试位置被占
  19. forms<="00";
  20. --p1 p2 p3 p4,居中
  21. -- p5
  22. p1x<="010";p2x<="011";p3x<="100";p4x<="101";
  23. p1y<="100";p2y<="100";p3y<="100";p4y<="100";
  24. p5x<="100";p5y<="101";
  25. when"11"=>--测试旋转路径有阻挡
  26. forms<="00";
  27. --p1 p2 p3 p4,居中
  28. -- p5
  29. p1x<="010";p2x<="011";p3x<="100";p4x<="101";
  30. p1y<="100";p2y<="100";p3y<="100";p4y<="100";
  31. p5x<="101";p5y<="101";
  32. when others=>null;
  33. end case;
  34. make<=X"1"; state<=display;

        这里给出的是四种测试项,对应实验设计任务上的正常旋转、靠近点阵四周、位置被占、旋转路径有阻挡。由第一节已知各点坐标的表示方法,即可表示出四种情况的对应坐标。其中p5表示一种可能的阻挡,在前两种情况中无需考虑,将p5设置为任意远离模块的坐标即可。在第三种情况中,需要考虑测试位置被占的情况,因此可以将p5置于p3下方,模拟旋转目标点阵位置被占的情况。同理,在第四种情况中,将p5置于p4下方。

        2.2 测试边界、空位与阻挡

  1. --测试I型模块能否以p3为轴心逆时针旋转--
  2. --测试边界、空位与阻挡--
  3. when test_Lp3=>
  4. case test is
  5. --测试边界与空位1--
  6. when X"1"=>--test
  7. if(forms="00")then
  8. if(p3y>"000" and p3y<"110")then--边界条件
  9. cx<=p3x; cy<=p3y-1; test<=X"2";--测试空位1
  10. else
  11. state<=wait_btn;--不能旋转,等待操作键
  12. end if;
  13. elsif(forms="01")then
  14. if(p3x>"000" and p3x<"110")then
  15. cx<=p3x-1; cy<=p3y; test<=X"2";
  16. else
  17. state<=wait_btn;
  18. end if;
  19. elsif(forms="10")then
  20. if(p3y>"001" and p3y<"111")then
  21. cx<=p3x; cy<=p3y-2; test<=X"2";
  22. else
  23. state<=wait_btn;
  24. end if;
  25. elsif(forms="11")then
  26. if(p3x>"001" and p3x<"111")then
  27. cx<=p3x-2; cy<=p3y; test<=X"2";
  28. else
  29. state<=wait_btn;
  30. end if;
  31. end if;
  32. when X"2"=>
  33. if(dotin="1")then--高电平点亮,位置已被占
  34. state<=wait_btn;--不能旋转,等待操作键
  35. else
  36. test<=X"3";--有空位,测试下一个位置
  37. end if;
  38. --测试空位2--
  39. when X"3"=>--test
  40. if(forms="00")then
  41. cx<=p3x; cy<=p3y+1; test<=X"4";
  42. elsif(forms="01")then
  43. cx<=p3x+1; cy<=p3y; test<=X"4";
  44. elsif(forms="10")then
  45. cx<=p3x; cy<=p3y-1; test<=X"4";
  46. elsif(forms="11")then
  47. cx<=p3x-1; cy<=p3y; test<=X"4";
  48. end if;
  49. when X"4"=>
  50. if(dotin="1")then state<=wait_btn;
  51. else
  52. test<=X"5";
  53. end if;
  54. --测试空位3--
  55. when X"5"=>--test
  56. if(forms="00")then
  57. cx<=p3x; cy<=p3y+2; test<=X"6";
  58. elsif(forms="01")then
  59. cx<=p3x+2; cy<=p3y; test<=X"6";
  60. elsif(forms="10")then
  61. cx<=p3x; cy<=p3y+1; test<=X"6";
  62. elsif(forms="11")then
  63. cx<=p3x+1; cy<=p3y; test<=X"6";
  64. end if;
  65. when X"6"=>
  66. if(dotin="1")then state<=wait_btn;
  67. else
  68. test<=X"7";
  69. end if;
  70. --测试阻挡1--
  71. when X"7"=>--test
  72. if(forms="00")then
  73. cx<=p1x; cy<=p1y+1; test<=X"8";
  74. elsif(forms="01")then
  75. cx<=p1x+1; cy<=p1y; test<=X"8";
  76. elsif(forms="10")then
  77. cx<=p1x; cy<=p1y-1; test<=X"8";
  78. elsif(forms="11")then
  79. cx<=p1x-1; cy<=p1y; test<=X"8";
  80. end if;
  81. when X"8"=>
  82. if(dotin="1")then --高电平点亮,有阻挡
  83. state<=wait_btn;--不能旋转,等待操作键
  84. else
  85. test<=X"9";--无阻挡,测试下一个位置
  86. end if;
  87. --测试阻挡2--
  88. when X"9"=>--test
  89. if(forms="00")then
  90. cx<=p2x; cy<=p2y+1; test<=X"A";
  91. elsif(forms="01")then
  92. cx<=p2x+1; cy<=p2y; test<=X"A";
  93. elsif(forms="10")then
  94. cx<=p2x; cy<=p2y-1; test<=X"A";
  95. elsif(forms="11")then
  96. cx<=p2x-1; cy<=p2y; test<=X"A";
  97. end if;
  98. when X"A"=>
  99. if(dotin="1")then
  100. state<=wait_btn;
  101. else
  102. test<=X"B";
  103. end if;
  104. --测试阻挡3--
  105. when X"B"=>--test
  106. if(forms="00")then
  107. cx<=p2x; cy<=p2y+2; test<=X"C";
  108. elsif(forms="01")then
  109. cx<=p2x+2; cy<=p2y; test<=X"C";
  110. elsif(forms="10")then
  111. cx<=p2x; cy<=p2y-2; test<=X"C";
  112. elsif(forms="11")then
  113. cx<=p2x-2; cy<=p2y; test<=X"C";
  114. end if;
  115. when X"C"=>
  116. if(dotin="1")then
  117. state<=wait_btn;
  118. else
  119. test<=X"D";
  120. end if;
  121. --测试阻挡4--
  122. when X"D"=>--test
  123. if(forms="00")then
  124. cx<=p4x; cy<=p4y-1; test<=X"E";
  125. elsif(forms="01")then
  126. cx<=p4x-1; cy<=p4y; test<=X"E";
  127. elsif(forms="10")then
  128. cx<=p4x; cy<=p4y+1; test<=X"E";
  129. elsif(forms="11")then
  130. cx<=p4x+1; cy<=p4y; test<=X"E";
  131. end if;
  132. when X"E"=>
  133. if(dotin="1")then
  134. state<=wait_btn;
  135. else
  136. make<=X"8"; state<=rotate_Lp3;
  137. end if;
  138. when others=>null;
  139. end case;

        在以上函数中,依次判断表中填写的边界条件、空位和阻挡。首先判断旋转中心p3位置是否在边界之内,否则无法旋转,跳出。在满足边界条件的情况下,依次判断空位1、空位2、空位3、阻挡1、阻挡2、阻挡3、阻挡4的点是否亮起(高电平),如果亮起则表示该位置无法旋转,跳出。注意这里的空位和阻挡要按顺序写,即空位1为表中每种状态下填写的第一个空位点(下图用黄色标出),以此类推。空位和阻挡的个数可视具体问题增删,在后续实验任务中会解释。

         2.3 I型模块以p3为轴逆时针旋转

  1. --I型模块以p3为轴心逆时针旋转--
  2. when rotate_Lp3=>
  3. case make is --make:8~F
  4. --清空原片--
  5. when X"8"=>
  6. wen_tmp<="1";--开写使能
  7. dotout_tmp<="0";--低电平,熄灭led灯
  8. cx<=p1x; cy<=p1y; make<=X"9";
  9. when X"9"=>
  10. cx<=p2x; cy<=p2y; make<=X"A";
  11. when X"A"=>
  12. cx<=p4x; cy<=p4y; make<=X"B";
  13. --更新p1,p2,p4新片位置--
  14. when X"B"=>--make
  15. if(forms="00")then
  16. p1x<=p1x+2; p1y<=p1y+2;
  17. p2x<=p2x+1; p2y<=p2y+1;
  18. p4x<=p4x-1; p4y<=p4y-1;
  19. elsif(forms="01")then
  20. p1x<=p1x+2; p1y<=p1y-2;
  21. p2x<=p2x+1; p2y<=p2y-1;
  22. p4x<=p4x-1; p4y<=p4y+1;
  23. elsif(forms="10")then
  24. p1x<=p1x-2; p1y<=p1y-2;
  25. p2x<=p2x-1; p2y<=p2y-1;
  26. p4x<=p4x+1; p4y<=p4y+1;
  27. elsif(forms="11")then
  28. p1x<=p1x-2; p1y<=p1y+2;
  29. p2x<=p2x-1; p2y<=p2y+1;
  30. p4x<=p4x+1; p4y<=p4y-1;
  31. end if;
  32. make<=X"C";
  33. --显示新片--
  34. when X"C"=>--make
  35. dotout_tmp<="1";--高电平,点亮led灯
  36. cx<=p1x; cy<=p1y; make<=X"D";
  37. when X"D"=>
  38. cx<=p2x; cy<=p2y; make<=X"E";
  39. when X"E"=>
  40. cx<=p4x; cy<=p4y; make<=X"F";
  41. when X"F"=>--make
  42. wen_tmp<="0";--关写使能

        此函数内需要我们填写旋转后的各点坐标,与表中最后一列内容对应。注意最后“显示新片”位置需要考虑旋转轴,示例的旋转轴为p3,因此p3位置始终不更新,只需要更新p1, p2, p4的位置。 

至此,I型模块的逆时针旋转测试与动作实验所有内容全部实现,相信你也掌握了旋转控制代码的原理。接下来将更新任务2:I型模块的顺时针旋转测试与动作。敬请期待。

附:本章节需要用到的代码:

Irotate_top.vhd: 

  1. --库
  2. library ieee;
  3. use ieee.std_logic_1164.all;
  4. use ieee.std_logic_arith.all;
  5. use ieee.std_logic_unsigned.all;
  6. --实体
  7. entity Irotate_top is
  8. port (clk_50M : in std_logic; --50MHz
  9. rst : in std_logic;
  10. btn_in : in std_logic_vector(2 downto 0);
  11. DIN: out std_logic;
  12. CS: out std_logic;
  13. CLK_MAX7219 : out std_logic);
  14. end;
  15. --结构体
  16. architecture behavioral of Irotate_top is
  17. component clkdiv_50M
  18. port (clk_50M : in std_logic; --50MHz
  19. rst : in std_logic;
  20. clk_btn: out std_logic;
  21. clk_game:out std_logic;
  22. clk_rama : out std_logic);
  23. end component;
  24. component btn_detect
  25. port (clk_btn : in std_logic;
  26. rst : in std_logic;
  27. btn_in : in std_logic_vector(2 downto 0);
  28. btn_en : out std_logic;
  29. btn_nlr : out std_logic_vector(2 downto 0));
  30. end component;
  31. component ctrl_Irotate
  32. port (clk_game : in std_logic;
  33. rst : in std_logic;
  34. btn_en : in std_logic;
  35. dotin : in std_logic_vector(0 downto 0);
  36. btn_nlr : in std_logic_vector(2 downto 0);
  37. addrb : out std_logic_vector(8 downto 0);
  38. web : out std_logic_vector(0 downto 0);
  39. dotout : out std_logic_vector(0 downto 0));
  40. end component;
  41. component ctrl_dotcasebitT
  42. port (clk_rama : in std_logic;
  43. rst : in std_logic;
  44. dataa : in std_logic_vector(0 downto 0);
  45. btn_en:in std_logic;
  46. dispgame:in std_logic;
  47. din : out std_logic;
  48. load_cs : out std_logic;
  49. clk_max7219 : out std_logic;
  50. addra : out std_logic_vector(8 downto 0));
  51. end component;
  52. component ram2ip
  53. port (clka : in std_logic;
  54. addra : in std_logic_vector(8 downto 0);
  55. wea : in std_logic_vector(0 downto 0):="0";
  56. dina : in std_logic_vector(0 downto 0):="0";
  57. clkb : in std_logic;
  58. addrb : in std_logic_vector(8 downto 0);
  59. web : in std_logic_vector(0 downto 0);
  60. dinb : in std_logic_vector(0 downto 0);
  61. douta : out std_logic_vector(0 downto 0);
  62. doutb : out std_logic_vector(0 downto 0));
  63. end component;
  64. signal clk_rama1:std_logic;
  65. signal clk_game: std_logic;
  66. signal clk_btn:std_logic;
  67. signal btn_en1:std_logic;
  68. signal btn_nlr: std_logic_vector(2 downto 0);
  69. signal dotin1:std_logic_vector(0 downto 0);
  70. signal addrb:std_logic_vector(8 downto 0);
  71. signal web:std_logic_vector(0 downto 0);
  72. signal dotout1:std_logic_vector(0 downto 0);
  73. signal dataa1:std_logic_vector(0 downto 0);
  74. signal addra:std_logic_vector(8 downto 0);
  75. begin
  76. --元件例化语句
  77. u1:clkdiv_50M port map(
  78. clk_50M => clk_50M,
  79. rst => rst,
  80. clk_rama => clk_rama1,
  81. clk_game => clk_game,
  82. clk_btn => clk_btn);
  83. u2:btn_detect port map(
  84. clk_btn => clk_btn,
  85. rst => rst,
  86. btn_in => btn_in,
  87. btn_en => btn_en1,
  88. btn_nlr => btn_nlr);
  89. u3:ctrl_Irotate port map(
  90. rst => rst,
  91. clk_game => clk_game,
  92. btn_en => btn_en1,
  93. btn_nlr => btn_nlr,
  94. dotin => dotin1,
  95. addrb => addrb,
  96. web => web,
  97. dotout => dotout1);
  98. u4:ctrl_dotcasebitT port map(
  99. clk_rama => clk_rama1,
  100. rst => rst,
  101. btn_en => btn_en1,
  102. dataa => dataa1,
  103. dispgame => btn_nlr(2),
  104. addra => addra,
  105. din => DIN,
  106. load_cs => CS,
  107. clk_max7219 => CLK_MAX7219);
  108. u5:ram2ip port map(
  109. clka => clk_rama1,
  110. addra => addra,
  111. clkb => clk_50M,
  112. addrb => addrb,
  113. web => web,
  114. dinb => dotout1,
  115. douta => dataa1,
  116. doutb => dotin1);
  117. end behavioral;

clkdiv_50M.vhd: 

  1. --库
  2. library ieee;
  3. use ieee.std_logic_1164.all;
  4. use ieee.std_logic_arith.all;
  5. use ieee.std_logic_unsigned.all;
  6. --实体
  7. entity clkdiv_50M is
  8. port (clk_50M : in std_logic; --50MHz
  9. rst : in std_logic;
  10. clk_btn: out std_logic;
  11. clk_game:out std_logic;
  12. clk_rama : out std_logic);
  13. end;
  14. --结构体
  15. architecture behavioral of clkdiv_50M is
  16. signal cnt:std_logic_vector(25 downto 0);
  17. begin
  18. process(rst,clk_50M)
  19. begin
  20. if(rst='1')then
  21. cnt<=(others=>'0');
  22. elsif rising_edge(clk_50M)then
  23. cnt<=cnt+1;
  24. end if;
  25. end process;
  26. clk_btn<=cnt(7);
  27. clk_game<=cnt(2);
  28. clk_rama<=cnt(8);
  29. end behavioral;

btn_detect.vhd:

  1. --库
  2. library ieee;
  3. use ieee.std_logic_1164.all;
  4. use ieee.std_logic_arith.all;
  5. use ieee.std_logic_unsigned.all;
  6. --实体
  7. entity btn_detect is
  8. port (clk_btn : in std_logic;
  9. rst : in std_logic;
  10. btn_in : in std_logic_vector(2 downto 0);
  11. btn_en : out std_logic;
  12. btn_nlr : out std_logic_vector(2 downto 0));
  13. end;
  14. --结构体
  15. architecture behavioral of btn_detect is
  16. component debounce is
  17. port(clk:in std_logic;
  18. rst:in std_logic;
  19. start:in std_logic;
  20. done:out std_logic);
  21. end component;
  22. signal start,done:std_logic:='0';
  23. signal btn_down,en_tmp:std_logic:='0';
  24. begin
  25. process(rst,clk_btn,btn_in)
  26. begin
  27. if(rst='1')then
  28. btn_down<='0';
  29. elsif rising_edge(clk_btn)then
  30. if(btn_in/="000")then --有键按下
  31. if(done='0')then
  32. start<='1';
  33. else
  34. start<='0';
  35. end if;
  36. if(start&done="11")then
  37. btn_nlr<=btn_in;
  38. btn_down<='1'; --确实有键按下
  39. end if;
  40. else
  41. btn_down<='0';
  42. start<='0';
  43. end if;
  44. end if;
  45. end process;
  46. --检测到有键按下,则btn_en翻转,控制ctrl_Irotate
  47. process(btn_down)
  48. begin
  49. if rising_edge(btn_down)then
  50. en_tmp<=not en_tmp;
  51. end if;
  52. end process;
  53. btn_en<=en_tmp;
  54. u2i:debounce port map(
  55. clk=>clk_btn,
  56. rst=>rst,
  57. start=>start,
  58. done=>done);
  59. end behavioral;

debounce.vhd:

  1. --库
  2. library ieee;
  3. use ieee.std_logic_1164.all;
  4. use ieee.std_logic_arith.all;
  5. use ieee.std_logic_unsigned.all;
  6. --实体
  7. entity debounce is
  8. port (clk: in std_logic;
  9. rst: in std_logic;
  10. start: in std_logic;
  11. done: out std_logic);
  12. end;
  13. --结构体
  14. architecture behavioral of debounce is
  15. signal cnt_delay:std_logic_vector(13 downto 0);--延时计数
  16. signal done_tmp:std_logic:='0';
  17. begin
  18. process(rst,clk,start)
  19. begin
  20. if(rst='1')then
  21. done_tmp<='0';
  22. cnt_delay<=(others=>'0');
  23. elsif rising_edge(clk)then
  24. if(start='1')then --有键按下
  25. if(cnt_delay>X"300")then
  26. done_tmp<='1'; --确实有键按下
  27. else
  28. cnt_delay<=cnt_delay+1;
  29. end if;
  30. else --无键按下
  31. done_tmp<='0';
  32. cnt_delay<=(others=>'0');
  33. end if;
  34. end if;
  35. done<=done_tmp;
  36. end process;
  37. end behavioral;

crtl_Irotate.vhd:

  1. --库
  2. library ieee;
  3. use ieee.std_logic_1164.all;
  4. use ieee.std_logic_arith.all;
  5. use ieee.std_logic_unsigned.all;
  6. --实体
  7. entity ctrl_Irotate is
  8. port (clk_game: in std_logic;
  9. rst: in std_logic;
  10. btn_en: in std_logic;
  11. dotin: in std_logic_vector(0 downto 0);
  12. btn_nlr: in std_logic_vector(2 downto 0);
  13. addrb: out std_logic_vector(8 downto 0);
  14. web: out std_logic_vector(0 downto 0);
  15. dotout: out std_logic_vector(0 downto 0));
  16. end;
  17. --结构体
  18. architecture behavioral of ctrl_Irotate is
  19. type state_group is(wait_btn,clr_screen,test_n,display,test_Lp3,rotate_Lp3);
  20. signal state:state_group:=wait_btn;
  21. signal test:std_logic_vector(3 downto 0):=X"0";--测试
  22. signal make:std_logic_vector(3 downto 0):=X"0";--动作
  23. signal makex,makey:std_logic_vector(3 downto 0):=X"0";--清屏
  24. signal next_n:std_logic_vector(1 downto 0):="00";--切换测试项
  25. signal rst_en,btnen_tmp:std_logic:='0';
  26. signal wen_tmp:std_logic_vector(0 downto 0):="0";
  27. signal dotout_tmp:std_logic_vector(0 downto 0);
  28. signal cy:std_logic_vector(2 downto 0):="000";--8行
  29. signal cx:std_logic_vector(2 downto 0):="000";--8列
  30. signal p1x,p2x,p3x,p4x,p5x:std_logic_vector(2 downto 0):="000";
  31. signal p1y,p2y,p3y,p4y,p5y:std_logic_vector(2 downto 0):="000";
  32. signal forms:std_logic_vector(1 downto 0):="00";--I型模块的形状
  33. begin
  34. web<=wen_tmp;
  35. addrb<="01"&cy&"1"&cx;--俄罗斯方块旋转测试界面的地址
  36. dotout<=dotout_tmp;
  37. process(rst,clk_game,btn_en,dotin,state,make,test)
  38. begin
  39. if(rst='1')then
  40. rst_en <= '1';
  41. btnen_tmp <= btn_en;
  42. makey <= X"0";
  43. makex <= X"0";
  44. state <= clr_screen;
  45. elsif rising_edge(clk_game)then
  46. --识别操作键
  47. if(btnen_tmp/=btn_en)then
  48. btnen_tmp<=not btnen_tmp;
  49. --BTN3:切换测试项
  50. if(btn_nlr="100" and state=wait_btn)then
  51. next_n<=next_n+1;
  52. makey<=X"0"; makex<=X"0"; state<=clr_screen;
  53. --BTN2:逆时针旋转(向左转)
  54. elsif(btn_nlr="010"and state=wait_btn)then
  55. test<=X"1"; state<=test_Lp3;
  56. --BTN1:顺时针旋转(向右转),此功能待开发(实验任务)
  57. elsif(btn_nlr="001"and state=wait_btn)then
  58. test<=X"1";state<=test_Rp3;
  59. end if;
  60. else
  61. case state is
  62. --等待按键操作--
  63. when wait_btn=>null;
  64. --清屏--
  65. when clr_screen=>
  66. if(makex<X"8")then
  67. wen_tmp<="1";--开写使能
  68. dotout_tmp<="0";--清空点阵显示,低电平不亮
  69. cx<=makex(2 downto 0); makex<=makex+1;
  70. cy<=makey(2 downto 0);
  71. else
  72. if(makey<X"8")then
  73. makey<=makey+1; makex<=X"0";
  74. else
  75. wen_tmp<="0";--关写使能
  76. if(rst_en='1')then
  77. rst_en<='0'; state<=wait_btn;
  78. else state<=test_n;
  79. end if;
  80. end if;
  81. end if;
  82. --选择新的测试项--
  83. when test_n=>
  84. case next_n is--共4种测试项
  85. when"00"=>--测试旋转
  86. forms<="00";--I型模块,p1 p2 p3 p4
  87. --
  88. --
  89. --p1 p2 p3 p4,左上,第三行
  90. p1x<="000";p2x<="001";p3x<="010";p4x<="011";
  91. p1y<="010";p2y<="010";p3y<="010";p4y<="010";
  92. p5x<="111";p5y<="010";
  93. when"01"=>--测试边界
  94. forms<="00";
  95. --
  96. --p1 p2 p3 p4,左上角,第2行
  97. p1x<="000";p2x<="001";p3x<="010";p4x<="011";
  98. p1y<="001";p2y<="001";p3y<="001";p4y<="001";
  99. p5x<="110";p5y<="111";
  100. when"10"=>--测试位置被占
  101. forms<="00";
  102. --p1 p2 p3 p4,居中
  103. -- p5
  104. p1x<="010";p2x<="011";p3x<="100";p4x<="101";
  105. p1y<="100";p2y<="100";p3y<="100";p4y<="100";
  106. p5x<="100";p5y<="101";
  107. when"11"=>--测试旋转路径有阻挡
  108. forms<="00";
  109. --p1 p2 p3 p4,居中
  110. -- p5
  111. p1x<="010";p2x<="011";p3x<="100";p4x<="101";
  112. p1y<="100";p2y<="100";p3y<="100";p4y<="100";
  113. p5x<="101";p5y<="101";
  114. when others=>null;
  115. end case;
  116. make<=X"1"; state<=display;
  117. --显示新的测试项形状--
  118. when display=>
  119. case make is --make:1~5
  120. when X"1"=>
  121. wen_tmp<="1";--开写使能
  122. dotout_tmp<="1";--高电平,点亮led灯
  123. cx<=p1x; cy<=p1y; make<=X"2";
  124. when X"2"=>
  125. cx<=p2x; cy<=p2y; make<=X"3";
  126. when X"3"=>
  127. cx<=p3x; cy<=p3y; make<=X"4";
  128. when X"4"=>
  129. cx<=p4x; cy<=p4y; make<=X"5";
  130. when X"5"=>
  131. cx<=p5x; cy<=p5y; make<=X"0";
  132. when others=>
  133. wen_tmp<="0";--关写使能
  134. state<=wait_btn;--等待操作键
  135. end case;
  136. --测试I型模块能否以p3为轴心逆时针旋转--
  137. --测试边界、空位与阻挡--
  138. when test_Lp3=>
  139. case test is
  140. --测试边界与空位1--
  141. when X"1"=>--test
  142. if(forms="00")then
  143. if(p3y>"000" and p3y<"110")then--边界条件
  144. cx<=p3x; cy<=p3y-1; test<=X"2";--测试空位1
  145. else
  146. state<=wait_btn;--不能旋转,等待操作键
  147. end if;
  148. elsif(forms="01")then
  149. if(p3x>"000" and p3x<"110")then
  150. cx<=p3x-1; cy<=p3y; test<=X"2";
  151. else state<=wait_btn;
  152. end if;
  153. elsif(forms="10")then
  154. if(p3y>"001" and p3y<"111")then
  155. cx<=p3x; cy<=p3y-2; test<=X"2";
  156. else state<=wait_btn;
  157. end if;
  158. elsif(forms="11")then
  159. if(p3x>"001" and p3x<"111")then
  160. cx<=p3x-2; cy<=p3y; test<=X"2";
  161. else state<=wait_btn;
  162. end if;
  163. end if;
  164. when X"2"=>
  165. if(dotin="1")then--高电平点亮,位置已被占
  166. state<=wait_btn;--不能旋转,等待操作键
  167. else
  168. test<=X"3";--有空位,测试下一个位置
  169. end if;
  170. --测试空位2--
  171. when X"3"=>--test
  172. if(forms="00")then
  173. cx<=p3x; cy<=p3y+1; test<=X"4";
  174. elsif(forms="01")then
  175. cx<=p3x+1; cy<=p3y; test<=X"4";
  176. elsif(forms="10")then
  177. cx<=p3x; cy<=p3y-1; test<=X"4";
  178. elsif(forms="11")then
  179. cx<=p3x-1; cy<=p3y; test<=X"4";
  180. end if;
  181. when X"4"=>
  182. if(dotin="1")then state<=wait_btn;
  183. else test<=X"5";
  184. end if;
  185. --测试空位3--
  186. when X"5"=>--test
  187. if(forms="00")then
  188. cx<=p3x; cy<=p3y+2; test<=X"6";
  189. elsif(forms="01")then
  190. cx<=p3x+2; cy<=p3y; test<=X"6";
  191. elsif(forms="10")then
  192. cx<=p3x; cy<=p3y+1; test<=X"6";
  193. elsif(forms="11")then
  194. cx<=p3x+1; cy<=p3y; test<=X"6";
  195. end if;
  196. when X"6"=>
  197. if(dotin="1")then state<=wait_btn;
  198. else test<=X"7";
  199. end if;
  200. --测试阻挡1--
  201. when X"7"=>--test
  202. if(forms="00")then
  203. cx<=p1x; cy<=p1y+1; test<=X"8";
  204. elsif(forms="01")then
  205. cx<=p1x+1; cy<=p1y; test<=X"8";
  206. elsif(forms="10")then
  207. cx<=p1x; cy<=p1y-1; test<=X"8";
  208. elsif(forms="11")then
  209. cx<=p1x-1; cy<=p1y; test<=X"8";
  210. end if;
  211. when X"8"=>
  212. if(dotin="1")then --高电平点亮,有阻挡
  213. state<=wait_btn;--不能旋转,等待操作键
  214. else
  215. test<=X"9";--无阻挡,测试下一个位置
  216. end if;
  217. --测试阻挡2--
  218. when X"9"=>--test
  219. if(forms="00")then
  220. cx<=p2x; cy<=p2y+1; test<=X"A";
  221. elsif(forms="01")then
  222. cx<=p2x+1; cy<=p2y; test<=X"A";
  223. elsif(forms="10")then
  224. cx<=p2x; cy<=p2y-1; test<=X"A";
  225. elsif(forms="11")then
  226. cx<=p2x-1; cy<=p2y; test<=X"A";
  227. end if;
  228. when X"A"=>
  229. if(dotin="1")then
  230. state<=wait_btn;
  231. else
  232. test<=X"B";
  233. end if;
  234. --测试阻挡3--
  235. when X"B"=>--test
  236. if(forms="00")then
  237. cx<=p2x; cy<=p2y+2; test<=X"C";
  238. elsif(forms="01")then
  239. cx<=p2x+2; cy<=p2y; test<=X"C";
  240. elsif(forms="10")then
  241. cx<=p2x; cy<=p2y-2; test<=X"C";
  242. elsif(forms="11")then
  243. cx<=p2x-2; cy<=p2y; test<=X"C";
  244. end if;
  245. when X"C"=>
  246. if(dotin="1")then
  247. state<=wait_btn;
  248. else
  249. test<=X"D";
  250. end if;
  251. --测试阻挡4--
  252. when X"D"=>--test
  253. if(forms="00")then
  254. cx<=p4x; cy<=p4y-1; test<=X"E";
  255. elsif(forms="01")then
  256. cx<=p4x-1; cy<=p4y; test<=X"E";
  257. elsif(forms="10")then
  258. cx<=p4x; cy<=p4y+1; test<=X"E";
  259. elsif(forms="11")then
  260. cx<=p4x+1; cy<=p4y; test<=X"E";
  261. end if;
  262. when X"E"=>
  263. if(dotin="1")then
  264. state<=wait_btn;
  265. else
  266. make<=X"8"; state<=rotate_Lp3;
  267. end if;
  268. when others=>null;
  269. end case;
  270. --I型模块以p3为轴心逆时针旋转--
  271. when rotate_Lp3=>
  272. case make is --make:8~F
  273. --清空原片--
  274. when X"8"=>
  275. wen_tmp<="1";--开写使能
  276. dotout_tmp<="0";--低电平,熄灭led灯
  277. cx<=p1x; cy<=p1y; make<=X"9";
  278. when X"9"=>
  279. cx<=p2x; cy<=p2y; make<=X"A";
  280. when X"A"=>
  281. cx<=p4x; cy<=p4y; make<=X"B";
  282. --更新p1,p2,p4新片位置--
  283. when X"B"=>--make
  284. if(forms="00")then
  285. p1x<=p1x+2; p1y<=p1y+2;
  286. p2x<=p2x+1; p2y<=p2y+1;
  287. p4x<=p4x-1; p4y<=p4y-1;
  288. elsif(forms="01")then
  289. p1x<=p1x+2; p1y<=p1y-2;
  290. p2x<=p2x+1; p2y<=p2y-1;
  291. p4x<=p4x-1; p4y<=p4y+1;
  292. elsif(forms="10")then
  293. p1x<=p1x-2; p1y<=p1y-2;
  294. p2x<=p2x-1; p2y<=p2y-1;
  295. p4x<=p4x+1; p4y<=p4y+1;
  296. elsif(forms="11")then
  297. p1x<=p1x-2; p1y<=p1y+2;
  298. p2x<=p2x-1; p2y<=p2y+1;
  299. p4x<=p4x+1; p4y<=p4y-1;
  300. end if;
  301. make<=X"C";
  302. --显示新片--
  303. when X"C"=>--make
  304. dotout_tmp<="1";--高电平,点亮led灯
  305. cx<=p1x; cy<=p1y; make<=X"D";
  306. when X"D"=>
  307. cx<=p2x; cy<=p2y; make<=X"E";
  308. when X"E"=>
  309. cx<=p4x; cy<=p4y; make<=X"F";
  310. when X"F"=>--make
  311. wen_tmp<="0";--关写使能
  312. --切换I型模块的形状--
  313. if(forms="00")then forms<="01";
  314. elsif(forms="01")then forms<="10";
  315. elsif(forms="10")then forms<="11";
  316. elsif(forms="11")then forms<="00";
  317. end if;
  318. make<=X"0"; state<=wait_btn;
  319. when others=>null;
  320. end case;
  321. end case;
  322. end if;
  323. end if;
  324. end process;
  325. end behavioral;

ctrl_dotcasebitT.vhd:

  1. --库
  2. library ieee;
  3. use ieee.std_logic_1164.all;
  4. use ieee.std_logic_arith.all;
  5. use ieee.std_logic_unsigned.all;
  6. --实体
  7. entity ctrl_dotcasebitT is
  8. port (clk_rama : in std_logic;
  9. rst : in std_logic;
  10. dataa : in std_logic_vector(0 downto 0);
  11. btn_en:in std_logic;
  12. dispgame:in std_logic;
  13. din : out std_logic;
  14. load_cs : out std_logic;
  15. clk_max7219 : out std_logic;
  16. addra : out std_logic_vector(8 downto 0));
  17. end;
  18. --结构体
  19. architecture behavioral of ctrl_dotcasebitT is
  20. type state_group is(load_shiften,SISO_16,clkedgeR_upaddr);
  21. signal state:state_group:=load_shiften;
  22. signal shift_en:std_logic:='0';
  23. signal btnen_tmp:std_logic:='0';
  24. signal addr_init:std_logic:='1';--1控制寄存器,0数据寄存器
  25. signal addr_game:std_logic:='0';--游戏界面/go
  26. signal addr_reg:std_logic_vector(2 downto 0):="000";
  27. signal addr_bit:std_logic_vector(3 downto 0):=X"0"; --16位数据的每一位
  28. begin
  29. addra<=addr_init&addr_game&addr_reg&addr_bit;
  30. process(rst,clk_rama,btn_en,state,dataa)
  31. variable cnt_shift:std_logic_vector(3 downto 0):=X"0";--移位计数
  32. variable cnt_delay:std_logic_vector(2 downto 0):="000";--延时计数
  33. begin
  34. if(rst='1')then
  35. addr_init<='0'; addr_game<='0'; --进入go界面
  36. addr_reg<="000"; addr_bit<=X"0";
  37. btnen_tmp<=btn_en;
  38. shift_en<='0'; load_cs<='1'; clk_max7219<='0';
  39. cnt_shift:=X"0"; cnt_delay:="000";
  40. state<=load_shiften;
  41. elsif rising_edge(clk_rama)then
  42. if(btnen_tmp/=btn_en and dispgame='1')then--切换测试项按钮
  43. btnen_tmp<=not btnen_tmp;
  44. addr_init<='0'; addr_game<='1'; --进入游戏的旋转测试界面
  45. addr_reg<="000"; addr_bit<=X"0";
  46. shift_en<='0'; load_cs<='1'; clk_max7219<='0';
  47. cnt_shift:=X"0"; cnt_delay:="000";
  48. state<=load_shiften;
  49. else
  50. case state is
  51. when load_shiften=>--装载锁存数据/移位使能
  52. clk_max7219<='0';
  53. if(shift_en='1')then
  54. load_cs<='0';--允许移位
  55. state<=SISO_16;
  56. else
  57. load_cs<='1';--装载锁存数据
  58. if(cnt_delay="111")then--延时,间隔各寄存器信息
  59. shift_en<='1'; cnt_delay:="000";
  60. else
  61. cnt_delay:=cnt_delay+1;
  62. end if;
  63. end if;
  64. when SISO_16=>--16位数据串行输入、串行输出
  65. clk_max7219<='0';
  66. din<=dataa(0);
  67. addr_bit<=addr_bit+1;--16位数据中的下一位
  68. state<=clkedgeR_upaddr;
  69. when clkedgeR_upaddr=>--产生时钟上升沿,切换寄存器地址
  70. clk_max7219<='1';--产生时钟clk_max7219上升沿
  71. --MAX7219各寄存器的切换
  72. if(cnt_shift=X"F")then--16位移完
  73. if(addr_init='1')then--MAX7219初始化
  74. if(addr_reg="100")then--初始化只执行一遍
  75. addr_init<='0'; addr_reg<="000";
  76. else
  77. addr_reg<=addr_reg+1;--下一个控制寄存器
  78. end if;
  79. else
  80. addr_reg<=addr_reg+1;--下一个数据寄存器
  81. end if;
  82. shift_en<='0';
  83. cnt_shift:=X"0"; state<=load_shiften;
  84. else
  85. cnt_shift:=cnt_shift+1; state<=SISO_16;
  86. end if;
  87. end case;
  88. end if;
  89. end if;
  90. end process;
  91. end behavioral;

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/442769
推荐阅读
相关标签
  

闽ICP备14008679号