RTL Design/Verilog RTL 설계
Verilog RTL 설계(7월 16일 - 3, Basys3 입문)
유로 청년
2024. 7. 18. 08:42
1. Counter의 비트 수 (크기)와 분주비의 상관 관계
- Counter의 크기는 N bit 를 갖는다면 Counter는 0 ~ 2^N-1 까지 Counting이 가능하다.
- ex) Counter가 21bit 크기를 갖는다면 0 ~ 2^21 -1까지 Counting이 가능하다.
- 따라서 Basys3의 기본 클럭 펄스의 주기는 10ns를 갖기 때문에 10bit Counter으로 분주화하게 되면 10ns * 1024 = 10240ns = 10us 을 주기를 갖는 새로운 펄스파를 생성시킬 수 있다.
=> Basys3의 기본 Clock Pulse의 주기는 10ns를 갖는다.
=> 10bit Counter로 1024분주하면 10us 주기를 갖는 펄스파형을 생성시킬 수 있다,
=> 21bit Counter로 2^21분주하면 10ns * 2,097,152 = 20.97152ms 주기를 갖는 펄스파형을 생성시킬 수 있다. - 여기에 Edge Detector를 설치하게 되면 일정한 주기를 갖는 One Cycle Pulse 를 얻을 수 있다.
2. 스위치 상단에 있는 LED를 일정한 주기를 갖고 Shift 시키기.
- 하나씩 하나씩 처음부터 설계해보자.
- 다음 질문에 대해서 하나씩 생각해보자.
Q) 몇 초 마다 Shift 할 것이며, 10ns 보다 긴 주기로 Shift한다면 어떻게 할 것인가?
Q) LED Shift를 반복적으로 어떻게 할 것인가?
2.1. 몇 초 마다 Shift 할 것인가?
- Shift 주기가 짧을 경우, Shift가 너무 빨라 LED의 변화를 눈으로 확인할 수 없다.
- 따라서 LED Shift를 감지하기 위해 넉넉하게 10ms마다 Shift하게끔 할 것이다.
2.2. 기본 클럭 주파수는 10ns인데, 어떻게 주기가 10ms인 펄스파를 만들어 줄 것인가?
- Counter와 Negative edge detector를 사용하여 Prescaler 방식을 이용하는 것이다.
- 10ms / 10ns = 1,000,000이기 때문에 Counter는 최소 1,000,000이상을 Counting 할 수 있어야 한다.
따라서 Counter의 크기는 최소 1,000,000이상 카운트 할 수 있는 20bit를 가져야 한다. - 10ms를 주기로 Shift하기 위해서는 펄스파형이 아닌 10ms를 주기로 10ns 동안 활성화 되는 One cycle pulse가 필요하다.
2.3. LED Shift를 반복적으로 어떻게 할 것인가?
- LED Shift는 Shift 연산을 통해 수행이 가능하지만, 무한 반복을 수행해야 하기 때문에 (무한 반복 + Shift 연산)을 수행할 수 있는 Ring Counter를 사용하는 것이 효율적일 것이다.
- 10ms를 주기로 Shifting 해야 하기 때문에 Ring Counter에 20bit Counter를 추가하여 counter[19] 비트 값이 0 → 1로 변화하는 순간을 Edge detector로 감지하도록 한다.
- counter[19] 비트 값이 0 → 1로 변화하는 순간을 Edge detector는 One Cycle Pulse를 발생시킨다.
- 이때, 발생시키는 One Cycle Pulse는 10ms 주기를 갖는다.
2.4. 10ns 주기를 갖는 Clock Pulse를 5,000,000 분주시켜 50ms 주기를 갖는 Pulse 를 생성
< Source , Edge Detector >
module edge_detector_n (
input clk, reset_p,
input cp,
output n_dege, p_edge );
reg flip_flop_current, flip_flop_old;
always @(negedge 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
< Source, Ring Counter of Shifting LED >
// Ring Counter
module ring_counter_LED (
input clk, reset_p,
output reg [15:0] led);
reg [19:0] counter;
always @(posedge clk or posedge reset_p)
if (reset_p) counter <= 0;
else counter <= counter + 1;
// Detect negative edge of counter
wire counter_nedge;
edge_detector_n detector_nedge(.clk(clk), .reset_p(reset_p), .cp(counter[19]), .p_edge(counter_nedge));
// Shifting
always @(posedge clk or posedge reset_p) begin
if(reset_p) led = 16'b0000_0000_0000_0001;
else if(counter_nedge) begin
if(led == 16'b1000_0000_0000_0000) led = 16'b0000_0000_0000_0001;
else led = {led[14:0], 1'b0};
end
end
endmodule
< Basys3 >
- Basys3의 LED는 10ms 주기로 Left Shifting 하게 된다.