跳转至

实验练习

说明

  1. 请在本次实验的三个方向中任选一个完成。注意:不同方向的题目得分不会累加。选择多个项目的我们只计入成绩最高的项目;
  2. 你可以查阅任何开源资料完成实验练习,但不能直接抄袭。一经发现,我们将取消所有抄袭参与者本次的实验成绩。情节特别严重的,我们将按照学校的有关规定进行处理;
  3. 部分题目我们提供了代码框架,你需要在框架指定的位置完成代码内容。你也可以自由修改框架代码,但需要根据题目要求完成练习;
  4. 本次实验上板的部分需要在 100MHz 的时钟频率下运行,因此请注意把控自己设计的时序情况;
  5. 如果你使用了我们预料之外的方法完成练习也没有关系,我们将根据思考量与任务量单独确定给分情况。

方向 1:Logisim 应用

Part 1:ALU

本部分满分 12 分。

题目 1-1:Logisim 版本的 ALU(12 分)

在 Lab6 中,我们用 Verilog 实现了一个基础的 ALU。现在,我们将在 Logisim 中搭建一个基础的 ALU 模块。要求如下:

  • ALU 的输入 src0src1 以及输出 res 的位宽为 8。控制信号 sel 的对应规则与 Lab6 中基本相同,但 sel = 12'H800 时为乘法运算,即 res = src0 * src1。计算完成后,将乘法结果的低 8 位作为结果输出。
  • 不允许使用 Plexers、Arithmetic 以及 Memory 目录下的组件。也就是说,你需要自己搭建基础的电路结构,例如选择器、寄存器、全加器等。
  • 各种运算的实现方法与复杂度不限,但应均为组合逻辑(包括乘法运算)。

Image title

Image title

本题的分数组成如下:

  • 正确搭建 8 位加法器:2 分;
  • 正确搭建 8 位减法器:1 分;
  • 正确搭建 8 位比较器(有符号、无符号):2 分;
  • 正确搭建 8 位移位器(左移、逻辑右移、算数右移):3 分;
  • 正确搭建 8 位组合乘法器:3 分;
  • 基于以上的内容正确搭建 8 位 ALU:1 分。

Part 2:汉字点阵显示

本题满分 10 分。

题目 1-2:汉字点阵显示(10 分)

请参考教程,基于 Logisim 中 Input/Output 目录下的 LED Matrix 组件搭建一个基础的汉字循环显示电路。要求显示的字符为「中科大 姓名 综合实验」( 为中文引号,无需显示;姓名需要替换成你的名字)。

除了以上内容,你还需要额外添加一部分扩展功能。本题的评分标准如下:

  • 实现 LED 横向循环显示的效果。要求 LED 显示屏需要以一定的速率向左或向右循环显示指定的字符,同一时刻显示的字符应不少于三个。(4 分)
  • 在横向移动的基础上增加对移动方向的控制功能。你需要设计一个位宽为 1 的输入 lr,当其为高电平时,字符向右循环移动;否则字符向左循环移动。(1 分)
  • 在横向移动的基础上增加暂停功能。你需要设计一个位宽为 1 的输入 pause,当其为高电平时,字符暂停移动(不是复位);否则继续循环移动。(1 分)
  • 在横向移动的基础上增加对移动速度的控制功能。你需要设计一个特定的输入 speed,要求移动范围至少可以在 0.5 倍、1 倍、2 倍、4 倍四个档位上调整。(2 分)
  • 实现 LED 纵向循环显示的效果。要求 LED 显示屏需要以一定的速率向上或向下循环显示指定的字符,同一时刻显示的字符应不少于三个。(2 分)

注意:前四项内容需要在一个 .circ 项目中的一个电路内实现。最后一项可以在 .circ 项目中新建一个电路。你可以自由使用 Logisim 中的任何组件。

提示

往届学长的项目或许能给予你一定的帮助。

方向 2:串口通信与应用

Part 1:串口协议

本部分满分 10 分。

题目 2-1:串口回显(1 分)

请在 Vivado 中创建一个项目,正确添加设计文件和约束文件,并烧写比特流,在 FPGAOL 平台上验证串口回显程序的功能。在正常情况下,在发送窗口输入数据并点击发送,之后会在接收窗口收到同样的内容。

Tips

不用怀疑,题目 2-1 不需要任何其他的操作,主要是为了让大家熟悉串口的操作界面。

题目 2-2:串口发送模块(4 分)

请根据教程的相关内容补充 Send 模块的完整代码。完成后,你需要使用下面的 TOP 模块以及先前的 Segment 模块进行简单的上板测试。

Top.v
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
module Top(
    input                   [ 0 : 0]        clk,
    input                   [ 0 : 0]        btn,

    input                   [ 7 : 0]        sw,

    output                  [ 3 : 0]        seg_data,
    output                  [ 2 : 0]        seg_an,

    output                  [ 0 : 0]        uart_dout
);

wire [ 0 : 0]   rst = sw[7];
wire [ 7 : 0]   dout_data;
wire [ 0 : 0]   dout_vld = btn;
reg  [31 : 0]   output_data;

Send send (
    .clk            (clk), 
    .rst            (rst),
    .dout           (uart_dout),
    .dout_vld       (dout_vld),
    .dout_data      (dout_data)
);

Segment segment (
    .clk            (clk),
    .rst            (rst),
    .output_data    (output_data),
    .output_valid   (8'H03),
    .seg_data       (seg_data),
    .seg_an         (seg_an)
);

always @(posedge clk) begin
    if (rst)
        output_data <= 0;
    else
        output_data <= {25'B0, sw[6:0]};
end

assign dout_data = output_data[7:0];
endmodule

上面提供的 TOP 模块允许我们通过 sw[6:0] 输入数据,按下按钮后将 {25'B0, sw[6:0]} 通过串口发送回来。串口界面显示的数据为 ASCII = {25'B0, sw[6:0]} 的字符。例如:如果开关输入为 sw = 8'H30,则按下按钮后串口界面会显示一个字符 0。为了便于调试,数码管会实时显示当前开关的输入内容,sw[7] 被我们用作复位信号 rst

项目对应的约束文件如下:

## Clock signal
set_property -dict { PACKAGE_PIN E3    IOSTANDARD LVCMOS33 } [get_ports { clk }]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz

## FPGAOL SWITCH
set_property -dict { PACKAGE_PIN D14   IOSTANDARD LVCMOS33 } [get_ports { sw[0] }];
set_property -dict { PACKAGE_PIN F16   IOSTANDARD LVCMOS33 } [get_ports { sw[1] }];
set_property -dict { PACKAGE_PIN G16   IOSTANDARD LVCMOS33 } [get_ports { sw[2] }];
set_property -dict { PACKAGE_PIN H14   IOSTANDARD LVCMOS33 } [get_ports { sw[3] }];
set_property -dict { PACKAGE_PIN E16   IOSTANDARD LVCMOS33 } [get_ports { sw[4] }];
set_property -dict { PACKAGE_PIN F13   IOSTANDARD LVCMOS33 } [get_ports { sw[5] }];
set_property -dict { PACKAGE_PIN G13   IOSTANDARD LVCMOS33 } [get_ports { sw[6] }];
set_property -dict { PACKAGE_PIN H16   IOSTANDARD LVCMOS33 } [get_ports { sw[7] }];


## FPGAOL HEXPLAY
set_property -dict { PACKAGE_PIN A14   IOSTANDARD LVCMOS33 } [get_ports { seg_data[0] }];
set_property -dict { PACKAGE_PIN A13   IOSTANDARD LVCMOS33 } [get_ports { seg_data[1] }];
set_property -dict { PACKAGE_PIN A16   IOSTANDARD LVCMOS33 } [get_ports { seg_data[2] }];
set_property -dict { PACKAGE_PIN A15   IOSTANDARD LVCMOS33 } [get_ports { seg_data[3] }];
set_property -dict { PACKAGE_PIN B17   IOSTANDARD LVCMOS33 } [get_ports { seg_an[0] }];
set_property -dict { PACKAGE_PIN B16   IOSTANDARD LVCMOS33 } [get_ports { seg_an[1] }];
set_property -dict { PACKAGE_PIN A18   IOSTANDARD LVCMOS33 } [get_ports { seg_an[2] }];

## FPGAOL BUTTON & SOFT_CLOCK
set_property -dict { PACKAGE_PIN B18   IOSTANDARD LVCMOS33 } [get_ports { btn }];

##USB-RS232 Interface
set_property -dict { PACKAGE_PIN D4    IOSTANDARD LVCMOS33 } [get_ports { uart_dout }]; #IO_L11N_T1_SRCC_35 Sch=uart_rxd_out

注意

按照上面的方式烧写的比特流在 FPGAOL 上运行时,可能会出现按动一次按钮输出了多个字符的现象。这是因为按钮按下后的 btn 信号持续了较长的一段时间,导致 Send 模块接收了多次相同字符的输出请求。为了解决这个问题,你需要参考 Lab3 的相关教程btn 信号进行取上升沿的处理操作。

提示

为了便于调试,我们提供了如下的示例仿真文件,你可以自行修改以满足调试需要。你可能需要延长仿真的时间以获取更多模块的工作信息。

Send_tb.v
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
module Send_tb();
reg clk, rst, dout_vld;
reg  [7 : 0] dout_data;
wire dout;

initial begin
    rst = 1;
    #10;
    rst = 0;
end

initial begin
    clk = 0;
    forever begin
        #5 clk = ~clk;
    end
end

initial begin
    #50;
    dout_vld = 1'B1;
    dout_data = "0";
    #100;
    dout_data = 0;
    dout_vld = 0;
end

Send send (
    .clk            (clk), 
    .rst            (rst),
    .dout           (dout),
    .dout_vld       (dout_vld),
    .dout_data      (dout_data)
);
endmodule

本题的分数组成如下:

  • 能够正确通过仿真测试:2 分;
  • 能够上板输出正确的字符。你需要在串口界面显示字符本身,在数码管上显示字符对应的 ASCII 码:1 分;
  • 能够正确获取 btn 信号的上升沿:1 分。

题目 2-3:串口接收模块(5 分)

请根据教程的相关内容补充 Receive 模块的完整代码。完成后,你需要使用下面的 TOP 模块以及先前的 Segment 模块进行简单的上板测试。

TOP.v
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
module Top(
    input                   [ 0 : 0]        clk,
    input                   [ 0 : 0]        rst,

    output                  [ 3 : 0]        seg_data,
    output                  [ 2 : 0]        seg_an,

    input                   [ 0 : 0]        uart_din
);

wire [ 7 : 0]   din_data;
wire [ 0 : 0]   din_vld;
reg  [31 : 0]   output_data;

Receive receive (
    .clk        (clk),
    .rst        (rst),
    .din        (uart_din),
    .din_vld    (din_vld),
    .din_data   (din_data)
);

Segment segment (
    .clk            (clk),
    .rst            (rst),
    .output_data    (output_data),
    .output_valid   (8'HFF),
    .seg_data       (seg_data),
    .seg_an         (seg_an)
);

always @(posedge clk) begin
    if (rst)
        output_data <= 32'B0;
    else if (din_vld)
        output_data <= {output_data[23:0], din_data};
end
endmodule

上面的 TOP 模块负责接收来自串口输入的数据,并将其以十六进制整数的形式显示在数码管上。每进行一次输入就将先前的内容左移 8bit。

项目对应的约束文件如下:

## Clock signal
set_property -dict { PACKAGE_PIN E3    IOSTANDARD LVCMOS33 } [get_ports { clk }]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz

## FPGAOL HEXPLAY
set_property -dict { PACKAGE_PIN A14   IOSTANDARD LVCMOS33 } [get_ports { seg_data[0] }];
set_property -dict { PACKAGE_PIN A13   IOSTANDARD LVCMOS33 } [get_ports { seg_data[1] }];
set_property -dict { PACKAGE_PIN A16   IOSTANDARD LVCMOS33 } [get_ports { seg_data[2] }];
set_property -dict { PACKAGE_PIN A15   IOSTANDARD LVCMOS33 } [get_ports { seg_data[3] }];
set_property -dict { PACKAGE_PIN B17   IOSTANDARD LVCMOS33 } [get_ports { seg_an[0] }];
set_property -dict { PACKAGE_PIN B16   IOSTANDARD LVCMOS33 } [get_ports { seg_an[1] }];
set_property -dict { PACKAGE_PIN A18   IOSTANDARD LVCMOS33 } [get_ports { seg_an[2] }];

## FPGAOL BUTTON & SOFT_CLOCK
set_property -dict { PACKAGE_PIN B18   IOSTANDARD LVCMOS33 } [get_ports { rst }];

##USB-RS232 Interface
set_property -dict { PACKAGE_PIN C4    IOSTANDARD LVCMOS33 } [get_ports { uart_din }]; #IO_L7P_T1_AD6P_35 Sch=uart_txd_in
提示

为了便于调试,我们提供了如下的示例仿真文件,你可以自行修改以满足调试需要。你可能需要延长仿真的时间以获取更多模块的工作信息。

Receive_tb.v
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
module Receive_tb();
reg clk, rst, din;
reg  [7 : 0] test_data, temp;
wire [7 : 0] din_data;
wire din_vld;

initial begin
    rst = 1;
    #10;
    rst = 0;
end

initial begin
    clk = 0;
    forever begin
        #5 clk = ~clk;
    end
end

initial begin
    din = 1;
    #20;
    repeat(1) begin
        din = 0;
        #8670;
        test_data = "a";        // 可以更改为其他测试数据
        repeat(8) begin
            temp = test_data & 8'B1;
            din = temp[0];
            test_data = test_data >> 1;
            #8670;
        end
        din = 1;
        #8670;
    end
end

Receive receive (
    .clk        (clk),
    .rst        (rst),
    .din        (din),
    .din_vld    (din_vld),
    .din_data   (din_data)
);
endmodule

本题的分数组成如下:

  • 能够正确通过仿真测试:3 分;
  • 能够正确上板运行,数码管显示串口输入的内容:2 分。

Part 2:应用(二选一)

请在 A、B 两个部分中任选一个部分的练习完成。如果多选则取得分最高的一项计分。

A. 猜数字游戏

本部分满分 16 分。

题目 2-A-1:开关输入(2 分)

请根据据教程内容,实现 SW_Input 模块的相关功能。你可以结合仿真波形验证自己设计的正确性。

题目 2-A-2:结果比对(2 分)

请根据据教程内容,实现 Check 模块的相关功能。你可以结合仿真波形验证自己设计的正确性。

题目 2-A-3:计时器(2 分)

请根据据教程内容,实现 Timer 模块的相关功能。你可以结合仿真波形验证自己设计的正确性。

题目 2-A-4:控制单元(2 分)

请根据据教程内容,自行设计所需的状态并编写 Control 模块对应的代码。你可以结合仿真波形验证自己设计的正确性。

题目 2-A-5:组装(1 分)

请根据教程内容,结合 2-A-1 ~ 2-A-4 的结果,补充下面的 Top 模块,以实现 Basic 版本的猜数字小游戏。

Top
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
module Top (
    input                   [ 0 : 0]            clk,
    input                   [ 0 : 0]            btn,
    input                   [ 7 : 0]            sw,

    output                  [ 7 : 0]            led,
    output                  [ 2 : 0]            seg_an,
    output                  [ 3 : 0]            seg_data
);

wire rst = sw[7];

endmodule

我们为你提供了四选一选择器模块 MUX4 的代码:

MUX4
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
module MUX4 # (
    parameter               WIDTH                   = 32
)(
    input                   [WIDTH-1 : 0]           src0, src1, src2, src3,
    input                   [      1 : 0]           sel,

    output                  [WIDTH-1 : 0]           res
);

assign res = sel[1] ? (sel[0] ? src3 : src2) : (sel[0] ? src1 : src0);
endmodule

本题需要上板运行。你可以使用下面的约束文件:

## Clock signal
set_property -dict { PACKAGE_PIN E3    IOSTANDARD LVCMOS33 } [get_ports { clk }]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz

## FPGAOL LED (signle-digit-SEGPLAY)
set_property -dict { PACKAGE_PIN C17   IOSTANDARD LVCMOS33 } [get_ports { led[0] }];
set_property -dict { PACKAGE_PIN D18   IOSTANDARD LVCMOS33 } [get_ports { led[1] }];
set_property -dict { PACKAGE_PIN E18   IOSTANDARD LVCMOS33 } [get_ports { led[2] }];
set_property -dict { PACKAGE_PIN G17   IOSTANDARD LVCMOS33 } [get_ports { led[3] }];
set_property -dict { PACKAGE_PIN D17   IOSTANDARD LVCMOS33 } [get_ports { led[4] }];
set_property -dict { PACKAGE_PIN E17   IOSTANDARD LVCMOS33 } [get_ports { led[5] }];
set_property -dict { PACKAGE_PIN F18   IOSTANDARD LVCMOS33 } [get_ports { led[6] }];
set_property -dict { PACKAGE_PIN G18   IOSTANDARD LVCMOS33 } [get_ports { led[7] }];


## FPGAOL SWITCH
set_property -dict { PACKAGE_PIN D14   IOSTANDARD LVCMOS33 } [get_ports { sw[0] }];
set_property -dict { PACKAGE_PIN F16   IOSTANDARD LVCMOS33 } [get_ports { sw[1] }];
set_property -dict { PACKAGE_PIN G16   IOSTANDARD LVCMOS33 } [get_ports { sw[2] }];
set_property -dict { PACKAGE_PIN H14   IOSTANDARD LVCMOS33 } [get_ports { sw[3] }];
set_property -dict { PACKAGE_PIN E16   IOSTANDARD LVCMOS33 } [get_ports { sw[4] }];
set_property -dict { PACKAGE_PIN F13   IOSTANDARD LVCMOS33 } [get_ports { sw[5] }];
set_property -dict { PACKAGE_PIN G13   IOSTANDARD LVCMOS33 } [get_ports { sw[6] }];
set_property -dict { PACKAGE_PIN H16   IOSTANDARD LVCMOS33 } [get_ports { sw[7] }];


## FPGAOL HEXPLAY
set_property -dict { PACKAGE_PIN A14   IOSTANDARD LVCMOS33 } [get_ports { seg_data[0] }];
set_property -dict { PACKAGE_PIN A13   IOSTANDARD LVCMOS33 } [get_ports { seg_data[1] }];
set_property -dict { PACKAGE_PIN A16   IOSTANDARD LVCMOS33 } [get_ports { seg_data[2] }];
set_property -dict { PACKAGE_PIN A15   IOSTANDARD LVCMOS33 } [get_ports { seg_data[3] }];
set_property -dict { PACKAGE_PIN B17   IOSTANDARD LVCMOS33 } [get_ports { seg_an[0] }];
set_property -dict { PACKAGE_PIN B16   IOSTANDARD LVCMOS33 } [get_ports { seg_an[1] }];
set_property -dict { PACKAGE_PIN A18   IOSTANDARD LVCMOS33 } [get_ports { seg_an[2] }];

## FPGAOL BUTTON & SOFT_CLOCK
set_property -dict { PACKAGE_PIN B18   IOSTANDARD LVCMOS33 } [get_ports { btn }];
提示

目前,数码管显示的倒计时是十六进制的数据,这是正常的。

题目 2-A-6:更高级的猜数字游戏(7 分)

请在题目 2-A-5 的基础上,参考教程内容,为猜数字游戏添加如下的功能:

  • 倒计时闪烁(1 分)
  • 随机生成题目(1 分)
  • BCD 码显示(2 分)
  • 串口命令(3 分)

以上四个功能的具体得分由助教根据工作量和实现情况确定。

注意:

  1. 你需要在一个项目里实现这些功能。我们不接受拆分成多个项目分别实现功能的做法;
  2. 本题需要上板运行。为了保证公平性,本题助教会要求现场烧写比特流并讲解关键代码。

B. LC-3 处理器

本部分满分 16 分。

2-B-1:LC-3 处理器:基础版(10 分)

请根据 ICS 教材以及所学知识,设计并搭建支持如下指令的 LC-3 处理器:

parameter INST_ADD  = 4'b0001;
parameter INST_AND  = 4'b0101;
parameter INST_BR   = 4'b0000;
parameter INST_JMP  = 4'b1100;
parameter INST_JSR  = 4'b0100;
parameter INST_LD   = 4'b0010;
parameter INST_LDR  = 4'b0110;
parameter INST_LEA  = 4'b1110;
parameter INST_NOT  = 4'b1001;
parameter INST_ST   = 4'b0011;
parameter INST_STR  = 4'b0111;

你需要支持以上指令的功能执行。关于中断与异常处理、轮询等操作均不要求实现。

在开发板上,你的处理器需要支持如下的外设操作:

  • 开关复位:sw[7] 为系统 rst 信号。为高电平时,系统内所有寄存器均复位到 0。
  • 按钮控制:按下按钮后,处理器从 IF 状态开始执行一条指令的完整流程,最后回到 IF 状态。你需要对按钮信号进行取上升沿的处理操作。
  • 数码管显示:数码管的高四位通过 sw[3:0] 显示对应寄存器中的数值。映射关系为:
    sw[3:0]             output_data[31:16]
    0000                R0
    0001                R1
    0010                R2
    0011                R3
    0100                R4
    0101                R5
    0110                R6
    0111                R7
    1000                PC
    1001                IR
    1010                条件码寄存器
    

你需要完成的内容包括:

  • 使用存储器 IP 核作为内存,并将 LC3-Tools 生成的机器码作为 COE 文件导入存储器。开始运行后,你的通路应当可以在不受外界干预的情况下正确执行存储器中的指令。
  • 设计基于开关和数码管的数码管显示功能。
  • 一段可以验证自己设计正确性的示例程序。由于我们目前无法在开发板上访问内存,因此请将最终的结果保存在寄存器中。

本题的分数组成如下:

  • 能够设计合理的数据通路与状态机:4 分;
  • 正确设计存储器与寄存器堆的结构:3 分;
  • 上板通过自定义的示例程序:3 分。
提示

由于我们精简了需要支持的指令,因此你可以同样精简状态机,而不是需要全部的几十个状态。例如,将指令执行的 6 个阶段分别作为一个状态,从而得到一个只有 6 个状态的状态机。

2-B-2:串口控制的处理器(6 分)

请根据文档中的内容,在 2-B-1 的基础上支持基于串口的命令控制。你需要实现的内容包括:

  • 串口命令控制。为此你需要增加对于串口命令的解析单元,并正确连接到存储器、控制器等单元;
  • 让七段数码管的低四位显示 r 指令读取的结果;
  • 一段可以验证自己设计正确性的示例程序,并使用串口命令进行写入、运行、读取的操作。

本题的分数组成如下:

  • 能够设计合理的数据通路与状态机,以实现串口命令的正确解析:4 分;
  • 上板通过自定义的示例程序:2 分。

方向 3:VGA 显示与应用

Part 1:VGA 协议

题目 3-1:如果我不曾见过光明(4 分)

请根据教程的相关内容补全 DST 模块的完整代码,并在 Vivado 中创建一个项目,正确添加设计文件和约束文件,烧写 bit 流。你应当能够让 VGA 屏幕显示为白色。

相关的约束文件部分参考如下:

## Clock signal
set_property -dict { PACKAGE_PIN E3    IOSTANDARD LVCMOS33 } [get_ports { clk }]; #IO_L12P_T1_MRCC_35 Sch=clk100mhz
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {clk}];

##Buttons
set_property -dict { PACKAGE_PIN C12   IOSTANDARD LVCMOS33 } [get_ports { rstn }]; #IO_L3P_T0_DQS_AD1P_15 Sch=cpu_resetn

##VGA Connector
set_property -dict { PACKAGE_PIN B11   IOSTANDARD LVCMOS33 } [get_ports { hs }]; #IO_L4P_T0_15 Sch=vga_hs
set_property -dict { PACKAGE_PIN B12   IOSTANDARD LVCMOS33 } [get_ports { vs }]; #IO_L3N_T0_DQS_AD1N_15 

提示

与 FPGAOL 不同,实际开发板的复位键是低电平有效的,故写作 rstn。

此外,实际开发板的约束文件接口与 FPGAOL 上的有较大差别,请使用 Nexys4DDR_Master.xdc 作为约束文件。

题目 3-2:让世界热闹起来!(4 分)

请根据教程的相关内容构建一个完整的 VGA 显示模块,并使用提供的脚本生成任意一张你喜欢的图片的 coe 文件,装载进 VRAM 中,并在显示屏上正确地显示出来。

相关的约束文件部分参考如下:

##VGA Connector
set_property -dict { PACKAGE_PIN A3    IOSTANDARD LVCMOS33 } [get_ports { red[0] }]; #IO_L8N_T1_AD14N_35 Sch=vga_r[0]
set_property -dict { PACKAGE_PIN B4    IOSTANDARD LVCMOS33 } [get_ports { red[1] }]; #IO_L7N_T1_AD6N_35 Sch=vga_r[1]
set_property -dict { PACKAGE_PIN C5    IOSTANDARD LVCMOS33 } [get_ports { red[2] }]; #IO_L1N_T0_AD4N_35 Sch=vga_r[2]
set_property -dict { PACKAGE_PIN A4    IOSTANDARD LVCMOS33 } [get_ports { red[3] }]; #IO_L8P_T1_AD14P_35 Sch=vga_r[3]

set_property -dict { PACKAGE_PIN C6    IOSTANDARD LVCMOS33 } [get_ports { green[0] }]; #IO_L1P_T0_AD4P_35 Sch=vga_g[0]
set_property -dict { PACKAGE_PIN A5    IOSTANDARD LVCMOS33 } [get_ports { green[1] }]; #IO_L3N_T0_DQS_AD5N_35 Sch=vga_g[1]
set_property -dict { PACKAGE_PIN B6    IOSTANDARD LVCMOS33 } [get_ports { green[2] }]; #IO_L2N_T0_AD12N_35 Sch=vga_g[2]
set_property -dict { PACKAGE_PIN A6    IOSTANDARD LVCMOS33 } [get_ports { green[3] }]; #IO_L3P_T0_DQS_AD5P_35 Sch=vga_g[3]

set_property -dict { PACKAGE_PIN B7    IOSTANDARD LVCMOS33 } [get_ports { blue[0] }]; #IO_L2P_T0_AD12P_35 Sch=vga_b[0]
set_property -dict { PACKAGE_PIN C7    IOSTANDARD LVCMOS33 } [get_ports { blue[1] }]; #IO_L4N_T0_35 Sch=vga_b[1]
set_property -dict { PACKAGE_PIN D7    IOSTANDARD LVCMOS33 } [get_ports { blue[2] }]; #IO_L6N_T0_VREF_35 Sch=vga_b[2]
set_property -dict { PACKAGE_PIN D8    IOSTANDARD LVCMOS33 } [get_ports { blue[3] }]; #IO_L4P_T0_35 Sch=vga_b[3]

题目 3-3:比 bilibili 何如?(4 分)

请利用你的 VGA 显示模块,播放一段你喜欢的视频(不要求同时播放音乐)。你可以通过图片轮播的方式来实现。

Part 2:应用(二选一)

请在 A、B 两个部分中任选一个部分的练习完成。如果多选则取得分最高的一项计分。

A. 绘图板

本部分满分 14 分。请在 3-A 系列的题目中任选其中的六题完成,如果多选则取得分最高的六题累加计分,不超过14分。

题目 3-A-1:笔尖即世界(5 分)

请根据教程的相关内容,实现一个简单的绘图板。要求实现以下功能:

  • 可使用开关 sw[11:0] 选择画笔颜色(2 分);
  • 可使用开关 sw[15] 控制是否绘制(2 分);
  • 可使用 btnu, btnl, btnr, btnd 四个按钮控制上下左右移动(1 分)。

对应的约束文件如下:

##Buttons

set_property -dict { PACKAGE_PIN M18   IOSTANDARD LVCMOS33 } [get_ports { up }]; #IO_L4N_T0_D05_14 Sch=btnu
set_property -dict { PACKAGE_PIN P17   IOSTANDARD LVCMOS33 } [get_ports { left }]; #IO_L12P_T1_MRCC_14 Sch=btnl
set_property -dict { PACKAGE_PIN M17   IOSTANDARD LVCMOS33 } [get_ports { right }]; #IO_L10N_T1_D15_14 Sch=btnr
set_property -dict { PACKAGE_PIN P18   IOSTANDARD LVCMOS33 } [get_ports { down }]; #IO_L9N_T1_DQS_D13_14 Sch=btnd

##Switches

set_property -dict { PACKAGE_PIN J15   IOSTANDARD LVCMOS33 } [get_ports { pred[0] }]; #IO_L24N_T3_RS0_15 Sch=sw[0]
set_property -dict { PACKAGE_PIN L16   IOSTANDARD LVCMOS33 } [get_ports { pred[1] }]; #IO_L3N_T0_DQS_EMCCLK_14 Sch=sw[1]
set_property -dict { PACKAGE_PIN M13   IOSTANDARD LVCMOS33 } [get_ports { pred[2] }]; #IO_L6N_T0_D08_VREF_14 Sch=sw[2]
set_property -dict { PACKAGE_PIN R15   IOSTANDARD LVCMOS33 } [get_ports { pred[3] }]; #IO_L13N_T2_MRCC_14 Sch=sw[3]
set_property -dict { PACKAGE_PIN R17   IOSTANDARD LVCMOS33 } [get_ports { pgreen[0] }]; #IO_L12N_T1_MRCC_14 Sch=sw[4]
set_property -dict { PACKAGE_PIN T18   IOSTANDARD LVCMOS33 } [get_ports { pgreen[1] }]; #IO_L7N_T1_D10_14 Sch=sw[5]
set_property -dict { PACKAGE_PIN U18   IOSTANDARD LVCMOS33 } [get_ports { pgreen[2] }]; #IO_L17N_T2_A13_D29_14 Sch=sw[6]
set_property -dict { PACKAGE_PIN R13   IOSTANDARD LVCMOS33 } [get_ports { pgreen[3] }]; #IO_L5N_T0_D07_14 Sch=sw[7]
set_property -dict { PACKAGE_PIN T8    IOSTANDARD LVCMOS18 } [get_ports { pblue[0] }]; #IO_L24N_T3_34 Sch=sw[8]
set_property -dict { PACKAGE_PIN U8    IOSTANDARD LVCMOS18 } [get_ports { pblue[1] }]; #IO_25_34 Sch=sw[9]
set_property -dict { PACKAGE_PIN R16   IOSTANDARD LVCMOS33 } [get_ports { pblue[2] }]; #IO_L15P_T2_DQS_RDWR_B_14 Sch=sw[10]
set_property -dict { PACKAGE_PIN T13   IOSTANDARD LVCMOS33 } [get_ports { pblue[3] }]; #IO_L23P_T3_A03_D19_14 Sch=sw[11]

set_property -dict { PACKAGE_PIN V10   IOSTANDARD LVCMOS33 } [get_ports { draw }]; #IO_L21P_T3_DQS_14 Sch=sw[15]

题目 3-A-2:一键清除(1 分)

请你为你的绘图板添加以下功能:

按下 rstn 复位键,清除绘画内容。(注意,不要清除你的绘图板背景)

题目 3-A-3:笔一直画(1 分)

请你为你的绘图板添加以下功能:

按下移动按键,画笔能够连续移动。

题目 3-A-4:你这斜线不连续呀(1 分)

请你为你的绘图板添加以下功能:

同时按下两个方向键,如 ← 和 ↑,画笔能够 45° 斜向移动。

题目 3-A-5:嘿,我在这儿(2 分)

请你为你的绘图板添加以下功能:

显示十字光标,指示画笔当前位置。

题目 3-A-6:方方正正(2 分)

请你为你的绘图板添加以下功能:

添加长方形绘制状态,先后在两个位置按下 btnc 键后,以此两点为基准点绘制长方形。

题目 3-A-7:我撤回了一个像素(2 分)

请你为你的绘图板添加以下功能:

按下 btnc 按钮,撤回上一次绘画的像素。

题目 3-A-8:洪水泛滥(3 分)

请你为你的绘图板添加以下功能:

添加填色状态,按下 btnc 按钮后,填充当前位置所在的区域。

B. 游戏设计

本部分满分 18 分。

题目 3-B-1:比 LC-3 更困难的(18 分)

请结合你一学期所学到的知识,自由地开发一款基于 FPGA 的游戏。题材不限,内容不限,你可以根据需要和能力额外使用其他外设如键盘、音响等。

完成本题的同学不需要再检查 VGA 方向的必做题部分。

本题需要现场答辩。助教们会根据你的任务量进行公正合理的评分。

祝你能够顺利完成你的项目,也祝你有一个难忘的开发经历!


最后更新: December 24, 2023

评论