다른 사람 꺼
module HC_SR04_cntr (
input clk, reset_p,
input hc_sr04_echo,
output reg hc_sr04_trig,
output reg [21:0] distance,
output [7:0] led_debug);
// For Test
assign led_debug[3:0] = state;
// Define state
parameter S_IDLE = 4'b0001;
parameter S_10US_TTL = 4'b0010;
parameter S_WAIT_PEDGE = 4'b0100;
parameter S_CALC_DIST = 4'b1000;
// Define state, next_state value.
reg [3:0] state, next_state;
// 언제 next_state를 state 변수에 넣는가?
always @(posedge clk or posedge reset_p) begin
if(reset_p) state = S_IDLE;
else state = next_state;
end
// get 10us negative one cycle pulse
wire clk_usec;
clock_div_100 usec_clk( .clk(clk), .reset_p(reset_p), .clk_div_100_nedge(clk_usec)); // 1us
// making usec counter.
reg [21:0] counter_usec;
reg counter_usec_en;
always @(posedge clk or posedge reset_p) begin
if(reset_p) begin counter_usec = 0;
end else if(clk_usec && counter_usec_en) counter_usec = counter_usec + 1;
else if(!counter_usec_en) counter_usec = 0;
end
// hc_sr04_data의 Negative edge, Positive edge 얻기.
wire hc_sr04_echo_n_edge, hc_sr04_echo_p_edge;
edge_detector_p edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(hc_sr04_echo), .n_edge(hc_sr04_echo_n_edge), .p_edge(hc_sr04_echo_p_edge));
// 상태 천이도에 따른 case문 정의
// 각 상태에 따른 동작 정의
always @(negedge clk or posedge reset_p) begin
if(reset_p) begin
next_state = S_IDLE;
counter_usec_en = 0;
end else begin
case(state)
S_IDLE : begin
if(counter_usec < 22'd3_000_000) begin
counter_usec_en = 1;
hc_sr04_trig = 0;
end
else begin
counter_usec_en = 0;
next_state = S_10US_TTL;
end
end
S_10US_TTL : begin
if(counter_usec < 22'd10) begin
counter_usec_en = 1;
hc_sr04_trig = 1;
end
else begin
hc_sr04_trig = 0;
counter_usec_en = 0;
next_state = S_WAIT_PEDGE;
end
end
S_WAIT_PEDGE :
if(hc_sr04_echo_p_edge) begin
next_state = S_CALC_DIST;
counter_usec_en = 1;
end
S_CALC_DIST : begin
if(hc_sr04_echo_n_edge) begin
distance = counter_usec / 58;
counter_usec_en = 0;
next_state = S_IDLE;
end
else next_state = S_CALC_DIST;
end
endcase
end
end
endmodule
module HC_SR04_top (
input clk, reset_p,
input hc_sr04_echo,
output hc_sr04_trig,
output [3:0] com,
output [7:0] seg_7, led_debug) ;
wire [21:0] distance_cm;
HC_SR04_cntr HC_SR04_cntr_0(.clk(clk), .reset_p(reset_p), .hc_sr04_echo(hc_sr04_echo), .hc_sr04_trig(hc_sr04_trig), .distance(distance_cm), .led_debug(led_debug));
wire [11:0] distance_cm_bcd;
bin_to_dec bcd_humi(.bin(distance_cm[11:0]), .bcd(distance_cm_bcd));
fnd_cntr fnd (.clk(clk), .reset_p(reset_p), .value(distance_cm_bcd), .com(com), .seg_7(seg_7));
endmodule
요구시간, 여유시간 = 슬랙시간, 베릴로그 WNS 주의 슬랙시간 표시 슬랙시간이 (-)이면 요구 시간보다 처리 시간이 더 긴것

WNS (Worst Negative Slack):
의미: WNS는 디지털 회로의 각 경로에서 가장 부정적인(즉, 가장 작은) 슬랙을 나타냅니다.
정의: 슬랙(slack)은 신호가 도착해야 하는 시간과 실제 도착하는 시간 사이의 차이를 의미합니다. WNS는 모든 경로 중 가장 작은 슬랙을 의미하며, 이는 해당 경로에서 신호가 가장 긴 시간 동안 지연될 수 있는 한계를 보여줍니다.
의미: WNS가 음수인 경우, 해당 경로의 신호는 지정된 도착 시간 내에 도달하지 못할 수 있습니다. 따라서 WNS를 최소화하여 회로의 신뢰성을 보장하는 것이 중요합니다.
TNS (Total Negative Slack):
의미: TNS는 전체 디지털 회로에서 모든 경로의 WNS를 합산한 값입니다.
정의: 모든 경로의 WNS 값을 더하여 구한 TNS는 디지털 회로 전체의 타이밍적 여유를 나타냅니다. TNS가 양수인 경우, 전체 회로는 동작 가능한 시간 여유를 가지고 있음을 나타내며, 음수인 경우에는 회로 전체에서 어떤 경로가 동작에 불안정성을 초래할 수 있음을 나타냅니다.
WHS (Worst Hold Slack):
의미: WHS는 각 회로 경로에서 가장 부정적인(즉, 가장 작은) 홀드 슬랙을 나타냅니다.
정의: 홀드 슬랙(hold slack)은 레지스터에서의 데이터가 유효한 시간 동안의 여유를 의미합니다. 따라서 WHS는 데이터가 유효하지 않을 수 있는 한계를 보여줍니다.
THS (Total Hold Slack):
의미: THS는 전체 디지털 회로에서 모든 경로의 WHS를 합산한 값입니다.
정의: 모든 경로의 WHS 값을 더하여 구한 THS는 디지털 회로 전체의 데이터가 유효하지 않을 수 있는 시간 여유를 나타냅니다. THS가 양수인 경우, 전체 회로는 안정적으로 동작할 수 있음을 나타내며, 음수인 경우에는 데이터 무결성 문제가 발생할 가능성이 있음을 나타냅니다.
나눗셈은 계산시간이 오래걸려 요구시간이 많이걸려 나눗셈을 안쓰는 코드로 수정
요구 시간을 줄이거나 클락을 늘리거나
나눗셈을 사용하지 않게하여 요구시간을 줄여본다
module HC_SR04_cntr (
input clk, reset_p,
input hc_sr04_echo,
output reg hc_sr04_trig,
output reg [21:0] distance,
output [7:0] led_debug);
// For Test
assign led_debug[3:0] = state;
// Define state
parameter S_IDLE = 4'b0001;
parameter S_10US_TTL = 4'b0010;
parameter S_WAIT_PEDGE = 4'b0100;
parameter S_CALC_DIST = 4'b1000;
// Define state, next_state value.
reg [3:0] state, next_state;
reg [1:0] echo_time;
// 언제 next_state를 state 변수에 넣는가?
always @(posedge clk or posedge reset_p) begin
if(reset_p) state = S_IDLE;
else state = next_state;
end
// get 10us negative one cycle pulse
wire clk_usec;
clock_div_100 usec_clk( .clk(clk), .reset_p(reset_p), .clk_div_100_nedge(clk_usec)); // 1us
// making usec counter.
reg [21:0] counter_usec;
reg counter_usec_en;
always @(posedge clk or posedge reset_p) begin
if(reset_p) begin counter_usec = 0;
end else if(clk_usec && counter_usec_en) counter_usec = counter_usec + 1;
else if(!counter_usec_en) counter_usec = 0;
end
// hc_sr04_data의 Negative edge, Positive edge 얻기.
wire hc_sr04_echo_n_edge, hc_sr04_echo_p_edge;
edge_detector_p edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(hc_sr04_echo), .n_edge(hc_sr04_echo_n_edge), .p_edge(hc_sr04_echo_p_edge));
// 상태 천이도에 따른 case문 정의
// 각 상태에 따른 동작 정의
always @(negedge clk or posedge reset_p) begin
if(reset_p) begin
next_state = S_IDLE;
counter_usec_en = 0;
end else begin
case(state)
S_IDLE : begin
if(counter_usec < 22'd3_000_000) begin
counter_usec_en = 1;
hc_sr04_trig = 0;
end
else begin
counter_usec_en = 0;
next_state = S_10US_TTL;
end
end
S_10US_TTL : begin
if(counter_usec < 22'd10) begin
counter_usec_en = 1;
hc_sr04_trig = 1;
end
else begin
hc_sr04_trig = 0;
counter_usec_en = 0;
next_state = S_WAIT_PEDGE;
end
end
S_WAIT_PEDGE :
if(hc_sr04_echo_p_edge) begin
next_state = S_CALC_DIST;
counter_usec_en = 1;
end
S_CALC_DIST : begin
if(hc_sr04_echo_n_edge) begin
echo_time = counter_usec;
counter_usec_en = 0;
next_state = S_IDLE;
end
else next_state = S_CALC_DIST;
end
endcase
end
end
always @(posedge clk or posedge reset_p)begin
if(reset_p) distance = 0;
else begin
if(echo_time < 174) distance = 2;
else if (echo_time < 232) distance = 3;
else if (echo_time < 290) distance = 4;
else if (echo_time < 348) distance = 5;
else if (echo_time < 406) distance = 6;
else if (echo_time < 464) distance = 7;
else if (echo_time < 522) distance = 8;
else if (echo_time < 580) distance = 9;
else if (echo_time < 638) distance = 10;
else if (echo_time < 696) distance = 11;
else if (echo_time < 754) distance = 12;
else if (echo_time < 812) distance = 13;
else if (echo_time < 870) distance = 14;
else if (echo_time < 928) distance = 15;
else if (echo_time < 986) distance = 16;
else distance = 17;
end
end
endmodule

현재 보드의 lut은 6개의 신호선으로 32경우의수 선택가능
32경우가 넘어서면 lut을 더 사용해야함, 이때 lut을 2개 이상 사용하게 되면 2개의 lut중 하나를 선택하기 위한 또 다른 lut이 필요하게 됨. 따라서 적은 경우의 수인경우 if-else문이나 case문을 사용하는것이 slack을 더 확보할수있겠지만 경우의 수가 늘어날수록 slack이 확연히 줄어든다.
클락을 조절

데이터의 클락의 앞뒤 여유시간


셋타임, 홀드타임

요구시간 - 도달시간 = 슬랙(여유시간)

module HC_SR04_cntr (
input clk, reset_p,
input hc_sr04_echo,
output reg hc_sr04_trig,
output reg [21:0] distance,
output [7:0] led_debug);
// For Test
assign led_debug[3:0] = state;
// Define state
parameter S_IDLE = 4'b0001;
parameter S_10US_TTL = 4'b0010;
parameter S_WAIT_PEDGE = 4'b0100;
parameter S_CALC_DIST = 4'b1000;
// Define state, next_state value.
reg [3:0] state, next_state;
reg [1:0] echo_time;
// 언제 next_state를 state 변수에 넣는가?
always @(posedge clk or posedge reset_p) begin
if(reset_p) state = S_IDLE;
else state = next_state;
end
// get 10us negative one cycle pulse
wire clk_usec;
clock_div_100 usec_clk( .clk(clk), .reset_p(reset_p), .clk_div_100_nedge(clk_usec)); // 1us
reg cnt_e;
wire [11:0] cm;
sr04_div_58(.clk(clk), .reset_p(reset_p),
.clk_usec(clk_usec), .cnt_e(cnt_e), .cm(cm));
// making usec counter.
reg [21:0] counter_usec;
reg counter_usec_en;
always @(posedge clk or posedge reset_p) begin
if(reset_p) begin counter_usec = 0;
end else if(clk_usec && counter_usec_en) counter_usec = counter_usec + 1;
else if(!counter_usec_en) counter_usec = 0;
end
// hc_sr04_data의 Negative edge, Positive edge 얻기.
wire hc_sr04_echo_n_edge, hc_sr04_echo_p_edge;
edge_detector_p edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(hc_sr04_echo), .n_edge(hc_sr04_echo_n_edge), .p_edge(hc_sr04_echo_p_edge));
// 상태 천이도에 따른 case문 정의
// 각 상태에 따른 동작 정의
always @(negedge clk or posedge reset_p) begin
if(reset_p) begin
next_state = S_IDLE;
counter_usec_en = 0;
cnt_e = 0;
end else begin
case(state)
S_IDLE : begin
if(counter_usec < 22'd3_000_000) begin
counter_usec_en = 1;
hc_sr04_trig = 0;
end
else begin
counter_usec_en = 0;
next_state = S_10US_TTL;
end
end
S_10US_TTL : begin
if(counter_usec < 22'd10) begin
counter_usec_en = 1;
hc_sr04_trig = 1;
end
else begin
hc_sr04_trig = 0;
counter_usec_en = 0;
next_state = S_WAIT_PEDGE;
end
end
S_WAIT_PEDGE :
if(hc_sr04_echo_p_edge) begin
next_state = S_CALC_DIST;
cnt_e = 1;
end
S_CALC_DIST : begin
if(hc_sr04_echo_n_edge) begin
distance = cm;
cnt_e = 0;
next_state = S_IDLE;
end
else next_state = S_CALC_DIST;
end
endcase
end
end
// always @(posedge clk or posedge reset_p)begin
// if(reset_p) distance = 0;
// else begin
// if(echo_time < 174) distance = 2;
// else if (echo_time < 232) distance = 3;
// else if (echo_time < 290) distance = 4;
// else if (echo_time < 348) distance = 5;
// else if (echo_time < 406) distance = 6;
// else if (echo_time < 464) distance = 7;
// else if (echo_time < 522) distance = 8;
// else if (echo_time < 580) distance = 9;
// else if (echo_time < 638) distance = 10;
// else if (echo_time < 696) distance = 11;
// else if (echo_time < 754) distance = 12;
// else if (echo_time < 812) distance = 13;
// else if (echo_time < 870) distance = 14;
// else if (echo_time < 928) distance = 15;
// else if (echo_time < 986) distance = 16;
// else if (echo_time < 1044) distance = 17;
// else if (echo_time < 1102) distance = 18;
// else if (echo_time < 1160) distance = 19;
// else if (echo_time < 1218) distance = 20;
// else if (echo_time < 1276) distance = 21;
// else if (echo_time < 1334) distance = 22;
// else if (echo_time < 1392) distance = 23;
// else if (echo_time < 1450) distance = 24;
// else if (echo_time < 1508) distance = 25;
// else if (echo_time < 1566) distance = 26;
// else if (echo_time < 1624) distance = 27;
// else if (echo_time < 1682) distance = 28;
// else if (echo_time < 1740) distance = 29;
// else if (echo_time < 1798) distance = 30;
// else if (echo_time < 1856) distance = 31;
// else if (echo_time < 1914) distance = 32;
// else if (echo_time < 1972) distance = 33;
// else if (echo_time < 2030) distance = 34;
// else distance = 35;
// end
// end
endmodule
module sr04_div_58(
input clk, reset_p,
input clk_usec, cnt_e,
output reg [11:0] cm);
reg [5:0] cnt;
always @(negedge clk or posedge reset_p)begin
if(reset_p)begin
cnt = 0;
cm = 0;
end
else if(clk_usec)begin
if(cnt_e)begin
if(cnt >= 57)begin
cnt = 0;
cm = cm + 1;
end
else cnt = cnt + 1;
end
end
else if(!cnt_e)begin
cnt = 0;
cm = 0;
end
end
endmodule
