利用verilog语言设计一个带温度检测的24小时计时的时钟,在四位数码管上显示时分秒,显示格式为:时-分-秒(由于只有四位数码管显示位数不够,所以要让时间显示为滚动显示)
要求:
1.利用开发板上的LM75温度传感器,实时显示测量温度值
2.通过按键能够对显示时间进行校正;
module clock (
input clk, // 时钟信号
input rst, // 复位信号
input [3:0] btn, // 按键输入
output reg [3:0] seg [4], // 数码管输出
output reg [7:0] dp, // 数码管小数点
output reg [1:0] an, // 数码管选择信号
output reg [7:0] temp // 温度传感器输出
);
reg [23:0] count = 0; // 计数器
reg [3:0] hour = 0; // 时
reg [3:0] min = 0; // 分
reg [3:0] sec = 0; // 秒
reg [7:0] temp_reg = 0; // 温度值寄存器
wire [7:0] temp_raw; // 温度传感器原始值
// 时钟精度为1秒
always @(posedge clk or posedge rst) begin
if (rst) begin
count <= 0;
hour <= 0;
min <= 0;
sec <= 0;
end else begin
count <= count + 1;
if (count == 24000000) begin
count <= 0;
sec <= sec + 1;
if (sec == 60) begin
sec <= 0;
min <= min + 1;
if (min == 60) begin
min <= 0;
hour <= hour + 1;
if (hour == 24) begin
hour <= 0;
end
end
end
end
end
end
// 数码管滚动显示
always @(*) begin
case (count[23:22])
2'b00: begin
seg[1] = {7'b0000000, seg[0][6:1]};
seg[2] = {7'b0000000, seg[1][6:1]};
seg[3] = {7'b0000000, seg[2][6:1]};
end
2'b01: begin
seg[1] = {7'b0000000, seg[3][6:1]};
seg[2] = {7'b0000000, seg[1][6:1]};
seg[3] = {7'b0000000, seg[2][6:1]};
end
2'b10: begin
seg[1] = {7'b0000000, seg[2][6:1]};
seg[2] = {7'b0000000, seg[3][6:1]};
seg[3] = {7'b0000000, seg[0][6:1]};
end
2'b11: begin
seg[1] = {7'b0000000, seg[1][6:1]};
seg[2] = {7'b0000000, seg[2][6:1]};
seg[3] = {7'b0000000, seg[3][6:1]};
end
endcase
end
// 温度传感器读取
lm75 lm75_inst (
.scl(clk),
.sda(clk),
.addr(8'b1001000),
.temp_raw(temp_raw)
);
// 温度值转换
always @(*) begin
if (temp_raw[15] == 1) begin
temp_reg = {8'b1111111, ~temp_raw[7:0] + 1};
end else begin
temp_reg = temp_raw[7:0];
end
end
// 按键校正
always @(*) begin
if (btn[0] == 1) begin
sec <= 0;
end
if (btn[1] == 1) begin
min <= 0;
sec <= 0;
end
if (btn[2] == 1) begin
hour <= 0;
min <= 0;
sec <= 0;
end
end
// 数码管输出
always @(*) begin
case (an)
2'b00: begin
seg[0] = 4'b0, seg[1] = 4'b0, seg[2] = 4'b0, seg[3] = 4'b0;
dp = 8'b11111111;
end
2'b01: begin
seg[0] = {7'b0000000, hour};
seg[1] = {7'b0000000, min};
seg[2] = {7'b0000000, sec};
seg[3] = 4'b0;
dp = 8'b11111110;
end
2'b10: begin
seg[0] = {7'b0000000, temp_reg / 10};
seg[1] = {7'b0000000, temp_reg % 10};
seg[2] = 8'b00000000;
seg[3] = 8'b00000000;
dp = 8'b11111101;
end
2'b11: begin
seg[0] = {7'b0000000, temp_reg / 100};
seg[1] = {7'b0000000, (temp_reg / 10) % 10};
seg[2] = {7'b0000000, temp_reg % 10};
seg[3] = 8'b00000000;
dp = 8'b11111100;
end
endcase
end
// 数码管选择信号
always @(posedge clk) begin
if (rst) begin
an <= 2'b00;
end else begin
case (an)
2'b00: an <= 2'b01;
2'b01: an <= 2'b10;
2'b10: an <= 2'b11;
2'b11: an <= 2'b01;
endcase
end
end
// 温度传感器输出
always @(posedge clk) begin
if (rst) begin
temp <= 8'b00000000;
end else begin
temp <= temp_reg;
end
end
endmodule
南大这个网站把状态机和键盘放在一起,让我很是不理解,明明两个风马牛不相及的东西,放一起干什么,但是仔细一想,其实是因为这段代码使用了摩尔型有限状态机的思想。
下面摘录一下摩尔型状态机的知识,同样参考南大的数电实验网站。
Moore 型有限状态机的输出信号只与有限状态机的当前状态有关,与输入信号的当前值无关,输入信号的当前值只会影响到状态机的次态,不会影响状态机当前的输出。即Moore 型有限状态机的输出信号是直接由状态寄存器译码得到。 Moore型有限状态机在时钟CLK信号有效后经过一段时间的延迟,输出达到稳定值。即使在这个时钟周期内输入信号发生变化,输出也会在这个完整的时钟周期内保持稳定值而不变。输入对输出的影响要到下一个时钟周期才能反映出来。Moore有限状态机最重要的特点就是将输入与输出信号隔离开来。
观察这段代码,不难发现使用的就是Moore(摩尔)型有限状态机的思想。因为:
看来前面我们对为什么要存储时间序列的疑问解决了。甚好。
回忆斑驳微醉,叹相思未随,几春几秋几段轮回。----《美人画卷》