|
/*********************************************************/
// 모듈:시계
// 파일이름:시계
// 버젼 : 1.0
// 날짜 : 2024.11.01
// 저자 : 탁 형옥
// 코딩 언어 : verilog
// 문제 내용 (해결해야 할 목표):
시계의 클럭 주파수가 정확히 100MHz가 들어 올때에 정확히 1일을 알리는 주기 신호 발생을 확인한다.
OSC 의 주파수가 부정확 할 때에 보정하는 방법을 확인한다.
// 요구되는 언어 기술 (어려운 점):
// 목표와 기술을 도달하기 위한 알아야 할 기술(문법), 어려운 점, 문제점 극복 과정:
// 결과 도출: 해냈어요.
// 기본 목표 과제를 한층 더 깊이 있게 하기 위한 생각:
// 이용 가능한 분야: 시계가 들어가는 응용제품, 컴퓨터,스마트폰,전자렌지,라디오,TV,등의 가전및 장비용 시계 및 타이밍 컨트롤러
// 기술과 트렌드:
// 설명 :
//
/*********************************************************/
`timescale 1ns/10ps
module SyncCnt4
#(parameter N=32)
(
(* IOB = "TRUE" *) input clki,rst_n,en,
(* IOB = "TRUE" *) input ld,
(* IOB = "TRUE" *) input sel,
(* IOB = "TRUE" *) input [47:0] start_t,
(* IOB = "TRUE" *) input [19:0] tick_10ms,
(* IOB = "TRUE" *) input [27:0] day_t,
(* IOB = "TRUE" *) output reg [19:0] q,
(* IOB = "TRUE" *) output reg [47:20] qm,
(* IOB = "TRUE" *) output wire co,
(* IOB = "TRUE" *) output reg tick_10ms_co,
(* IOB = "TRUE" *) output reg day_co
);
clk_wiz_0 U0 (.clk_out1(clk),.clk_out2(),.clk_out3(),.reset(1'b0),.locked(),.clk_in1(clki));
//wire co1,co3,co4;
reg co_r,co2_r; // co3_r,co4_r;
(* dont_touch="yes" *) wire [47:0] qo;
wire [29:0] qw;
(* dont_touch="yes" *) wire o0,o1,o2,o3,o4,o5,o6,o7,o8,o9,o10,o11,o12,o13;
reg tick_10ms_co;
LUT5 #(.INIT(32'h8000_0000)) G0 (.O(o0),.I0(qo[0]),.I1(qo[1]),.I2(qo[2]),.I3(qo[3]),.I4(qo[4]));
LUT5 #(.INIT(32'h8000_0000)) G1 (.O(o1),.I0(qo[5]),.I1(qo[6]),.I2(qo[7]),.I3(qo[8]),.I4(qo[9]));
LUT5 #(.INIT(32'h8000_0000)) G2 (.O(o2),.I0(qo[10]),.I1(qo[11]),.I2(qo[12]),.I3(qo[13]),.I4(qo[14]));
LUT5 #(.INIT(32'h8000_0000)) G3 (.O(o3),.I0(qo[15]),.I1(qo[16]),.I2(qo[17]),.I3(qo[18]),.I4(qo[19]));
LUT5 #(.INIT(32'h8000_0000)) G4 (.O(o4),.I0(qo[20]),.I1(qo[21]),.I2(qo[22]),.I3(qo[23]),.I4(qo[24]));
LUT5 #(.INIT(32'h8000_0000)) G5 (.O(o5),.I0(qo[25]),.I1(qo[26]),.I2(qo[27]),.I3(qo[28]),.I4(qo[29]));
LUT5 #(.INIT(32'h8000_0000)) G7(.O(o7),.I0(qo[30]),.I1(qo[31]),.I2(qo[32]),.I3(qo[33]),.I4(qo[34]));
LUT5 #(.INIT(32'h8000_0000)) G8(.O(o8),.I0(qo[35]),.I1(qo[36]),.I2(qo[37]),.I3(qo[38]),.I4(qo[39]));
LUT5 #(.INIT(32'h8000_0000)) G9(.O(o9),.I0(qo[40]),.I1(qo[41]),.I2(qo[42]),.I3(qo[43]),.I4(qo[44]));
LUT3 #(.INIT(8'b1000_0000)) G10(.O(o10),.I0(qo[45]),.I1(qo[46]),.I2(qo[47]));
LUT4 #(.INIT(16'h8000)) G11 (.O(o6),.I0(o12),.I1(o1),.I2(o2),.I3(o3));
LUT1 #(.INIT(2'b10)) G12 (.O(o11),.I0(o0));
LUT2 #(.INIT(4'b1000)) G13 (.O(o12),.I0(o0),.I1(o11));
LUT6 #(.INIT(64'h8000_0000_0000_0000)) G14 (.O(o13),.I0(o12),.I1(o1),.I2(o2),.I3(o3),.I4(o4),.I5(o5));
//LUT2 #(.INIT(4'b1000)) G15 (.O(o14),.I0(o7),.I1(o8));
//LUT2 #(.INIT(4'b1000)) G16 (.O(o15),.I0(o9),.I1(o10));
(* dont_touch="yes" *) wire [27:0] c;
wire [19:0] ot;
(* dont_touch="yes" *) reg [19:0] t;
generate
genvar j;
for(j=0;j<20;j=j+1)
begin:genJ
LUT2 #(.INIT(4'b1001)) G19 (.O(ot[j]),.I0(qo[j]),.I1(tick_10ms[j]));
end
endgenerate
reg rst_0,rst_1;
// bug not assign day_co = &c ;
always @(negedge clk)
begin
// co_r <= o0 & o1;
tick_10ms_co <= (ot==20'hf_ffff) ? 1'b1 :1'b0;
// co_r <= o12 & o1; // to remove glitch of LUT
co_r <= o12 & o1 ;
// co2_r <= o6 ;
co2_r <= sel==1'b0 ?o6 : ((ot==20'hf_ffff) ? 1'b1 :1'b0);
// co3_r <= o13;
// co4_r <= o13 & o14;
t <= ot;
end
always @*
begin
// day_co= (t!=20'hf_ffff) && (c!=28'hfff_ffff) ? 1'b1 : 1'b0;
day_co= (t==20'hf_ffff) && (c==28'hfff_ffff) ? 1'b0 : 1'b1; // waits for day_co timing for all 1s'
end
always @(posedge clk)
begin
// rst_0 <= rst_n & ((~co2_r & sel) | (~sel )) & day_co;
rst_0 <= rst_n & ((~tick_10ms_co & sel) | (~sel )) & day_co;
rst_1 <= rst_n & day_co;
end
always @(posedge clk)
begin
q<=qo[19:0];
qm<={h10,h1,min10,min1,sec10,sec1,t10m_100,t10m_1};
end
//COUNTER10_e U1(.clk(clk),.rst_n(rst_0),.start_t(start_t[9:0]),.en(en),.q(qo[9:0]),.co(co1));
COUNTER10_e U1(.clk(clk),.rst_n(rst_0),.start_t(start_t[9:0]),.en(en),.q(qo[9:0]),.co());
//COUNTER10_e1 U2(.clk(clk),.rst_n(rst_0),.start_t(start_t[19:10]),.en(co_r),.q(qo[19:10]),.co(co2));
COUNTER10_e1 U2(.clk(clk),.rst_n(rst_0),.start_t(start_t[19:10]),.en(co_r),.q(qo[19:10]),.co());
/*
COUNTER10_e1 U3(.clk(clk),.rst_n(rst_1),.start_t(start_t[29:20]),.en(co2_r),.q(qo[29:20]),.co(co3));
COUNTER10_e1 U4(.clk(clk),.rst_n(rst_1),.start_t(start_t[39:30]),.en(co3_r),.q(qo[39:30]),.co(co4));
COUNTER10_e1 U5(.clk(clk),.rst_n(rst_1),.start_t(start_t[49:40]),.en(co4_r),.q(qo[49:40]),.co(co));
*/
wire [3:0] t10m_100,t10m_1;
wire [2:0] sec10;
wire [3:0] sec1;
wire [2:0] min10;
wire [3:0] min1;
wire [1:0] h10;
wire [3:0] h1;
// wire t10m_co;
//wire sec_co;
//wire min_co;
generate
genvar i;
for(i=0;i<4;i=i+1)
begin:genI0
LUT2 #(.INIT(4'b1001)) G017 (.O(c[i]),.I0(t10m_1[i]),.I1(day_t[i]));
end
for(i=4;i<8;i=i+1)
begin:genI1
LUT2 #(.INIT(4'b1001)) G018 (.O(c[i]),.I0(t10m_100[i-4]),.I1(day_t[i]));
end
for(i=8;i<12;i=i+1)
begin:genI2
LUT2 #(.INIT(4'b1001)) G019 (.O(c[i]),.I0(sec1[i-8]),.I1(day_t[i]));
end
for(i=12;i<15;i=i+1)
begin:genI3
LUT2 #(.INIT(4'b1001)) G020 (.O(c[i]),.I0(sec10[i-12]),.I1(day_t[i]));
end
for(i=15;i<19;i=i+1)
begin:genI4
LUT2 #(.INIT(4'b1001)) G021 (.O(c[i]),.I0(min1[i-15]),.I1(day_t[i]));
end
for(i=19;i<22;i=i+1)
begin:genI5
LUT2 #(.INIT(4'b1001)) G022 (.O(c[i]),.I0(min10[i-19]),.I1(day_t[i]));
end
for(i=22;i<26;i=i+1)
begin:genI6
LUT2 #(.INIT(4'b1001)) G023 (.O(c[i]),.I0(h1[i-22]),.I1(day_t[i]));
end
for(i=26;i<28;i=i+1)
begin:genI7
LUT2 #(.INIT(4'b1001)) G024 (.O(c[i]),.I0(h10[i-26]),.I1(day_t[i]));
end
endgenerate
wire tclk;
BUFG BG0 (.O(tclk),.I(tick_10ms_co));
COUNTER100M U3 (
// .clki(co2_r),.clk(co2_r),.rst_n(rst_1),.en(1'b1),
// .clki(co2_r),.clk(tclk),.rst_n(rst_0),.start_t(start_t[27:20]),.en(1'b1),
.clki(clk),.clk(tclk),.rst_n(rst_1),.ld(ld),.start_t(start_t[27:20]),.en(1'b1),
.q10(t10m_100),
.q(t10m_1),
// .co(t10m_co)
.co()
);
wire sec_en = (t10m_100==4'd9 && t10m_1==4'd9);
COUNTER60M U4 (
.clki(clk),.clk(tclk),.rst_n(rst_1),.ld(ld),.start_t(start_t[34:28]),.en(sec_en),
.q10(sec10),
.q(sec1),
.co()
);
wire min_en = (sec10==3'd5 && sec1==4'd9) && (t10m_100==4'd9 && t10m_1==4'd9) ;
COUNTER60M U5 (
.clki(clk),.clk(tclk),.rst_n(rst_1),.ld(ld),.start_t(start_t[41:35]),.en(min_en),
.q10(min10),
.q(min1),
.co()
);
wire h_en = (min10==3'd5) && (min1 == 4'd9) && (sec10==3'd5 && sec1==4'd9)&& (t10m_100==4'd9 && t10m_1==4'd9);
COUNTER24H U6 (
.clki(clk),.clk(tclk),.rst_n(rst_1),.ld(ld),.start_t(start_t[47:42]),.en(h_en),
.q10(h10),
.q(h1)
);
endmodule
module COUNTER5
(
input clk,rst_n,en,
input [4:0] start_t,
output reg [4:0] q
);
always @(posedge clk)
begin
if(rst_n==1'b0)
q<=start_t;
else if(en)
q<=q+1'b1;
end
endmodule
module COUNTER5_1
(
input clk,rst_n,en,
output reg [4:0] q
);
always @(posedge clk or negedge rst_n)
begin
if(rst_n==1'b0)
q<=0;
else if(en)
q<=q+1'b1;
end
endmodule
module COUNTER10_e
#(parameter ADJ=5'b1_1110)
(
input clk,rst_n,en,
input [9:0] start_t,
output wire [9:0] q,
output reg co
);
reg en_1;
COUNTER5 U0 (.clk(clk),.rst_n(rst_n),.start_t(start_t[4:0]),.en(en),.q(q[4:0]));
// always @(posedge clk)
always @(*)
begin
en_1<= q[4:0]==5'b1_1111;
end
COUNTER5 U1 (.clk(clk),.rst_n(rst_n),.start_t(start_t[9:5]),.en(en_1),.q(q[9:5]));
endmodule
module COUNTER10_e1
#(parameter ADJ=5'b1_1110)
(
input clk,rst_n,en,
input [9:0] start_t,
output wire [9:0] q,
output reg co
);
wire en_1;
COUNTER5 U0 (.clk(clk),.rst_n(rst_n),.start_t(start_t[4:0]),.en(en),.q(q[4:0]));
assign en_1 = (q[4:0]==5'b1_1111) && en==1'b1 ;
COUNTER5 U1 (.clk(clk),.rst_n(rst_n),.start_t(start_t[9:5]),.en(en_1),.q(q[9:5]));
endmodule
module COUNTER10_e2
#(parameter ADJ=5'b1_1110)
(
input clk,rst_n,en,
output wire [9:0] q,
output reg co
);
wire en_1;
COUNTER5_1 U0 (.clk(clk),.rst_n(rst_n),.en(en),.q(q[4:0]));
assign en_1 = (q[4:0]==5'b1_1111) && en==1'b1 ;
COUNTER5_1 U1 (.clk(clk),.rst_n(rst_n),.en(en_1),.q(q[9:5]));
endmodule
module COUNTER100M
(
input clki,clk,rst_n,en,ld,
input [7:0] start_t,
output reg [3:0] q10,
output reg [3:0] q,
output reg co
);
reg en1;
reg rst_d;
always @(posedge clki)
rst_d<= rst_n;
always @(posedge clk or negedge rst_d or posedge ld)
begin
if(rst_d==1'b0)
q=4'b0;
else if(ld==1'b1)
q=start_t[3:0];
else if(en==1'b1)
begin
if(q<9)
q=q+1'b1;
else
q=0;
end
end
always @(negedge clk)
en1<=(q==4'd9) & en;
always @(negedge clk)
co <= (q10==4'd9) & en;
always @(posedge clk or negedge rst_d or posedge ld)
// always @(posedge clk or negedge rst_d)
begin
if(rst_d==1'b0)
q10=0;
else if(ld==1'b1)
q10=start_t[7:4];
else if(en1==1'b1)
begin
if(q10<9)
q10=q10+1'b1;
else
q10=0;
end
end
endmodule
module COUNTER60M
(
input clki,clk,rst_n,en,ld,
input [6:0] start_t,
output reg [2:0] q10,
output reg [3:0] q,
output reg co
);
reg en1,rst_d,rst_d1;
always @(posedge clki)
begin
rst_d<= rst_n;
// rst_d<= rst_d1;
end
always @(posedge clk or negedge rst_d or posedge ld)
// always @(posedge clk or negedge rst_d)
begin
if(rst_d==1'b0)
q=4'b0;
else if(ld==1'b1)
q=start_t[3:0];
else if(en==1'b1)
begin
if(q<9)
q=q+1'b1;
else
q=0;
end
end
always @(negedge clk)
begin
en1= (q==4'd9) & en;
co <= (q10==4'd5) & en;
end
always @(posedge clk or negedge rst_d or posedge ld)
// always @(posedge clk or negedge rst_d)
begin
if(rst_d==1'b0)
q10=3'b0;
else if(ld==1'b1)
q10=start_t[6:4];
else if(en1==1'b1)
begin
if(q10<5)
q10=q10+1'b1;
else
q10=0;
end
end
endmodule
module COUNTER24H
(
input clki,clk,rst_n,en,ld,
input [5:0] start_t,
output reg [1:0] q10,
output reg [3:0] q
);
reg en1,rst_d,rst_d1;
always @(posedge clki)
begin
rst_d<= rst_n;
// rst_d<= rst_d1;
end
always @(negedge clk)
begin
en1<= (q==4'd9) & en;
end
always @(posedge clk or negedge rst_d or posedge ld)
// always @(posedge clk or negedge rst_d)
begin
if(rst_d==1'b0)
q<=4'b0;
else if(ld==1'b1)
q<=start_t[3:0];
else if(en==1'b1)
begin
if(q<9)
q<=q+1'b1;
else
q<=0;
end
end
always @(posedge clk or negedge rst_d or posedge ld)
// always @(posedge clk or negedge rst_d)
begin
if(rst_d==1'b0)
q10<=0;
else if(ld==1'b1)
q10<=start_t[5:4];
else if(en1==1'b1)
begin
if(q10<2)
q10<=q10+1'b1;
else
q10<=2;
end
end
endmodule
`timescale 1ns/10ps
module tb_SyncCnt4;
reg clki,rst_n,en,ld;
reg sel;
reg [47:0] start_t;
reg [19:0] tick_10ms;
reg [27:0] day_t;
wire [19:0] q;
wire [47:20] qm;
wire co;
wire tick_10ms_co;
wire day_co;
SyncCnt4 DUT (.clki(clki),.rst_n(rst_n),.en(en),.ld(ld),.sel(sel),.start_t(start_t),.tick_10ms(tick_10ms),.day_t(day_t),.q(q),.qm(qm),.co(co),.tick_10ms_co(tick_10ms_co),.day_co(day_co));
always #5 clki=~clki;
initial
begin
clki=1'b0; rst_n=1'b1; en=1'b0; sel=1'b1; tick_10ms=20'd999_999; ld=1'b0;
clki=1'b0; rst_n=1'b1; en=1'b0; sel=1'b1; tick_10ms=20'd9;
// not counts clki=1'b0; rst_n=1'b1; en=1'b0; sel=1'b1; tick_10ms=20'd0;
clki=1'b0; rst_n=1'b1; en=1'b0; sel=1'b1; tick_10ms=20'd999_998; // tick 10msec
clki=1'b0; rst_n=1'b1; en=1'b0; sel=1'b1; tick_10ms=20'd998; //tick-2'd2 tick 10usec
clki=1'b0; rst_n=1'b1; en=1'b0; sel=1'b1; tick_10ms=20'd999_998; // tick 10msec
clki=1'b0; rst_n=1'b1; en=1'b0; sel=1'b1; tick_10ms=20'd3;
clki=1'b0; rst_n=1'b1; en=1'b0; sel=1'b1; tick_10ms=20'd999_998; // tick 10msec
// clki=1'b0; rst_n=1'b1; en=1'b0; sel=1'b1; tick_10ms=20'd3;
start_t=48'b0000000000__0000000000__0000000000__0000000000__0000000000;
// start_t =50'b0000011111__1111111111__1111111111__1111111111__1111111110;
// day_t =50'b0000011111__1111111111__1111111111__1111111111__1111111110;
// day_t =66'b__101_1001__1001_1001;// 3_4(h)___3_4(m)___3_4(s)___4_4(10mm)
// day_t =29'b10_0011_101_1001__101_1001__1001_1001;// 3_4(h)___3_4(m)___3_4(s)___4_4(10mm)
// day_t =29'b10_0100_000_0000__000_0000__0000_0000;// 3_4(h)___3_4(m)___3_4(s)___4_4(10mm)
day_t =28'b00_0000_000_0000__001_0000__0000_0000; // 3_4(h)___3_4(m)___3_4(s)___4_4(10mm)
day_t =28'b10_0011_101_1001__101_1001__1001_1001;// 3_4(h)___3_4(m)___3_4(s)___4_4(10mm)
//29 22 15 8
// 2 3 5 9 5 9 9 9
// 2 3 5 9 5 8 0 0
// day_t =28'b10_0011_101_1001__101_1001__1001_1001;// 3_4(h)___3_4(m)___3_4(s)___4_4(10mm)
day_t =28'b10_0100_000_0000__000_0000__0000_0000;// 3_4(h)___3_4(m)___3_4(s)___4_4(10mm)
/* test Okay to check day's elapse timing
#100 rst_n=1'b0;
repeat(100) @(posedge clki); rst_n=1'b1;
#100 en=1'b1;
start_t=48'b10_0011_101_1001__101_1001__1001_1001__0000000000__0000000000;
#100 ld=1'b1;
start_t=48'b10_0011_101_1001__101_1001__1001_1000__0000000000__0000000000;
#500 ld=1'b0;
*/
// test okay to check reset's timing after releasing reset signal
#100 rst_n=1'b0;
repeat(100) @(posedge clki); rst_n=1'b1;
#100 en=1'b1;
start_t=48'b0000000000__0000000000__0000000000__0000000000__0000000000;
#100 ld=1'b1;
start_t=48'b0000000000__0000000000__0000000000__0000000000__0000000000;
#500 ld=1'b0;
/*
repeat(4'b1111) @(posedge clki);
rst_n=1'b0;
start_t=48'b00000000__0000000000__0000000000__0000000000__0000000000;
#100 rst_n=1'b1;
repeat(12'd2010) @(posedge clki);
rst_n=1'b0;
start_t=48'b00000000__0000000000__0000000000__0000000000__1111111000;
#100 rst_n=1'b1;
repeat(12'd2010) @(posedge clki);
rst_n=1'b0;
start_t=48'b00000000__0000000000__0000000000__1111_0100_0010_0011_1000;
#100 rst_n=1'b1;
repeat(12'd2010) @(posedge clki);
rst_n=1'b0;
start_t=48'b00000000__0000000000__0000000000__0000011110__1111111000;
#100 rst_n=1'b1;
repeat(4'b1111) @(posedge clki);
rst_n=1'b0;
start_t=48'b00000000__0000000000__0000000000__1111111111__1111111000;
#100 rst_n=1'b1;
repeat(4'b1111) @(posedge clki);
rst_n=1'b0;
start_t=48'b00000000__0000000000__0000011111__1111111111__1111111000;
#100 rst_n=1'b1;
repeat(4'b1111) @(posedge clki);
rst_n=1'b0;
start_t=48'b00000000__0000000000__1111111111__1111111111__1111111000;
#100 rst_n=1'b1;
repeat(4'b1111) @(posedge clki);
rst_n=1'b0;
start_t=48'b00000000__0000011111__1111111111__1111111111__1111111000;
#100 rst_n=1'b1;
repeat(4'b1111) @(posedge clki);
rst_n=1'b0;
start_t=48'b00000000__1111111111__1111111111__1111111111__1111111000;
#100 rst_n=1'b1;
repeat(4'b1111) @(posedge clki);
rst_n=1'b0;
start_t=48'b00011111__1111111111__1111111111__1111111111__1111111000;
repeat(4'b1111) @(posedge clki);
#100 rst_n=1'b1;
start_t=48'b00011111__1111111111__1111111111__1111111111__1111111000;
day_t =48'b00011111__1111111111__1111111111__1111111111__1111111100;
repeat(12'h1111) @(posedge clki);
#100 rst_n=1'b1;
start_t=48'b00011111__1111111111__1111111111__1111111111__1111111001;
day_t =48'b00011111__1111111111__1111111111__1111111111__1111111101;
*/
end
endmodule
|