上次计数器里说到利用PYNQ-Z2的开发板上Arm核与上位机实现串口通信将4位计数器的结果实时回传到上位机的串口界面中还没做好捏,插播一个小破时钟吧。
首先呢我这只用了一个十进制同步置位异步复位的计数芯片74160哈,然后时钟的话最基本的当然就是小时的24进制和分钟秒钟的60进制啦,所以就是利用74160整24进制和60进制的电路然后给它接一起(进位信号啥的做对输入)然后基本的电子钟功能就实现啦。
做完了基本功能后想到以前小时候家里的时候整点都会响一声嘛,一般好像是正午和晚上的十二点,不过我写的Verilog是在每一个整点都会有一个Remind信号,大概改一下就可以实现正午和晚上啦。然后emmm还拓展了一个闹钟的功能,可以在设定的时间有一个RES信号出现,在上板子后接个蜂鸣之类的就可以作为闹钟了。不过有个问题呢就是这个时钟只能从00:00开始,没加入人为设置时间的功能、或者说可以联网同步世界时钟就更好了!感兴趣的小伙伴可以试试看捏。
/*
Description: Digital Clock
Author: jc, luo
*/
先写一个基本的74160芯片吧。
`timescale 1ns / 1ps
module Counter74160(
input clk,
input CR_n,
input LD_n,
input EP,ET,
input D,C,B,A,
output reg RCO = 1'b0,
output [3:0]Q
);
reg [3:0]data_in;
assign Q = data_in;
always@ (negedge clk or negedge CR_n)
begin
if(~CR_n)
begin
data_in <=4'b0;
RCO <=1'b0;
end
else if( ~LD_n )
data_in <= { D, C, B, A };
else if( ~EP | ~ET )
data_in <= data_in;
else
begin
data_in <= (data_in < 4'b1001) ? data_in + 1'b1 : 4'b0;
RCO <= (data_in < 4'b1001) ? 1'b0 : 1'b1;
end
end
endmodule
然后的话利用一下时序电路的知识利用置数法设计60进制、整体置数法设计24进制(复位清零法也可用,不过要注意毛刺信号一般忽略不计,为此计数过程中需要注意到n还是n+1)
// 60 进制
`timescale 1ns / 1ps
module Counter_60bit(
CLK,
RST,
C_Second,
Q_1,
Q_2
);
input wire CLK;
input wire RST;
output wire C_Second;
output wire [3:0] Q_1;
output wire [3:0] Q_2;
wire SYNTHESIZED_WIRE_21;
wire SYNTHESIZED_WIRE_22;
wire SYNTHESIZED_WIRE_23;
wire SYNTHESIZED_WIRE_8;
wire SYNTHESIZED_WIRE_24;
wire SYNTHESIZED_WIRE_17;
wire SYNTHESIZED_WIRE_19;
wire SYNTHESIZED_WIRE_20;
assign SYNTHESIZED_WIRE_20 = Q_2[0];
assign SYNTHESIZED_WIRE_19 = Q_2[2];
assign SYNTHESIZED_WIRE_21 = 1;
assign SYNTHESIZED_WIRE_22 = 0;
Counter74160 b2v_inst(
.clk(CLK),
.ET(SYNTHESIZED_WIRE_21),
.A(SYNTHESIZED_WIRE_22),
.B(SYNTHESIZED_WIRE_22),
.C(SYNTHESIZED_WIRE_22),
.D(SYNTHESIZED_WIRE_22),
.LD_n(SYNTHESIZED_WIRE_21),
.EP(SYNTHESIZED_WIRE_21),
.CR_n(SYNTHESIZED_WIRE_23),
.Q(Q_1),
.RCO(SYNTHESIZED_WIRE_17)
);
Counter74160 b2v_inst1(
.clk(SYNTHESIZED_WIRE_8),
.ET(SYNTHESIZED_WIRE_21),
.A(SYNTHESIZED_WIRE_22),
.B(SYNTHESIZED_WIRE_22),
.C(SYNTHESIZED_WIRE_22),
.D(SYNTHESIZED_WIRE_22),
.LD_n(SYNTHESIZED_WIRE_24),
.EP(SYNTHESIZED_WIRE_21),
.CR_n(SYNTHESIZED_WIRE_23),
.Q(Q_2)
);
assign SYNTHESIZED_WIRE_23 = ~RST;
assign SYNTHESIZED_WIRE_8 = ~SYNTHESIZED_WIRE_17;
assign C_Second = ~SYNTHESIZED_WIRE_24;
assign SYNTHESIZED_WIRE_24 = ~(SYNTHESIZED_WIRE_19 & SYNTHESIZED_WIRE_20);
endmodule
// 24进制
`timescale 1ns / 1ps
module Counter_24bit(
C_Minute,
RST,
Q_1,
Q_2,
);
input wire C_Minute;
input wire RST;
output wire [3:0] Q_1;
output wire [3:0] Q_2;
wire SYNTHESIZED_WIRE_20;
wire SYNTHESIZED_WIRE_21;
wire SYNTHESIZED_WIRE_22;
wire SYNTHESIZED_WIRE_23;
wire SYNTHESIZED_WIRE_24;
wire SYNTHESIZED_WIRE_16;
wire SYNTHESIZED_WIRE_17;
wire SYNTHESIZED_WIRE_18;
assign SYNTHESIZED_WIRE_18 = Q_2[1];
assign SYNTHESIZED_WIRE_16 = Q_1[0];
assign SYNTHESIZED_WIRE_17 = Q_1[1];
assign SYNTHESIZED_WIRE_20 = 1;
assign SYNTHESIZED_WIRE_21 = 0;
Counter74160 b2v_inst(
.clk(C_Minute),
.ET(SYNTHESIZED_WIRE_20),
.A(SYNTHESIZED_WIRE_21),
.B(SYNTHESIZED_WIRE_21),
.C(SYNTHESIZED_WIRE_21),
.D(SYNTHESIZED_WIRE_21),
.LD_n(SYNTHESIZED_WIRE_22),
.EP(SYNTHESIZED_WIRE_20),
.CR_n(SYNTHESIZED_WIRE_23),
.Q(Q_1),
.RCO(SYNTHESIZED_WIRE_24)
);
Counter74160 b2v_inst1(
.clk(C_Minute),
.ET(SYNTHESIZED_WIRE_24),
.A(SYNTHESIZED_WIRE_21),
.B(SYNTHESIZED_WIRE_21),
.C(SYNTHESIZED_WIRE_21),
.D(SYNTHESIZED_WIRE_21),
.LD_n(SYNTHESIZED_WIRE_22),
.EP(SYNTHESIZED_WIRE_24),
.CR_n(SYNTHESIZED_WIRE_23),
.Q(Q_2)
);
assign SYNTHESIZED_WIRE_23 = ~RST;
assign SYNTHESIZED_WIRE_22 = ~(SYNTHESIZED_WIRE_16 & SYNTHESIZED_WIRE_17 & SYNTHESIZED_WIRE_18);
endmodule
然后的话闹钟的实现我是考虑把设定时间与流动的实际时间做一个比对,只要二者一致即表明到了设定的闹钟时间,为此考虑用同或逻辑实现(考虑到一般闹钟只精确到时位和分位这里做的也只有时位和分位)
`timescale 1ns / 1ps
module Judge(
P,
Q,
RES
);
input wire [7:0] P;
input wire [7:0] Q;
output wire RES;
assign RES = (
(P[0]~^Q[0]) &
(P[1]~^Q[1]) &
(P[2]~^Q[2]) &
(P[3]~^Q[3]) &
(P[4]~^Q[4]) &
(P[5]~^Q[5]) &
(P[6]~^Q[6]) &
(P[7]~^Q[7])
);
endmodule
最后就是顶层数字电子钟调用上述几个模块整合成一个真正能用的电子钟了
`timescale 1ns / 1ps
module Digital_Clock(
CLK,
RST,
P,
Q_sec,
Q_min,
Q_hour,
Remind,
RES
);
input wire [15:0] P;
input wire CLK;
input wire RST;
output wire [7:0] Q_sec;
output wire [7:0] Q_min;
output wire [7:0] Q_hour;
output wire Remind;
output wire RES;
wire SYNTHESIZED_WIRE_18;
wire SYNTHESIZED_WIRE_19;
wire SYNTHESIZED_WIRE_20;
wire SYNTHESIZED_WIRE_21;
assign Remind = SYNTHESIZED_WIRE_21;
Counter_24bit b2v_inst(
.RST(RST),
.C_Minute(SYNTHESIZED_WIRE_21),
.Q_1(Q_hour[3:0]),
.Q_2(Q_hour[7:4])
);
Counter_60bit b2v_inst2(
.RST(RST),
.CLK(SYNTHESIZED_WIRE_20),
.Q_1(Q_min[3:0]),
.Q_2(Q_min[7:4]),
.C_Second(SYNTHESIZED_WIRE_21)
);
Judge b2v_inst28(
.P(P[7:0]),
.Q(Q_min),
.RES(SYNTHESIZED_WIRE_18)
);
Judge b2v_inst29(
.P(P[15:8]),
.Q(Q_hour),
.RES(SYNTHESIZED_WIRE_19)
);
Counter_60bit b2v_inst3(
.RST(RST),
.CLK(CLK),
.Q_1(Q_sec[3:0]),
.Q_2(Q_sec[7:4]),
.C_Second(SYNTHESIZED_WIRE_20)
);
assign RES = SYNTHESIZED_WIRE_18 & SYNTHESIZED_WIRE_19;
endmodule
很想吐槽优快云没有Verilog的代码显示捏,看着好单调好难受,emmm。
tb(测试代码)有需要的话踢一下我,量不少就不放上来了,看看几个模块的测试结果就好。
74160十进制计数器(0-9)
60进制计数器(0-59)
24进制计数器(0-23)
判断期望与实际是否一致(闹钟逻辑)
END