이것은 FPGAs의 resets에 대한 시리즈 의 세 번째이자 마지막 페이지입니다. 이 책보다 먼저 첫 두 개를 읽는 것이 좋습니다.
개요
resets를 생성하기 위해 적절한 logic을 설정하는 데 시간을 들이는 것은 항상 좋은 생각입니다. design 에 명백한 문제가 없더라도 design 에서 이 단계를 건너뛰면 큰 피해를 입을 수 있습니다. 나중에 logic이 제대로 초기화되지 않았기 때문이라는 사실을 깨닫지 못한 채 불안정한 문제를 해결하기 위해 며칠을 보낼 수 있습니다. 시간이 지남에 따라 이와 같은 문제를 해결하려는 시도에서 design은 문제의 근본을 이해하지 못한 채 만들어진 추악한 해결 방법을 축적합니다. 이 페이지 에서 이상한 불안정성에 대해 자세히 알아보세요.
프로젝트 시작부터 reset signals를 생각하고 설계하는 것도 새로운 기능이 추가됨에 따라 제대로 성장하도록 보장하기 위해 중요합니다. FPGA 프로젝트가 처음부터 시작되면 핵심 기능이 먼저 구현되는 경우가 많고, 시간이 지남에 따라 기능이 추가됩니다. 다른 modules 에는 종종 별도의 clocks 와 resets가 필요하기 때문에 각 부분에 대해 별도로 빠르게 무언가를 적어두는 함정에 빠지기 쉽습니다. 이는 종종 프로젝트가 진행됨에 따라 점점 더 혼란스러워집니다.
resets 및 clocks를 포함하기 위해 첫날부터 올바르게 작성된 중앙 module을 사용하면 지저분한 프로젝트를 피하는 것이 더 쉽습니다. 그리고 아래에서 추가로 설명하는 것처럼 reset controller 와 clock resources (필요한 경우PLLs 와 clock buffers )는 서로 영향을 미치므로 동일한 module 에 두는 것이 좋습니다. 나는 보통 이 module 에 clkrst.v라는 이름을 붙입니다.
그러나 일부 IP cores, 하위 시스템 또는 design blocks가 자체 resets 및 clocks그룹을 생성할 수 있으므로 이 모든 것을 하나의 module에 집중시키는 것은 종종 불가능합니다.이 경우 서로 다른 소스에서 도착하는 resets에 대한 요청에 대해 무엇이 무엇에 따라 달라지는지, 전체 시스템이 어떻게 반응해야 하는지 신중하게 생각해야 합니다.예를 들어, PCIe block 에 대한 reset은 거의 항상 bus 자체에서 도착하고 block은 이 block에 연결된 logic 에서 사용할 reset signal을 생성합니다.이와 같은 상황에서는 예를 들어 PCIe bus 에서 reset이 도착하는 경우(전혀 응답하지 않을 가능성 포함) 일반적으로 시스템이 어떻게 응답해야 하는지 고려해야 합니다.
각 프로젝트에는 고유한 스토리가 있기 때문에 모든 경우에 대한 단일 솔루션은 없습니다. 이 페이지는 개념을 설명하고 자신의 reset controller를 위한 빌딩 블록으로 사용할 수 있는 아이디어와 코드 조각을 제안합니다. 그러나 이러한 코드 조각은 프로젝트에 직접 잘라내어 붙여넣기를 위한 것이 아니라 데모로 처리해야 합니다.
단순화를 위해 시스템의 다른 block은 clocks 나 resets를 생성하지 않는다고 가정하지만 controller를 일반적인 경우로 확장하는 것은 매우 간단합니다.
reset state machine
대부분의 designs에는 재설정이 필요한 두 가지 주요 시나리오가 있습니다.
- FPGA의 powerup 와 bitstream configuration바로 다음에 깨끗한 출발을 보장하기 위해.
- pushbutton을 누르거나 processor 또는 컴퓨터의 명령에 의해 reset이 명시적으로 요청되는 경우.
또한 watchdog timers가 만료되거나 다른 방법으로 주요 시스템 오류가 감지되면 재설정이 필요할 수 있습니다.
이러한 모든 시나리오에 대한 예상되는 응답은 기본적으로 다시 시작하는 것입니다. 어떤 일이 잘못되었더라도 바로잡을 수 있도록 하는 종류의 것입니다. 이것은 state machine이 시작된 이유에 관계없이 일관되고 반복 가능한 reset sequence를 보장하는 일종의 state machine에서 가장 잘 수행되는 경우가 많습니다.
그렇게 말했지만, 로컬하고 반복적인 재설정이 합리적인 시나리오가 있습니다. 예를 들어, video image frames를 처리하는 logic은 각 frame이 시작되기 전에 재설정될 수 있습니다. 이는 일반적으로 가벼운 메커니즘을 필요로 하며, 로컬 synchronous reset이 활성화될 때 여러 registers 에 초기 값을 할당하는 것으로 귀결됩니다. 이는 다른 것과 같은 재설정 메커니즘이며, 종종 견고한 작동을 보장하는 깨끗하고 간단한 방법입니다.
하지만 이 가능성에 대해 더 이상 추가할 내용이 없으므로 이 페이지의 나머지 부분은 FPGA전체를 포괄하는 기본 reset에 초점을 맞춥니다.
불안정한 clocks 와 reset의 필요성
clocks를 생성하기 위해 FPGA의 자체 PLLs를 사용하는 것은 매우 일반적이며 일반적으로 권장됩니다. 그러나 이러한 PLLs는 일반적으로 FPGA 의 다른 모든 logic이 활성화되는 것과 동시에 작동을 시작합니다. 결과적으로 이러한 clocks 에 의존하는 logic은 불안정한 clock와 함께 공급되며, 이는 정상보다 훨씬 높은 주파수를 가질 수 있습니다.
이 경우 해당 logic paths 의 timing은 보장되지 않습니다. 따라서 PLLs 에 의해 생성된 clocks 에 의존하는 모든 logic은 PLL이 잠길 때까지 timing constraints를 달성하지 못한 것처럼 처리해야 합니다.
적절하고 일반적인 솔루션은 관련 PLL이 잠길 때까지 이러한 모든 logic을 reset 에 유지하는 것입니다. 또는 이 logic은 PLL이 잠길 때까지 clock을 무시하도록 설정할 수 있습니다. 예를 들어 flip-flops의 Clock Enable input (CE)가 비활성화되었는지 확인합니다.
외부 clock이 FPGA의 pin 에서 logic elements로 직접 연결된 경우 문제는 clock generator (일반적으로 PLL)가 FPGA 에 bitstream이 로드된 것보다 더 빨리 잠겼는지 여부입니다. 이것에 대해 확신하는 것이 항상 쉬운 것은 아닙니다.
결과적으로, 대부분의 designs에서 많은 synchronous elements를 재설정해야 합니다. 또는 보다 정확하게는 불안정한 clock로 인해 reset이 필요한지 여부에 대해 이러한 elements를 세 그룹으로 나눌 수 있습니다.
- garbage data가 포함되어 있을 수 있으며 문제가 되지 않습니다.
- clock이 불안정한 한(예: clock enable덕분에) 무시하도록 보장된 것입니다.
- 리셋이 필요한 것들.
일부 FPGAs는 configuration 프로세스(즉, bitstream을 로드하고 FPGA를 초기화하는 프로세스)를 설정할 수 있으므로 모든 PLLs가 잠길 때까지 FPGA의 웨이크업이 지연된다는 점을 언급할 가치가 있습니다. 이것은 이 문제를 해결하는 방법일 수 있습니다. 이 솔루션의 단점은 외부 clock에 문제가 있는 경우 FPGA가 전혀 시작되지 않는다는 것입니다. 이와 같은 상황은 매우 혼란스러울 수 있습니다.
간단한 state machine
기본적인 시작 또는 다시 시작은 매우 드문 이벤트이므로 필요한 것보다 몇 마이크로초가 더 걸리더라도 문제가 되지 않습니다. 대부분의 경우 최대 100 ms 정도면 충분하며 이를 활용할 수 있습니다. 따라서 일반 counter는 일련의 이벤트를 구현하는 간단한 방법입니다.
가장 간단한 형태로 요약하면 다음과 같습니다.
reg [4:0] reset_count;
reg rst_src_pll, rst_src_shreg, rst_src_debounce;
reg clear_counter;
reg master_reset;
initial reset_count = 0;
initial master_reset = 1;
initial clear_counter = 1;
always @(posedge wakeup_clk)
begin
clear_counter <= rst_src_pll || rst_src_shreg || rst_src_debounce;
master_reset <= (reset_count != 31);
if (clear_counter)
reset_count <= 0;
else if (reset_count != 31)
reset_count <= reset_count + 1;
end
@rst_src_pll, @rst_src_shreg 및 @rst_src_debounce는 시스템을 재설정하는 다른 이유를 나타냅니다. 이 registers는 다른 logic에 의해 값이 주어집니다. 이러한 logic의 몇 가지 예를 살펴보겠습니다. 하지만 지금 중요한 점은 이러한 registers가 @wakeup_clk 와 동기화되어 있으므로 clock domain crossing이 필요하지 않다는 것입니다.
@clear_counter는 reset에 대한 이러한 이유 중 logic OR 입니다. 이 register는 @reset_count를 0으로 변경합니다. 그렇지 않으면 이 counter는 0에서 31(이 예에서)로 이동한 후 멈춥니다.
마지막으로 @reset_count가 계산을 마치지 않는 한 @master_reset은 활성화됩니다. 이것은 reset state machine의 가장 단순한 형태이며, 31까지 세는 것 또한 상당히 겸손합니다.
따라서 @rst_src_N signals 중 하나라도 활성화되면, clock cycle이 하나라도 활성화되지만, synchronous reset은 최대 31개의 clock cycles에 대해 활성화됩니다.
긴 reset pulse에는 두 가지 이점이 있습니다. 첫째, 관련 @rst_src_N이 무작위로 켜지고 꺼지는 경우(예: PLL lock detectors, push buttons가 흔들리거나 resets를 여러 번 요청하는 소프트웨어) 이러한 다중 활성화는 가시적인 synchronous reset로 전파되지 않습니다. 이러한 다중 활성화는 일반적으로 무해하지만 output pins의 불필요한 활동을 초래할 수 있습니다. 그러한 활동은 부정적인 영향을 미칠 수 있습니다. 예를 들어 전자 제품을 테스트하는 사람이 무언가 잘못되었다고 생각하도록 혼동을 줄 수 있습니다.
그런 의미에서 31 clock cycles 의 예는 상당히 미니멀합니다. 이러한 지연이 허용된다면 10-100 ms에 해당하는 값으로 계산하는 것이 훨씬 좋습니다. 이렇게 하면 reset controller에 의해 그보다 짧은 모든 흔들림이 숨겨집니다.
긴 reset pulse 의 두 번째 이유는 원본 synchronous reset을 로컬 복사본으로 배포하는 데(앞서 설명한 대로) 하나의 clock cycle지연이 포함되기 때문입니다. logic 전체에 reset을 배포하기 위해 신호를 여러 번 복사해야 하는 경우 전체 지연이 길어질 뿐만 아니라 고르지 않을 수도 있습니다. 긴 reset pulse는 특정 시점에서 모든 logic이 활성 synchronous reset에 노출되도록 합니다. reset 의 비활성화도 고르지 않게 되기 때문에 reset path에서 고르지 못한 지연을 갖는 것은 여전히 나쁜 생각이지만 때로는 문제가 없습니다. 이 문제에서 reset pulse 용 31 clock cycles는 필요한 것보다 훨씬 길지만 아프지는 않습니다.
다른 clock domains용Resets
@master_reset은 일반 synchronous reset이 지만 application logic에서 사용하는 clocks 와 다를 수 있는 clock 와 동기화됩니다. 다른 clocks에 대해 synchronous resets를 생성하려면 각 clock에 대해 다음과 같은 작업을 수행해야 합니다.
reg reset_clk_pre1, reset_clk_pre2;
reg reset reset_clk;
always @(posedge clk)
begin
reset_clk <= reset_clk_pre2;
reset_clk_pre2 <= reset_clk_pre1;
reset_clk_pre1 <= master_reset;
end
이것은 @reset_clk을 생산하는 3단계의 일반 clock domain crossing 입니다. 이 신호는 @clk와 함께 가는 synchronous reset 입니다. 실제로는 2단계면 충분하지만 중요한 신호이므로 추가로 register를 추가하여 안전을 위해 탐닉했습니다.
reset controller의 clock
원칙적으로 @wakeup_clk로 사용할 수 있는 clocks 에는 세 가지 종류가 있습니다. 즉, reset state machine의 경우:
- FPGA외부에서 생성된 clock 로, FPGA가 깨어났을 때 안정적인 것으로 알려져 있습니다.
- FPGA의 PLL 에 의해 생성된 clock이 므로 FPGA가 깨어날 때 준비가 되지 않을 것으로 예상됩니다.
- 일부 FPGAs에서는 FPGA 자체에서 ring oscillator 에 의해 생성된 configuration clock을 사용할 수 있습니다.
첫 번째 옵션은 작업하기 가장 쉽습니다. FPGA의 PLLs를 구동하는 reference clock이 거의 항상 있기 때문에 이 reference clock을 종종 wakeup clock로 직접 사용할 수 있습니다. 그러나 FPGA가 깨어날 때 clock이 실제로 안정적인지 확인하는 것이 중요합니다. 즉, FPGA가 bitstream을 로드하는 데 걸리는 시간이 외부 oscillator가 유효한 clock을 생성하는 데 걸리는 시간보다 길어야 합니다. 이는 일반적으로 datasheets을 볼 때 큰 여백이 있는 경우입니다. 그러나 board의 powerup sequence가 적절하게 계획되지 않은 경우 oscillator 의 supply voltage가 올바른 수준에 도달하기 훨씬 전에 FPGA가 bitstream을 읽도록 승인을 받을 수 있습니다.
두 번째 옵션은 FPGA 자체에서 PLL 로 생성된 clock을 사용하는 것입니다. 명백한 장점은 이 clock이 application logic 에도 사용될 수 있으므로 clock resources 와 power모두에서 더 효율적이라는 것입니다. 이 선택은 clock이 안정될 때까지 reset state machine을 초기 상태로 유지해야 하며, 다음과 같은 방법으로 수행할 수 있습니다.
reg rst_src_pll;
reg rst_src_pll_pre;
initial rst_src_pll = 1;
initial rst_src_pll_pre = 1;
always @(posedge wakeup_clk)
begin
rst_src_pll <= rst_src_pll_pre;
rst_src_pll_pre <= !pll_locked;
end
@pll_locked는 @wakeup_clk (active high)를 생성하는 PLL 의 lock detector output 입니다. 이 신호는 비동기식이므로 먼저 @wakeup_clk와 동기화한 다음 위에 표시된 것처럼 @clear_counter를 활성화하는 이유 중 하나로 사용됩니다(예: @rst_src_pll).
이 옵션의 또 다른 장점은 reference clock이 일시적으로 불안정하거나 없는 경우(특히 board전원을 켠 후) lock detector 도 불안정할 가능성이 크다는 것입니다. 따라서 @master_reset을 비활성화하기 전에 @reset_count가 큰 숫자(확실히 31보다 훨씬 높음)로 계산되면 reference clock이 작동하기에 적합할 때까지 FPGA가 reset 에 단단히 남아 있을 가능성이 있습니다. 그러나 이는 신뢰할 수 없습니다.
어쨌든 @wakeup_clk이 PLL 의 output 라는 사실은 반드시 이 clock이 안정화되기 전에 logic을 공급한다는 것을 의미합니다. 따라서 해당 기간 동안 state machine이 제대로 작동하는지 확실하지 않습니다. 어느 시점에서 clock이 충분히 좋아지고 적절한 resets가 생성되기 때문에 이것이 중요하지 않다고 주장하는 것이 가능합니다. reset이후에 모든 것이 과거에 남아 있다면 그 이전에 무슨 일이 일어났는지 누가 신경을 쓰겠습니까?
보다 엄격한 접근 방식은 wakeup clock이 잠길 때까지 resets를 꾸준히 활성 상태로 유지해야 하므로 FPGA가 bitstream configuration직후 이상하게 작동하지 않습니다. 이를 위해서는 이 clock와 함께 매우 간단한 logic 만 사용하는 데 주의를 기울여야 합니다. 즉, logic은 clock 의 주파수가 예상보다 높은 경우 크게 실패하지 않는 종류여야 합니다.
@wakeup_clk이 일시적으로 너무 높은 주파수를 갖는 경우 어떤 일이 발생하는지 분석하려면 @reset_count가 vector인 reset state machine 의 유일한 register 라는 점에 유의하십시오. 이는 다른 모든 flip-flops가 timing위반으로 인해 최악의 경우 계산된 "next value" 하나의 clock을 너무 늦게 샘플링할 수 있음을 의미합니다. 특히 @pll_locked는 로우이고 PLL은 잠겨 있지 않기 때문에 @rst_src_pll은 곧 꾸준히 하이가 되고, 따라서 @clear_counter 도 꾸준히 하이가 된다. flip-flop 의 D input (다음 value)가 변경되지 않으면 clock이 얼마나 빠른지는 중요하지 않습니다.
따라서 가능한 유일한 문제는 @reset_count에 있는데, 계산된 next value가 @clear_counter때문에 0으로 안정적으로 유지될 때까지 잘못 계산될 수 있습니다. 예를 들어, 현재 값이 3(binary 011)인 경우 다음에 계산된 값은 4(binary 100)입니다. 하지만 두 개의 LSBs가 timing때문에 샘플링되지 않고 세 번째 bit이 그럼에도 샘플링되면 counter의 값은 대신 7(111 binary)로 점프할 수 있습니다.
이를 방지하기 위해 @pll_locked 에서 @clear_counter 까지의 registers 체인의 초기 값은 모두 @reset_count를 0으로 유지하기 위해 할당됩니다. 따라서 @pll_locked가 @wakeup_clk이 안정될 때까지 계속 낮은 상태로 유지되면 @reset_count는 0에서 벗어나지 않고 @master_reset은 꾸준히 활성 상태를 유지합니다.
마지막 옵션은 FPGA의 ring oscillator를 reset controller용으로 사용하려면: 제가 직접 해보지 않아서 얼마나 좋은 아이디어인지는 잘 모르겠습니다. 그러나 다른 옵션이 없는 사람을 구하는 경우 Xilinx의 FPGAs를 사용하여 수행하는 방법은 다음과 같습니다. 에 대한 FPGA 의 Configuration User Guide 에서 STARTUPE2 (또는 이와 유사한 것)라는 primitive를 찾습니다. FPGA 자체에 있는 부정확한 ring oscillator 의 clock 인 CFGMCLK라는 output이 있어야 합니다. 주파수는 약 50-65 MHz입니다. 이 clock은 FPGA가 깨어났을 때 안정적임을 보장하며 timing constraint를 상당히 높은 주파수(예: 100 MHz)로 설정합니다.
그러나 이것은 정말로 다른 선택이 없다면 내가 할 일입니다. 예를 들어 FPGA가 깨어났을 때 외부 reference clock이 안정적이지 않으면 logic에서 추가 지연을 구현해야 합니다.
PLLs재설정
일반적으로 reset sequence의 일부로 PLLs를 재설정하는 것이 좋습니다. 이렇게 하면 reference clock이 유효한 것으로 알려진 경우 재설정됩니다. 또한 reset이 사용자에 의해 시작된 경우(예: reset pushbutton누르기) 이는 제대로 잠기지 않은 PLL로 인한 문제에 대한 응답일 수 있습니다. 발생해서는 안되지만 발생하는 경우를 대비하여.
@clear_counter는 PLL이 잠기지 않는 즉시 활성화되기 때문에 PLL을 재설정하는 데 사용할 수 없습니다. 사용되었다면 PLL은 reset state에 남아 결코 잠기지 않으며 reset은 결코 해제되지 않습니다. 같은 이유로 PLLs의 resets는 @reset_count에서 파생될 수 없습니다. 모든 PLLs가 잠겨 있는 경우를 제외하고는 0으로 유지됩니다.
해결책은 @clear_counter와 유사한 PLL용으로 별도의 reset register를 만드는 것입니다. 따라서 위의 표기법에서 잠겨 있지 않은 PLLs는 @rst_src_pll에 반영되며 다음과 같이 요약됩니다.
reg clear_counter;
reg reset_plls;
initial clear_counter = 1;
initial reset_plls = 1;
assign reset_sources = rst_src_shreg || rst_src_debounce;
always @(posedge wakeup_clk)
begin
clear_counter <= rst_src_pll || reset_sources;
reset_plls <= reset_sources;
[ ... ]
이 코드 조각에서 @rst_src_pll은 @reset_sources에서 제외되었으며 @clear_counter에만 사용됩니다. 결과적으로 PLLs는 잠기지 않는 결과를 제외하고 전체 FPGA와 함께 재설정됩니다.
@reset_sources가 무작위로 낮아지고 높아지면 여기에 표시된 코드에 따라 @reset_plls 도 마찬가지입니다. reset이 미친 듯이 켜졌다 꺼질 때 PLLs 에 나쁜 일이 일어나지 않기 때문에 이것은 일반적으로 무해합니다. 그럼에도 불구하고 다음에 설명하는 것처럼 이것을 피하는 방법도 있습니다.
더 복잡한 시작 시퀀스
일반 counter (@reset_count)를 state variable 로 사용하면 더 복잡한 startup sequences를 쉽게 구현할 수 있습니다. 예를 들어, clocks가 꺼진 상태에서 활성 상태인 적절한 asynchronous resets를 생성하는 것은 매우 간단합니다. clocks가 꺼지고 resets가 활성화되는 시간 슬롯을 정의하는 간단한 logic expressions 로 완료됩니다.
따라서 이 일반 counter 방법은 프로젝트가 시작될 때 reset state machine 에서 간단한 요구 사항이 있는 것처럼 보이는 designs 의 경우에도 좋은 출발점입니다. 나중에 복잡한 startup sequence가 필요하다는 것이 밝혀지면 이 목표를 달성하기 위해 기존 logic을 쉽게 확장할 수 있습니다.
어쨌든 startup sequence 계획은 sequence 의 각 단계가 적용되는 기간을 정의하는 것으로 요약됩니다. 이러한 각 기간은 @reset_count가 가져야 하는 값 범위로 변환됩니다.
예를 들어, design 에 두 개 이상의 관련 없는 clocks가 있는 경우 위에 표시된 대로 각 clock domain 에 대해 reset signals를 만들 수 있습니다("다른 clock domains에 대한Resets " 참조). 하지만 해당 방법을 채택하면 각 clock domains가 효과적으로 무작위 순서로 reset 에서 나옵니다. 이는 일반적으로 문제가 되지 않지만 문제가 되는 경우 각 clock domain은 @reset_count의 진행 상황에 따라 정의된 시간에 reset을 비활성화할 수 있습니다.
counter를 두 개 이상 구현하는 것도 가능합니다. 이는 reset sequence가 계속하기 전에 특정 조건이 충족될 때까지 기다려야 할 때 유용합니다. 예를 들어, reset sequence가 PLLs를 재설정하고, 잠길 때까지 기다린 다음 reset sequence를 계속 진행하는 경우, 모든 PLLs가 잠길 때까지 0으로 유지되는 하나의 counter를 갖는 것이 합리적입니다. 두 번째 counter는 첫 번째 counter가 계산을 마칠 때까지 0으로 유지됩니다.
PLL이 lock을 잃는 경우 PLLs 자체는 재설정되지 않지만 종속된 모든 항목은 재설정됩니다. lock을 잃는 PLL은 대부분의 designs에서 심각한 결함이기 때문에 이것은 원하는 동작이 아닐 수 있습니다. lock이 손실된 경우 전체 reset을 요청하려면 @reset_sources를 얻기 위해 OR 와 함께 가져온 신호에 아래 정의된 대로 @pll_restart를 추가하십시오.
assign pll_restart = rst_src_pll && !master_reset;
이것은 단순히 말합니다. master reset이 비활성화된 후 PLL이 잠금 해제된 경우 PLLs를 포함하여 모든 것을 다시 재설정하십시오. 이것이 작동하려면 reset count가 lock detectors의 가능한 흔들림을 견딜 수 있을 만큼 충분히 길어야 합니다. 즉, reset count는 PLL이 아직 잠겨 있지 않더라도 PLL의 lock detector가 하이일 수 있는 시간보다 길어야 합니다. 이것은 PLL이 lock을 획득하는 데 걸리는 시간과 혼동하지 마십시오. 일부 lock detectors는 전혀 흔들리지 않으며 이러한 흔들림은 PLL의 lock time ( datasheet에 지정된 대로)보다 훨씬 짧을 가능성이 큽니다.
wakeup shift register
약간의 overkill일 수도 있지만 일반적으로 내 designs에 이런 종류의 wakeup shift register를 추가합니다.
reg [15:0] wakeup_shift;
reg rst_src_shreg;
initial rst_src_shreg = 1;
initial wakeup_shift = 0;
always @(posedge wakeup_clk)
begin
rst_src_shreg <= !wakeup_shift[15];
wakeup_shift <= { wakeup_shift, 1'b1 };
end
대부분의 FPGAs는 @wakeup_shift를 shift register primitive로 구현하여 LUT와 동일한 것을 소모하기 때문에 리소스가 저렴하고 powerup중에 reset이 실행되도록 하는 또 다른 메커니즘을 제공합니다. 이는 PLLs가 없는 design 에서 필요한데, 그 외에는 @clear_counter를 활성화할 것이 없기 때문입니다. 하지만 PLLs가 있더라도 FPGA가 깨어날 때 이미 잠겨 있을 가능성이 있는데, 이는 일부 FPGAs에서 bitstream configuration 에 대한 가능한 옵션입니다.
따라서 어쨌든 이것은 권장되는 추가 기능입니다. 죄송합니다보다 더 안전.
외부 reset button
Reset buttons는 매우 일반적입니다. 그들이 하는 일은 design 마다 다릅니다. 한 가지 가능성은 사용자가 "reset"로 간주하는 button이 bitstream을 FPGA에 로드하는 프로세스를 시작하는 FPGA pin 에 연결되어 있다는 것입니다. embedded processor가 있는 FPGAs 의 processor의 reset pin에도 연결할 수 있습니다.
그리고 이 reset button은 FPGA logic을 재설정하기 위해 FPGA의 일반 I/O pin 에 연결할 수 있습니다. 이 경우 @clear_counter를 활성화해야 하는 또 다른 이유입니다.
@reset_count가 10 ms 또는 그 이상에 해당하는 숫자로 계산되면 흔들림이 counter 자체에 의해 흡수되므로 input pin의 신호 debounce가 필요하지 않습니다. 이 경우 다음으로 충분합니다.
reg rst_src_debounce;
reg rst_src_debounce_pre;
initial rst_src_debounce = 1;
initial rst_src_debounce_pre = 1;
always @(posedge wakeup_clk)
begin
rst_src_debounce <= rst_src_debounce_pre;
rst_src_debounce_pre <= reset_button_pin;
end
그러나 counter가 빠르게 완료되면(위의 예와 같이 31에 도달) pushbutton 에는 debouncing이 필요합니다. 이를 수행하는 방법에는 여러 가지가 있습니다. 예를 들면 다음과 같습니다.
reg [17:0] debounce_count = 0;
reg reset_button_d, reset_button_d2, reset_button_d3;
wire debounce_reached = (debounce_count == 250000);
initial debounce_count = 0;
initial rst_src_debounce = 1;
always @(posedge wakeup_clk)
begin
reset_button_d3 <= reset_button_d2;
reset_button_d2 <= reset_button_d;
reset_button_d <= reset_button_pin;
if (reset_button_d2 != reset_button_d3)
debounce_count <= 0;
else if (!debounce_reached)
debounce_count <= debounce_count + 1;
if (debounce_reached)
rst_src_debounce <= reset_button_d3;
end
이것은 비교적 엄격한 debouncer로, 시끄러운 input signals와 잘 작동하지 않습니다. 이것은 필요에 따라 장점이거나 단점입니다.
이 코드 예제는 25 MHz clock용으로 작성되었습니다. 10 ms동안 @reset_button_pin이 동일한 값을 가졌다면 @reset_button_pin 의 값은 @rst_src_debounce 로 복사됩니다. @reset_button_d3이 값을 변경할 때와 동일한 clock cycle 에서 @debounce_count가 0으로 변경된다는 점에 유의하십시오. 따라서 @reset_button_d3이 값을 변경하면 @rst_src_debounce 에 즉시 복사되지 않고 오랫동안 동일한 값을 유지한 후에만 복사됩니다.
요약
FPGA의 초기화를 설계할 때 고려해야 할 사항이 많이 있습니다. 이 페이지에서는 몇 가지 개념과 아이디어를 제시했지만 실제 작업은 작업을 시작하는 데 필요한 이벤트를 올바르게 인식하는 것임을 명심하는 것이 중요합니다. logic을 작동 상태로 안정적으로 가져오려면 이러한 각 이벤트에 대한 올바른 응답을 정의하는 것도 중요합니다.