본문 바로가기

RTL Design/Verilog RTL 설계

Verilog RTL 설계(7월 17일 - 3, Clock Mode)

1. Clock Pulse를 이용하여 Clock 만들기

  • basys3의 기본 클럭 펄스의 주기는 10ns이다. 이를 활용하여 시계를 만들고자 한다.
  • 다음과 같이 동작한다.
    - 4개의 FND를 이용하여 첫 번째, 두 번째 FND는 초 단위, 세 번째, 네 번째 FND는 분 단위를 출력한다.
    - 초 단위는 0 ~ 59초 까지 Counting이 가능하며, 60초가 되면 0초로 초기화되며, 분 값이 1씩 증가한다.
    - 분 단위도 0 ~ 59분 까지 Counting이 가능하며, 60분이 되면 0분으로 초기화된다.

 

 

 

1.1. 동시에 서로 다른 숫자들을 동시에 출력하기

  • 시간을 분의 십의 자리, 분의 일의 자리, 초의 십의 자리, 초의 일의 자리로 나눈다.
  • 각각의 시간의 데이터를 Ring Counter를 이용하여 com 변수 값들을 빠르게 Shifting하면서 해당 위치의 FND에 출력하면 동시에 서로 다른 숫자들을 출력할 수 있다.
  • 10ms 이하의 주기를 갖고, com 변수 값들을 Shifting 한다면 사람의 눈으로는 Shifting한다는 사실을 인지할 수 없이 동시에 출력되는 것을 착각하게 만들 수 있다.
  • 따라서 이번에는 1ms 주기를 갖고, com 변수 값을 Left Shifting하도록 하겠다.
  • 자세한 원리 및 구현 방법은 아래 게시글을 참고 바란다.
    Verilog RTL 설계(7월 17일 - 2, FND 동시 출력) (tistory.com)
 

Verilog RTL 설계(7월 17일 - 2, FND 동시 출력)

1. 서로 다른 숫자들을 FND을 통해 동시 출력하기이번에는 4자리 16진수 데이터를 FND을 통해 한 번에 동시 출력 되도록 설계해보도록 하겠다.이번 구현 동작은 다음과 같이 동작한다.- 16개의 Switch

jbhdeve.tistory.com

 

 

 

 

 

1.2. 10ns 주기를 갖는 기본 클럭 펄스를 가지고, 분과 초를 얻을 수 있는가?

  • 분과 초 값을 얻기 위해서 Counter를 이용할 것이다.
  • 초를 기준으로 설명하자면 다음과 같이 생각할 수 있다.
    - 어떤 주기가 1초인 신호가 있는데, 이 신호는 1초마다 Counter에게 "1초 지났어. 카운터 값을 1씩 증가해." 알려준다.
    - Counter는 해당 신호를 받고, 현재 Counter가 현재까지 Counting한 값을 1씩 증가시킨다.
    - 이 때, 필요한 신호가 "1초가 지났음을 알려주는 신호"이며, 해당 신호의 역활 수행할 수 있는 것이 "주기가 1sec인 One Cycle Pulse" 이다.
    - 즉, Counter는 외부에서 발생한 One Cycle Pulse를 감지하고, 현재까지 Counting한 값을 1씩 증가하는 것이다.
    - 초 값은 0 ~ 59까지만 존재하기 때문에 Counter가 60까지 카운팅하면 다시 0으로 초기화 된다.
  • 분 또한 초와 마찬가지로 움직인다. 다만, 분을 카운터하는 Counter 같은 경우에는 "주기가 1min인 One Cycle Pulse"를 받아야 올바른 시점에 카운터 값을 1씩 증가 시킬 수 있다.

 

 

 

 

1.3. 어떻게 1sec, 1min인 One Cycle Pulse를 만들 것인가?

  • 바로 분주비를 통해 원하는 주기를 갖는 Pulse wave와 One Cycle Pulse를 생성할 수 있다.
  • 분주비는 여러 개의 Pulse를 하나로 묶어 하나의 Pulse로 생각하는 방식이다.
  • 따라서 분주비를 통해 10ns인 펄스파를 묶어서 원하는 주기인 1sec, 1min One Cycle Pulse와 Pulse wave를 얻을 수 있다.
  • 주기가 1sec, 1min인 One Cycle Pulse를 다음과 같은 과정을 통해 얻을 것이다.
    - 먼저, 10ns인 CP를 100분주를 통해 주기가 1usec인 Pulse wave를 얻을 수 있다.
    - 1use인 Pulse wave를 1000분주를 통해 주기가 1msec인 Pulse wave를 얻을 수 있다.
    - 1msec인 Pulse wave를 1000분주를 통해 주기가 1sec인 Pulse wave를 얻을 수 있다.
    - 1sec인 Pulse wave를 60분주를 통해 주기가 1min인 Pulse wave을 얻을 수 있다.

 

 

 

 

 

 

2. 구현 

  • 일반적인 클럭을 구현하기 위해 다음과 같은 모듈을 만들었다.
  • edge_detector_n : 임의의 펄스를 입력받아서 edge를 감지한 One Cycle Pulse를 출력으로 내보내는 모듈
  • decoder_seg_7 : 16진수 데이터를 입력받아서 FND에 출력하기 위한 8bit 데이터를 출력으로 내보내는 모듈
  • ring_counter_fnd : FND의 Common anode 값을 이용하여 1ms 주기로 출력으로 내보낼 FND를 Shifting하는 모듈
  • fnd_cntr : FND Control 및 입력 받은 데이터를 FND로 출력으로 내보내는 모듈
  • clk_div_60 : 입력 받은 펄스를 60분주시켜 새로운 펄스 파와 One Cycle Pulse를 출력으로 내보내는 모듈
  • clk_div_100 : CP를 100분주시켜 새로운 펄스 파와 One Cycle Pulse를 출력으로 내보내는 모듈
  • clk_div_1000 : 입력 받은 펄스를 1000분주시켜 새로운 펄스 파와 One Cycle Pulse를 출력으로 내보내는 모듈
  • counter_bcd_60 : BCD Code 형태로 0 ~ 59까지 카운트할 수 있는 모듈
  • Normal_Clock_0 : Root of module

 

 

 

2.1. Source, Edge Detector

  • D Flip Flop 2개를 직렬로 이어 구현한 Negative edge Detector이다.
  • edge를 감지하게 되면 감지했음을 One Cycle Pulse 출력시켜 알리게 된다.
// Edge detector 
module edge_detector_n (
    input clk, reset_p,
    input cp,
    output n_edge, p_edge );
    
    reg flip_flop_current, flip_flop_old;
    
    always @(posedge clk or posedge reset_p) begin
         if(reset_p) begin
            flip_flop_current <= 0;
            flip_flop_old <= 0;
         end
         else begin
            flip_flop_current <= cp;
            flip_flop_old <= flip_flop_current;
         end
    end
    
    assign p_edge = ({flip_flop_current, flip_flop_old} == 2'b10)? 1 : 0;
    assign n_edge = ({flip_flop_current, flip_flop_old} == 2'b01)? 1 : 0;
    
endmodule

 

 

 

 

2.2. Source, decoder_seg_7 

  • 4bit 크기를 갖는 16진 데이터를 입력받으면 해당 데이터를 FND로 출력하기 위한 8bit 데이터로 만들어 반환한다.
  • 해당 모듈은 Decoder로 구현되며, 입력 값으로 16진 데이터, 출력 값으로 FND 데이터를 갖게 된다. 
// Decoder of FND
module decoder_seg_7 (
    input [3:0] hex_value,
    output reg [7:0] seg_7);
    
    always @(hex_value) begin
        case(hex_value)
            0  : seg_7 = 8'b0000_0011;  // 0
            1  : seg_7 = 8'b1001_1111;  // 1
            2  : seg_7 = 8'b0010_0101;  // 2
            3  : seg_7 = 8'b0000_1101;  // 3
            4  : seg_7 = 8'b1001_1001;  // 4
            5  : seg_7 = 8'b0100_1001;  // 5
            6  : seg_7 = 8'b0100_0001;  // 6
            7  : seg_7 = 8'b0001_1111;  // 7
            8  : seg_7 = 8'b0000_0001;  // 8
            9  : seg_7 = 8'b0000_1001;  // 9
            10 : seg_7 = 8'b0000_0101;  // A
            11 : seg_7 = 8'b1100_0001;  // b
            12 : seg_7 = 8'b0110_0011;  // C
            13 : seg_7 = 8'b1000_0101;  // d
            14 : seg_7 = 8'b0110_0001;  // E
            15 : seg_7 = 8'b0111_0001;  // F
        endcase 
    end
    
endmodule

 

 

 

 

2.3. Source, ring_counter_fnd

  • 0 ~ 99999 까지 Counting을 할 수 있어야 하기 때문에 17bit 크기를 갖는 Counter여야 한다.
  • counter를 통해 주기가 0.5ms이고, Duty cycle이 50%인 Pulse wave (clk_div_100000) 생성하며,
    edge detector를 통해 주기가 0.5ms인 One Cycle Pulse (clk_div_100000_nedge)를 생성한다.
  • clk_div_100000_nedge 가 활성화되는 순간에 com 변수 값을 Left Shifting하게 된다.
// Ring Counter 
module ring_counter_fnd (
    input clk, reset_p,
    output reg [3:0] com);
    
    // prescale 100000
    reg[16:0] counter;
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) counter = 0;
        else begin
            if(counter >= 99999) counter =0;
            else counter = counter + 1;
        end
    end
   
    // clk_div_100000 : 주기가 0.5ms이고, Duty cycle이 50%인 Pulse wave
    // clk_div_100000_nedge : 주기가 0.5ms인 One Cycle Pulse
    wire  clk_div_100000, clk_div_100000_nedge;
    assign clk_div_100000 = (counter < 50000)? 0 : 1;
    edge_detector_n edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_div_100000), .n_edge(clk_div_100000_nedge));  
   
   
    // clk_div_100000_nedge이 활성화되면 com 변수 값을 Left Shifting한다.
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) com = 4'b1110;
        else if(clk_div_100000_nedge) begin
                if(com == 4'b0111) com = 4'b1110;
                else com = {com[2:0], 1'b1};
        end
    end 
    
endmodule

 

 

 

 

2.4. Source, fnd_cntr

  • ring_counter_fnd 모듈을 통해 com 변수를 정한 뒤,  com 변수를 통해 해당 FND에 출력되어야 하는 hex_value를 얻는다.
  • 16bit 크기를 갖는 value 변수는 "분의 십의 자리, 분의 일의 자리, 초의 십의 자리, 초의 일의 자리" 로 구성된 데이터이다.
  • decoder_seg_7 모듈에 hex_value를 전달해줌으로서 해당 모듈로부터 FND에 출력을 위한 데이터(seg_7)을 얻을 수 있다.
// 7-Segment Control
module fnd_cntr (
    input clk, reset_p,
    input [15:0] value,
    output [3:0] com,
    output [7:0] seg_7 );
 
    // Get One Cycle Pulse of 1ms
   ring_counter_fnd fnd (.clk(clk), .reset_p(reset_p), .com(com));
    
    // Select the hex_value.
    reg [3:0] hex_value;
    
    always @(posedge clk) begin
        case(com) 
            4'b1110 : hex_value = value[3:0];
            4'b1101 : hex_value = value[7:4];
            4'b1011 : hex_value = value[11:8];
            4'b0111 : hex_value = value[15:12];
            default : hex_value = hex_value;
        endcase
    end 
   
    decoder_seg_7 decoder (.hex_value(hex_value), .seg_7(seg_7));
endmodule

 

 

 

 

2.5. Source, clk_div_1000

  • clk_div_1000 모듈은 입력 받은 클럭파를 1000분주하여 새로운 펄스파와 One Cycle Pulse를 출력으로 내보낸다.
  • 입력으로 받은 clk_source 펄스파는 One Cycle Pulse가 아닌 펄스 파형이다.
  • 0 ~ 999까지 Counting하기 위해서는 10bit 크기를 갖는 Counter를 가져야 한다.
  • clk_source_nedge 변수는 edge detector로부터 얻은 negative edge를 알려주는 One Cycle Pulse이며, clk_source_nedge 변수가 활성화 될 때마다 카운터 값을 1씩 증가 시킨다.
  • 출력으로 내보내는 clk_div_1000 펄스 파는 1000분주하여 만들어진 새로운 파형이며, Duty Cycle은 50%를 갖는다.
  • clk_div_1000_nedge 변수는 clk_div_1000  펄스 파를 edge detector를 통해 얻은 One Cycle Pulse이다.
// prescaler 1000
module clk_div_1000 (  
    input clk, reset_p,
    input clk_source,
    output clk_div_1000,
    output clk_div_1000_nedge );
    
    wire clk_source_nedge;
    edge_detector_n edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_source), .n_edge(clk_source_nedge));
    
    reg [9:0] counter;
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) counter = 0;
        else if(clk_source_nedge) begin
            if(counter >= 999) counter = 0;
            else counter = counter + 1;
        end
    end
    
    assign clk_div_1000 = (counter < 500)? 0 : 1;
    
    edge_detector_n edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(clk_div_1000), .n_edge(clk_div_1000_nedge));
endmodule

 

 

 

 

 

2.6. Source, clk_div_60

  • clk_div_1000 모듈과 동일하게 동작한다.
  • clk_div_60 모듈을 통해 1sec 주기를 갖는 펄스파를 60분주하여 1min 주기를 갖는 펄스파를 생성하게 된다.
// prescaler 60
module clk_div_60 (
    input clk, reset_p,
    input clk_source,
    output clk_div_60,
    output clk_div_60_nedge );
    
    wire clk_source_nedge;
    edge_detector_n edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_source), .n_edge(clk_source_nedge));
    
    reg[5:0] counter;
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) counter = 0;
        else if(clk_source_nedge) begin
            if(counter >= 59) counter = 0;
            else counter = counter + 1;
        end
    end
    
    assign clk_div_60 = (counter < 30) ? 0 : 1;
    
    edge_detector_n edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(clk_div_60), .n_edge(clk_div_60_nedge));  
endmodule

 

 

 

 

 

2.7. Source, clk_div_100

  • CP(Clock Pulse, Period = 10ns)를 100분주하여 1usec 주기를 갖는 펄스파를 생성하는 모듈
// Prescaler 100
module clk_div_100 (
    input clk, reset_p,
    output clk_div_100,
    output clk_div_100_nedge );
    
    reg [6:0] counter;
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) counter = 0;
        else begin
            if(counter >= 99) counter = 0;
            else counter = counter + 1;
        end
    end
    
    assign clk_div_100 = (counter < 50)? 0 : 1;
    
    edge_detector_n edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(clk_div_100), .n_edge(clk_div_100_nedge));    
endmodule

 

 

 

 

2.8. Source, counter_bcd_60

  • 입력 받은 clk_time 펄스를 Edge detector를 거쳐 clk_time의 One Cycle Pulse인 clk_time_nedge를 만든 뒤, clk_time_nedge 값이 활성화된 순간마다 카운트 값을 1씩 증가 시키는 BCD 60진 카운터이다.
  • 60진 카운터이기 때문에 0 ~ 59까지만 카운트 할 수 있다.
  • bcd1 : 분 / 초의 일의 자리를 값을 BCD 형태로 나타낸다.
  • bcd10 : 분 / 초의 십의 자리를 값을 BCD 형태로 나타낸다.
// BCD 60 Counter
module counter_bcd_60 (
    input clk, reset_p,
    input clk_time,
    output reg [3:0] bcd1, bcd10 );
    
    // Get One Cycle Pulse of clk_time.
    wire clk_time_nedge;
    edge_detector_n edge_detector (.clk(clk), .reset_p(reset_p), .cp(clk_time), .n_edge(clk_time_nedge));
    
    // Counting
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) begin
            bcd1 = 0;
            bcd10 = 0;
        end
        else if(clk_time_nedge) begin
            if(bcd1 >= 9 ) begin
                bcd1 = 0;
                if(bcd10 >= 5) bcd10 = 0;
                else bcd10 = bcd10 + 1;
            end
            else bcd1 = bcd1 + 1;
        end
    end
    
endmodule

 

 

 

 

2.9. Source, Normal_Clock_0

  • 10ns 주기를 갖는 clk를 가지고, 100분주화, 1000분주화, 60분주화를 통해 주기가 1sec, 1min인 Pulse wave를 얻는다. ( 주기가 1sec인 펄스파 : clk_sec ,  주기가 1min인 펄스파 : clk_min )
  • counter_bcd_60 모듈의 argument 값으로 clk_sec, clk_min을 전달함으로서 counter_bcd_60는 각각의 기준 펄스를 가지고, Countng한 뒤, FND에 표시할 분과 초 값을 십의 자리와 일의 자리로 나누어 return 한다.
  • 그리고 난 뒤, 결합 연산자를 통해 분과 초를 결합하여 16bit 데이터로 만든 뒤, fnd_cntr 모듈에게 전달하여 출력하도록 한다.
module Normal_Clock_0(
    input clk, reset_p, 
    output [3:0] com,
    output [7:0] seg_7 );
    
    // Get Pulse of second, minute
    wire clk_usec, clk_msec, clk_sec, clk_min;
    clk_div_100 clk_div_usec (.clk(clk), .reset_p(reset_p), .clk_div_100(clk_usec));
    clk_div_1000 clk_div_msec (.clk(clk), .reset_p(reset_p), .clk_source(clk_usec), .clk_div_1000(clk_msec));
    clk_div_1000 clk_div_sec (.clk(clk), .reset_p(reset_p), .clk_source(clk_msec), .clk_div_1000(clk_sec));
    clk_div_60 clk_div_min (.clk(clk), .reset_p(reset_p), .clk_source(clk_sec), .clk_div_60(clk_min));
    
    // BCD 60 Counter
    wire [3:0] min10, min1, sec10, sec1;
    counter_bcd_60 counter_sec (.clk(clk), .reset_p(reset_p), .clk_time(clk_sec), .bcd1(sec1), .bcd10(sec10));
    counter_bcd_60 counter_min (.clk(clk), .reset_p(reset_p), .clk_time(clk_min), .bcd1(min1), .bcd10(min10));
    
    // Combine data of second and minute.
    wire [15:0] value;
    assign value = {min10, min1, sec10, sec1};
    
    // Print the FND
    fnd_cntr fnd (.clk(clk), .reset_p(reset_p), .value(value), .com(com), .seg_7(seg_7));    
endmodule

 

 

 

 


2.10. Total Source

module Normal_Clock_0(
    input clk, reset_p, 
    output [3:0] com,
    output [7:0] seg_7 );
    
    // Get Pulse of second, minute
    wire clk_usec, clk_msec, clk_sec, clk_min;
    clk_div_100 clk_div_usec (.clk(clk), .reset_p(reset_p), .clk_div_100(clk_usec));
    clk_div_1000 clk_div_msec (.clk(clk), .reset_p(reset_p), .clk_source(clk_usec), .clk_div_1000(clk_msec));
    clk_div_1000 clk_div_sec (.clk(clk), .reset_p(reset_p), .clk_source(clk_msec), .clk_div_1000(clk_sec));
    clk_div_60 clk_div_min (.clk(clk), .reset_p(reset_p), .clk_source(clk_sec), .clk_div_60(clk_min));
    
    // BCD 60 Counter
    wire [3:0] min10, min1, sec10, sec1;
    counter_bcd_60 counter_sec (.clk(clk), .reset_p(reset_p), .clk_time(clk_sec), .bcd1(sec1), .bcd10(sec10));
    counter_bcd_60 counter_min (.clk(clk), .reset_p(reset_p), .clk_time(clk_min), .bcd1(min1), .bcd10(min10));
    
    // Combine data of second and minute.
    wire [15:0] value;
    assign value = {min10, min1, sec10, sec1};
    
    // Print the FND
    fnd_cntr fnd (.clk(clk), .reset_p(reset_p), .value(value), .com(com), .seg_7(seg_7));    
endmodule

// BCD 60 Counter
module counter_bcd_60 (
    input clk, reset_p,
    input clk_time,
    output reg [3:0] bcd1, bcd10 );
    
    wire clk_time_nedge;
    edge_detector_n edge_detector (.clk(clk), .reset_p(reset_p), .cp(clk_time), .n_edge(clk_time_nedge));
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) begin
            bcd1 = 0;
            bcd10 = 0;
        end
        else if(clk_time_nedge) begin
            if(bcd1 >= 9 ) begin
                bcd1 = 0;
                if(bcd10 >= 5) bcd10 = 0;
                else bcd10 = bcd10 + 1;
            end
            else bcd1 = bcd1 + 1;
        end
    end
    
endmodule

// Prescaler 100
module clk_div_100 (
    input clk, reset_p,
    output clk_div_100,
    output clk_div_100_nedge );
    
    reg [6:0] counter;
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) counter = 0;
        else begin
            if(counter >= 99) counter = 0;
            else counter = counter + 1;
        end
    end
    
    assign clk_div_100 = (counter < 50)? 0 : 1;
    
    edge_detector_n edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(clk_div_100), .n_edge(clk_div_100_nedge));    
endmodule

// prescaler 1000
module clk_div_1000 (  
    input clk, reset_p,
    input clk_source,
    output clk_div_1000,
    output clk_div_1000_nedge );
    
    wire clk_source_nedge;
    edge_detector_n edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_source), .n_edge(clk_source_nedge));
    
    reg [9:0] counter;
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) counter = 0;
        else if(clk_source_nedge) begin
            if(counter >= 999) counter = 0;
            else counter = counter + 1;
        end
    end
    
    assign clk_div_1000 = (counter < 500)? 0 : 1;
    
    edge_detector_n edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(clk_div_1000), .n_edge(clk_div_1000_nedge));
endmodule

// prescaler 60
module clk_div_60 (
    input clk, reset_p,
    input clk_source,
    output clk_div_60,
    output clk_div_60_nedge );
    
    wire clk_source_nedge;
    edge_detector_n edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_source), .n_edge(clk_source_nedge));
    
    reg[5:0] counter;
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) counter = 0;
        else if(clk_source_nedge) begin
            if(counter >= 59) counter = 0;
            else counter = counter + 1;
        end
    end
    
    assign clk_div_60 = (counter < 30) ? 0 : 1;
    
    edge_detector_n edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(clk_div_60), .n_edge(clk_div_60_nedge));  
endmodule

// 7-Segment Control
module fnd_cntr (
    input clk, reset_p,
    input [15:0] value,
    output [3:0] com,
    output [7:0] seg_7 );
 
    // Get One Cycle Pulse of 1ms
   ring_counter_fnd fnd (.clk(clk), .reset_p(reset_p), .com(com));
    
    // Select the hex_value.
    reg [3:0] hex_value;
    
    always @(posedge clk) begin
        case(com) 
            4'b1110 : hex_value = value[3:0];
            4'b1101 : hex_value = value[7:4];
            4'b1011 : hex_value = value[11:8];
            4'b0111 : hex_value = value[15:12];
            default : hex_value = hex_value;
        endcase
    end 
   
    decoder_seg_7 decoder (.hex_value(hex_value), .seg_7(seg_7));
endmodule

// Ring Counter 
module ring_counter_fnd (
    input clk, reset_p,
    output reg [3:0] com);
    
    // prescale 100000
    reg[16:0] counter;
    
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) counter = 0;
        else begin
            if(counter >= 99999) counter =0;
            else counter = counter + 1;
        end
    end
   
    wire  clk_div_100000, clk_div_100000_nedge;
    assign clk_div_100000 = (counter < 50000)? 0 : 1;
    edge_detector_n edge_detector_0 (.clk(clk), .reset_p(reset_p), .cp(clk_div_100000), .n_edge(clk_div_100000_nedge));  
   
    always @(posedge clk or posedge reset_p) begin
        if(reset_p) com = 4'b1110;
        else if(clk_div_100000_nedge) begin
                if(com == 4'b0111) com = 4'b1110;
                else com = {com[2:0], 1'b1};
        end
    end 
    
endmodule

// Decoder of FND
module decoder_seg_7 (
    input [3:0] hex_value,
    output reg [7:0] seg_7);
    
    always @(hex_value) begin
        case(hex_value)
            0  : seg_7 = 8'b0000_0011;  // 0
            1  : seg_7 = 8'b1001_1111;  // 1
            2  : seg_7 = 8'b0010_0101;  // 2
            3  : seg_7 = 8'b0000_1101;  // 3
            4  : seg_7 = 8'b1001_1001;  // 4
            5  : seg_7 = 8'b0100_1001;  // 5
            6  : seg_7 = 8'b0100_0001;  // 6
            7  : seg_7 = 8'b0001_1111;  // 7
            8  : seg_7 = 8'b0000_0001;  // 8
            9  : seg_7 = 8'b0000_1001;  // 9
            10 : seg_7 = 8'b0000_0101;  // A
            11 : seg_7 = 8'b1100_0001;  // b
            12 : seg_7 = 8'b0110_0011;  // C
            13 : seg_7 = 8'b1000_0101;  // d
            14 : seg_7 = 8'b0110_0001;  // E
            15 : seg_7 = 8'b0111_0001;  // F
        endcase 
    end
    
endmodule

// Edge detector 
module edge_detector_n (
    input clk, reset_p,
    input cp,
    output n_edge, p_edge );
    
    reg flip_flop_current, flip_flop_old;
    
    always @(posedge clk or posedge reset_p) begin
         if(reset_p) begin
            flip_flop_current <= 0;
            flip_flop_old <= 0;
         end
         else begin
            flip_flop_current <= cp;
            flip_flop_old <= flip_flop_current;
         end
    end
    
    assign p_edge = ({flip_flop_current, flip_flop_old} == 2'b10)? 1 : 0;
    assign n_edge = ({flip_flop_current, flip_flop_old} == 2'b01)? 1 : 0;
    
endmodule

 

 

 

 

 

3. 구현 영상