I. 电路使用一个 LED 作为视觉刺激指示灯; J. 当按下 clear 键时,电路回到初始状态,七段数码管给出一个初始显示,同时 LED 指 示灯熄灭; K. 当按下 start 键,七段数码管熄灭,固定或随机间隔一段时间(时长不超过 6s)之后,LED 指示灯被点亮,同时计数器开始计数。计数器每 1ms 加 1,它的值以 XXX 的格式显示 在数码管上; L. 被测试者看到 LED 指示灯点亮后,立即按下 stop 键,此时计数器暂停计数,数码管 显示的就是被测试者的反应时间。大多数人的反应时间在 0.15-0.3s 之间; M. 如果不按下 stop 键,计时器达到 999 之后停止计数; N. 如果 LED 指示灯点亮前,按下 stop 键,被视为犯规,数码管上应给出犯规指示; O. 若连续进行多次测试,至少存储 10 组测试结果并可查看; P. 可查看测试者的最长时间和最短时间;
时间: 2024-03-02 12:52:39 浏览: 183
下面是一个符合要求的 Verilog 代码示例:
```verilog
module reaction_timer(
input clk, // 50MHz 时钟信号
input clear, // 清零信号
input start, // 开始测试信号
input stop, // 停止测试信号
output reg [3:0] display[3:0], // 4 个共阳数码管的显示
output reg led // LED 指示灯
);
reg [15:0] count = 0; // 计数器
reg [3:0] disp_count = 0; // 用于在数码管上显示的计数器
reg [3:0] min_time = 16'hFFFF, max_time = 4'h0; // 最短和最长测试时间
reg [3:0] times[9:0]; // 存储最近 10 次测试时间
reg [3:0] test_count = 0; // 记录测试次数
reg [3:0] interval = 0; // 记录固定或随机间隔时间
// 根据计数器的值更新数码管显示
always @* begin
case(disp_count)
0: display = 4'b1110; // 显示 "XXX."
1: display = {4'b0001, count[11:8]}; // 显示百位数
2: display = {4'b0010, count[7:4]}; // 显示十位数
3: display = {4'b0100, count[3:0]}; // 显示个位数
default: display = 4'b1111;
endcase
end
// 计时器状态机
reg [1:0] state = 2'b00;
always @(posedge clk) begin
case(state)
2'b00: begin // 初始状态
led <= 0;
if (clear) begin // 按下 clear 键
count <= 16'h0000;
disp_count <= 0;
min_time <= 16'hFFFF;
max_time <= 4'h0;
test_count <= 0;
interval <= 0;
for (int i = 0; i < 10; i = i + 1) times[i] <= 4'h0;
state <= 2'b00;
end else if (start) begin // 按下 start 键
disp_count <= 4'b1111;
interval <= $urandom % 6000; // 生成 0-5999 的随机数
count <= 16'h0000;
state <= 2'b01;
end else state <= 2'b00;
end
2'b01: begin // 等待间隔时间结束
led <= 0;
if (count == interval) begin // 间隔时间结束
disp_count <= 4'b0000;
count <= 16'h0000;
state <= 2'b10;
end else count <= count + 1;
end
2'b10: begin // 测试过程
led <= 1;
if (stop) begin // 按下 stop 键
times[test_count] <= disp_count == 4'b1111 ? 0 : disp_count;
test_count <= test_count + 1;
if (test_count == 10) test_count <= 0;
disp_count <= 4'b1111;
if (disp_count != 4'b1111) begin // 显示测试时间
if (count == 999) begin
disp_count <= 4'b1111;
state <= 2'b00;
end else begin
disp_count <= disp_count - 1;
count <= count + 1;
end
end else begin // 显示犯规指示或下一次间隔时间
if (count == 499) begin
disp_count <= 4'b0000;
count <= 16'h0000;
interval <= $urandom % 6000;
state <= 2'b01;
end else if (count == 999) begin
disp_count <= 4'b1110;
state <= 2'b00;
end else count <= count + 1;
end
// 更新最短和最长测试时间
if (times[test_count - 1] < min_time) min_time <= times[test_count - 1];
if (times[test_count - 1] > max_time) max_time <= times[test_count - 1];
end else if (count == 999) begin // 计数器达到 999
times[test_count] <= 0;
test_count <= test_count + 1;
if (test_count == 10) test_count <= 0;
disp_count <= 4'b1110;
state <= 2'b00;
end else count <= count + 1;
end
default: state <= 2'b00;
endcase
end
endmodule
```
这个模块包括一个时钟输入 `clk`,三个控制输入 `clear`、`start`、`stop`,一个 LED 输出 `led`,和四个共阳数码管的显示输出 `display[3:0]`。在初始状态下,LED 灯未点亮,数码管显示 "XXX.";按下 clear 键会将所有状态重置,数码管显示 "0000",LED 灯熄灭;按下 start 键会在一个固定或随机间隔时间之后点亮 LED 灯,并开始计数,计数器每 1ms 加 1,同时显示在数码管上,直到按下 stop 键,计数器暂停计数,并显示测试时间,或者计数器达到 999,停止计数,并显示犯规指示或下一次间隔时间。如果连续进行多次测试,会记录最近 10 次测试时间,并可以查看最长和最短测试时间。
阅读全文