/*********************************************************/
// 모듈:faultRecoveryCounter
// 파일이름:faultRecoveryCounter.v
// 버젼 : 1.0
// 날짜 : 2026.05.05
// 저자 : 탁 형옥
// 코딩 언어 : verilog
// 문제 내용 (해결해야 할 목표):
카운터의 카운팅에 오류값 천이시에 오류 직전 카운터값에서 카운팅을 이어가거나 0부터 카운팅을 이어서 계속 카운팅하는 회로
// 요구되는 언어 기술 (어려운 점):
카운터의 카운팅 오류 상태 진입 감지가 어렵고, 정상 카운터로 다시 시작하기가 어렵다.
카운팅은 stIDLE 에서 st0로 진입후에 순차 증가로 st0~st9를 라운드 로빈으로 천이한다.
// 목표와 기술을 도달하기 위한 알아야 할 기술(문법), 어려운 점, 문제점 극복 과정:
// 결과 도출:
- stIDLE로 장애 카운팅시에 초기값에서 다시 시작하는 카운팅 동작을 수행한다.
- stRecovery 상태로 정상카운팅 오류 직전 마지막 상태값으로의 카운팅 진입을 위해 만들었다.
// 기본 목표 과제를 한층 더 깊이 있게 하기 위한 생각:
일시적으로 0을 유지하는 오류 카운터값 입력시 장애가 풀리면 장애전의 상태카운터값부터 이어서 카운팅
(장애 발생싯점으로 부터 연속성 보장이 의심 스러움)
일시적으로 1을 유지하는 오류 카운터값 입력시 장애가 있는 동안 카운팅이 정상적이지 않지만 장애가 풀리면 장애전의 복구 상태값에서 부터 카운팅을 시작함
// 이용 가능한 분야: 몰라요. (시계에 쓸수 있을까)
// 기술과 트렌드:
// 설명 :
//
/*********************************************************/
module faultRecoveryCounter (
input clki,rst_n,
input modeSel, // stIDLE 로 진입할 것인지 stRecovery를 장애 발생전 상태값으로 부터 진입시킬 것인지 결정
output reg [11:0] state
);
//localparam st0 =4'd0, st1=4'd1,st2=4'd2,st3=4'd3,st4=4'd4,st5=4'd5,st6=4'd6,st7=4'd7,st8=4'd8,st9=4'd9,stRecovery=4'd10,stIdle=4'd15;
localparam st0 =12'b1111_1111_1110, st1=12'b1111_1111_1101,st2=12'b1111_1111_1011,st3=12'b1111_1111_0111,
st4=12'b1111_1110_1111,st5=12'b1111_1101_1111,st6=12'b1111_1011_1111,st7=12'b1111_0111_1111,
st8=12'b1110_1111_1111,st9=12'b1101_1111_1111,stRecovery=12'b1011_1111_1111, stIDLE=12'b11111_1111_1111;
localparam FAIL=1'b1,pstateSuccess=1'b0;
reg [9:0] faults;
(* dont_touch ="yes" *) reg [11:0] expected_addr,fault_addr,safe_addr,safe_addr_d;
(* dont_touch ="yes" *) wire clkn;
reg [7:0] fault_cnt;
reg en_r1,en_r2,upDown_r,rst_r;
clk_wiz_0 CLOCK
(
.clk_out1(clk),
// .clk_out2(clkn),
// .clk_out3(clk_out3),
.reset(1'b0),
.locked(locked),
.clk_in1(clki)
);
// BUFG G0 (.O(clk),.I(clki));
always @(posedge clk)
begin
if(rst_n==1'b0)
begin
expected_addr<=stIDLE;
fault_cnt<=0;
end
else
begin
case(expected_addr)
stIDLE: expected_addr<= expected_addr[10]!=1'b0 ? st0:stIDLE;
st0: expected_addr<=(expected_addr[10]!=1'b0 )?st1:st0;
st1: expected_addr<=(expected_addr[10]!=1'b0 )?st2:st1;
st2: expected_addr<=(expected_addr[10]!=1'b0 )?st3:st2;
st3: expected_addr<=(expected_addr[10]!=1'b0 )?st4:st3;
st4: expected_addr<=(expected_addr[10]!=1'b0 )?st5:st4;
st5: expected_addr<=(expected_addr[10]!=1'b0 )?st6:st5;
st6: expected_addr<=(expected_addr[10]!=1'b0 )?st7:st6;
st7: expected_addr<=(expected_addr[10]!=1'b0 )?st8:st7;
st8: expected_addr<=(expected_addr[10]!=1'b0 )?st9:st8;
st9: expected_addr<=(expected_addr[10]!=1'b0 )?st0:st9;
stRecovery:expected_addr <= fault_addr;
default: begin
//fault_addr <=stIDLE;
fault_addr <=(modeSel==1'b0) ?{2'b11,safe_addr_d[9:0]} : stIDLE;
expected_addr <=stRecovery;
fault_cnt<=fault_cnt+1;
end
endcase
state <= expected_addr;
end
end
always @(negedge clk)
begin
safe_addr <= (expected_addr[10]!=1'b0 )? expected_addr : safe_addr;
safe_addr_d <= (expected_addr[10]!=1'b0) ? safe_addr : safe_addr_d;
end
endmodule
`timescale 1ns/1ns
module tb_faultRecoveryCounter ;
reg clki,rst_n;
reg modeSel;
wire [11:0] state;
faultRecoveryCounter DUT (.clki(clki),.rst_n(rst_n),.modeSel(modeSel),.state(state));
always #5 clki=~clki;
initial
begin
clki=1'b0; rst_n=1'b1; modeSel=1'b0;
#10 rst_n=1'b0;
#10 rst_n=1'b1;
asyncRST;
#1000 @(posedge clki) asyncRST;
#1000 @(posedge clki) asyncRST;
#1000 @(posedge clki) asyncRST;
#1000 @(posedge clki) asyncRST;
#1000 @(posedge clki) asyncRST;
end
task asyncRST;
begin
#499 rst_n=1'b0;
#9 rst_n=1'b1;
end
endtask
endmodule