Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- vivado
- java
- structural modeling
- behavioral modeling
- i2c 통신
- ring counter
- stop watch
- test bench
- Linked List
- pwm
- uart 통신
- Algorithm
- Recursion
- dataflow modeling
- DHT11
- half adder
- prescaling
- LED
- gpio
- ATMEGA128A
- Edge Detector
- atmega 128a
- BASYS3
- soc 설계
- D Flip Flop
- KEYPAD
- Pspice
- FND
- hc-sr04
- verilog
Archives
- Today
- Total
거북이처럼 천천히
Verilog RTL 설계(7월 15일 - 2, Register, TestBench) 본문
1. Register는 D Flip Flop을 기반으로 구현 할 수 있다.
- D Flip Flop은 1bit 데이터를 저장할 수 있는 기억 소자이다.
- 따라서 D Flip Flop을 병렬로 여러 개를 이어붙어 Register를 생성할 수 있다.
- 아래 코드는 8개의 D Flop Flop을 병렬적으로 이어 붙어 8bit register를 생성할 수 있다.
< Source, 8bit register >
// 8bit register
module Register_8bit_implemented_with_D_Flip_Flop_Positive(
input clk, enable, reset_p,
input [7:0] d,
output reg [7:0] q );
always @(posedge clk or posedge reset_p) begin
if(reset_p) q = 0;
else if(enable) q =d;
end
endmodule
< RTL analysis >
2. Register은 다양한 입력, 출력 구조를 갖으며, 이에 따라 종류를 구분한다.
- Register는 아래와 같이 다양한 입출력 구조를 갖으며, 입출력 구조에 따라 Register를 구분한다.
- 직렬 입력 - 직렬 출력 (SISO) : 송신기 + 수신기를 동시에 사용하고자 할 때, 사용
- 직렬 입력 - 병렬 출력 (SIPO) : DEMUX 구조를 갖으며, 수신기를 구현하고자 할 때, 사용
- 병렬 입력 - 직렬 출력 (PISO) : MUX 구조를 갖으며, 송신기를 구현하고자 할 때, 사용
- 병렬 입력 - 병렬 출력 (PIPO) : 고속으로 데이터를 처리하고자 할 때, 사용
3. SISO Shift Register ( Series Input Series Output )
- 직렬 형태로 입력을 받고, 레지스터에 저장된 데이터를 직렬로 출력하는 레지스터
- clk (Clock Pulse)의 한 주기마다 레지스터내에서 Shift시켜 데이터를 저장하거나 출력한다.
- SISO Shift Register는 아래와 같은 블록도와 Timing diagram을 갖는다.
3.1. Vivado 를 통해 SISO Shift Register를 구현하기
< Source, Non-blocking, 잘못된 예시>
// SISO Shift Register
// Series Input, Series Output
module shift_register_SISO_Non_blocking (
input clk, enable, reset_p,
input d, output q);
reg [3:0] siso_reg;
always @(posedge clk or reset_p) begin
if(reset_p) siso_reg = 4'b0000;
else if(enable) begin
siso_reg[3] = d;
siso_reg[2] = siso_reg[3];
siso_reg[1] = siso_reg[2];
siso_reg[0] = siso_reg[1];
end
end
assign q = siso_reg[0];
endmodule
- 위 코드는 Non-blocking으로 구현하였다.
- 따라서 always 문내에서 siso_reg 변수에 데이터를 저장하는 과정에서 순차적으로 진행되기 때문에 siso_reg [0] ~ siso_reg [3]는 모두 동일한 값을 갖는다.
- 따라서 회로적으로나 논리적으로 심각한 오류를 발생시킨다.
< Source, Non-blocking >
// SISO Shift Register.
module SISO_Shift_Register_Insert_Negative (
input clk, enable, reset_p,
input d,
output reg q );
reg [3:0] siso_reg;
always @(negedge clk or posedge reset_p) begin
if(reset_p) q = 0;
else if(enable) begin
siso_reg[3] = siso_reg[2];
siso_reg[2] = siso_reg[1];
siso_reg[1] = siso_reg[0];
siso_reg[0] = d;
end
end
endmodule
< Source, Non-blocking, Shift Operator 대신에 결합 연산자를 사용하여 구현 >
// SISO Shift Register.
// MSB 자리에 입력 값,d을 append하고,
// LSB 자리의 값을 출력값으로 내보낸다.
module SISO_Shift_Register_Positive(
input clk, enable, reset_p,
input d,
output reg q );
reg [3:0] siso_reg;
always @(posedge clk or posedge reset_p) begin
if(reset_p) siso_reg <= 0;
else if(enable) siso_reg <= {d, siso_reg[3:1]};
end
assign q = siso_reg[0];
endmodule
< Source, Non-blocking, Shift Operator 대신에 결합 연산자를 사용하여 구현 + Parameter 사용 >
// SISO Shift Register by using parameter.
module SISO_Shift_Register_By_Using_Parameter #(parameter N = 8)(
input clk, enable, reset_p,
input d,
output q );
reg [N-1: 0] siso_reg;
always @(posedge clk or posedge reset_p) begin
if(reset_p) siso_reg <= 0;
else if(enable) siso_reg <= {1'b0 , siso_reg[N-1:1]};
end
assign q = siso_reg[0];
endmodule
4. Test Bench
- 우리는 위 SISO Shift Register의 시뮬레이션을 실행하여 결과값을 확인하기 위해서는 입력값, d에 4bit 값을 하나씩 넣어봐야 한다.
- 그러나, 이는 굉장히 귀찮고, 만약 32bit 데이터를 넣어야 한다면, 얼마나 힘들까?
- 이러한 상황에서 사용할 수 있는 것이 Test Bench 이다.
- Test Bench는 시뮬레이션 환경 구성, 자동화 테스트 지원을 소스 코드로 정의할 수 있는 도구이다.
4.1. Test Bench는 어떻게 만들 수 있는가?
- add Source 버튼 클릭
- Add or create simulation source 클릭
- Test bench 명 설정후, 파일 생성 (일반적으로 tb 키워드를 붙어 test bench임을 표시한다.)
4.2. Test Bench의 내부 구성은 어떻게 만들 수 있는가?
- 1단계) module의 입출력의 자료형을 정의한다.
(입력 변수의 자료형 : reg, 출력 변수의 자료형 : wire) - 2단계) module의 instance를 생성
- 3단계) Initialization of Simulation 를 정의
- 4단계) always문을 이용하여 Clock Pulse를 정의
- 5단계) Processing of Simulation (시뮬레이션의 과정)을 정의
4.3. 4bit SISO Shift Register를 Test Bench로 구현
< Source >
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2024/07/15 20:24:35
// Design Name:
// Module Name: tb_SISO_4bit_Shift_Register
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module tb_SISO_4bit_Shift_Register( );
// module의 Input / Ouput 자료형 선언
// module의 input = reg
// module 의 output = wire
reg clk, enable, reset_p, d;
wire q;
// Register에 저장할 값,데이터
parameter data = 4'b1101;
// Create instance
// DUT (Design Under Test) 라고 주로 Instance 명을 설정
SISO_Shift_Register_By_Using_Parameter #(.N(4)) DUT(
clk, enable, reset_p, d, q );
// Initializtaion of simulation
initial begin
clk = 0; enable = 1; reset_p = 1; d = 0;
end
// Set clock pulse
always #5 clk = ~clk;
// 변수 선언
integer i;
// Processing of simulation
initial begin
#10;
reset_p = 0;
// insert data in register.
for(i = 0; i <4; i = i+1) begin
d = data[i]; #10;
end
// Delay time
#40;
// End of Simulation
$finish;
end
endmodule
< Simulation >
- clk (Clock Pulse)가 Positive edge일 때, 레지스터에 저장하고자 하는 데이터인 data로 부터 입력단자,d를 통해 하나씩 데이터를 입력 받아서 저장한다.
- 입력과 동시에 출력이 발생한다.
- Q) 왜 데이터 입력과 동시에 출력이 발생하는가?
A) assign q = siso_reg[0]; 명령문은 어떤 조건 없이 무조건 실행되기 때문에 모듈이 실행될 때마다 siso_reg[0]을 출력한다.
4.4 Analysis of source code
- `timescale 1ns / 1ps : 시뮬레이션의 타입 비율을 정의
(1ns은 클럭 신호의 단위, 1ps은 시뮬레이션 시간 단위)
→ 1ns / 1ps 라고 정의하고, #5 는 5ns를 의미, #15 는 15ns를 의미
→ 2ns / 1ps 라고 정의하고, #5 는 10ns를 의미, #15 는 30ns를 의미 - Q) 모듈의 입력값은 reg 형, 출력값은 wire 형으로 정의하였는가?
A) 모듈의 입력값은 SISO Register내에서 데이터 값으로 활용되지만, 출력값은 Register의 출력값으로 활용하기 때문에 모듈의 입력값은 reg 형, 출력값은 wire 형으로 정의하였다. - 상수 값은 parameter 키워드, int형 변수는 integer 키워드를 사용하여 정의한다.
- 단, 상수 및 변수 선언은 module 안에서 선언 되지만, initial 안에서는 선언할 수 없다.
- 즉, 상수 및 변수 선언은 module과 initial 사이에서 선언해야 한다. - Instance 명은 DUT (Design Under Timer)이라고 주로 명명한다.
- 초기 시뮬레이션 설정 (Initialization of Simulation)은 변수 값을 설정한다.
- Q) 초기 시뮬레이션 설정내에서 설정 후, delay time을 주면 안되는가?
- A) 일반적으로 초기 시뮬레이션 설정 범위내에서는 변수 값을 정의하고, 나중에 시뮬레이션 진행
과정에서 delay time을 주는 것이 일반적이다.
★★★★★★ - 아래 Clock Pulse 설정은 어떤 의미를 담고, 어떻게 동작하는가?
always #5 clk = ~ clk;
- always 문은 C언어의 while 문과 동일한 역활을 수행
- #5 clk = ~ clk; : 클럭을 5ns 주기로 클럭의 상태 값을 Toggle 시키라는 의미
따라서 위 코드를 통해 시뮬레이션이 진행되는 동안 주기 10ns인 clock pulse
신호가 생성된다. - Q) 두 번째 initial 문은 첫 번째 initial 문과 어떤 차이점을 갖는가?
A) 첫 번째 initial 문은 시뮬레이션 실행전 초기 세팅값 설정을 하게 되고,
두 번째 initial 문은 시물레이션이 동작되는 동안의 상태 및 관리를 하게 된다. - Q) 두 번째 initial 문 내에서 초기 #10 (= 10ns)을 주었는가?
A) 시뮬레이션 초기 세팅에 대한 여유 시간을 갖기 위해 10ns 만큼의 delay time을 주는 것이다. - $ finish; : 시뮬레이션의 종료시키는 키워드
'RTL Design > Verilog RTL 설계' 카테고리의 다른 글
Verilog RTL 설계(7월 15일 - 4, PISO Shift Register) (0) | 2024.07.16 |
---|---|
Verilog RTL 설계(7월 15일 - 3, SISO Register, SIPO Register) (2) | 2024.07.16 |
Verilog RTL 설계(7월 15일 - 1, 오전 내용 복습) (2) | 2024.07.15 |
Verilog RTL 설계(7월 12일 - 6, Edge detector) (0) | 2024.07.15 |
Verilog RTL 설계(7월 12일 - 6, 링 카운터) (0) | 2024.07.14 |