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 | 29 | 30 |
Tags
- java
- FND
- BASYS3
- vivado
- Pspice
- Algorithm
- ATMEGA128A
- DHT11
- uart 통신
- test bench
- Edge Detector
- Linked List
- pwm
- structural modeling
- KEYPAD
- stop watch
- i2c 통신
- hc-sr04
- behavioral modeling
- gpio
- half adder
- dataflow modeling
- soc 설계
- verilog
- Recursion
- atmega 128a
- ring counter
- prescaling
- D Flip Flop
- LED
Archives
- Today
- Total
거북이처럼 천천히
Verilog RTL 설계(8월 12일 - 3, ADC Converter - 3) 본문
1. 조이스틱의 x축, y축 아날로그 값을 xadc 모듈을 통해 디지털로 변환
- 이번에는 조이스틱의 x축, y축 아날로그 값을 xadc 모듈을 통해 디지털로 변환한 뒤, FND로 출력해보도록 하겠다.
- 이번에는 변환해야하는 아날로그 값이 2개이기 때문에 xadc 모듈의 설정 값을 다음과 같이 설정하였다.
2. ADC Converter Module 설정
- 2개의 아날로그 값을 변환하기 위해 JXADC 모듈의 6핀과 15핀을 사용하도록 하겠다.
3. ADC Converter 모듈 설계
- ADC Converter 모듈에 대한 설명은 코드와 함께 설명하도록 하겠다.
< Source, Input / Output 선언 >
module adc_converter_1_ch14_15(
input clk, reset_p,
input vauxp6, vauxn6,
input vauxp15, vauxn15,
input sw,
output reg [11:0] red_duty, green_duty, blue_duty,
output reg red_blue);
endmodule
- xadc 모듈의 6번 핀과 15핀을 사용할 것이기 때문에 이에 대한 6번과15핀의 input 설정한다.
- RGB 색상의 duty을 컨트롤하기 위해 red_duty, green_duty, blue_duty 을 이용하도록 하겠다.
- red_blue는 조이스틱의 x축을 통해 Red의 duty, Blue의 duty 값을 조절하기 위해 선언한 Register이다.
< Source, xadc_wiz 인스턴스 선언 >
// Declare variables.
wire eoc_out; // End of convert, 변환 종료 신호
wire [4:0] channel_out; // 현재 선택된 채널
wire [15:0] do_out;
// Instance of XADC Converter
xadc_wiz_0 adc_ch14_ch15 (
.daddr_in({2'b0, channel_out}), // XADC 레지스터에 접근하기 위한 주소를 지정
.dclk_in(clk), // xadc 모듈의 clk 설정
.den_in(eoc_out), // den_in는 eoc_out로 부터 디지털 변환 신호를 끝났다는 신호를
// 받으면 데이터 전송을 시작하게 된다.
.reset_in(reset_p), // 시스템 제어를 위한 리셋 신호
.vauxp6(vauxp6), // Auxiliary channel 14
.vauxn6(vauxn6),
.vauxp15(vauxp15), // Auxiliary channel 15
.vauxn15(vauxn15),
.channel_out(channel_out), // 채널 선택 출력, 현재 선택된 채널을 나타낸다.
.do_out(do_out), // 아날로그 신호를 디지털 값으로 변환된 결과 값
.eoc_out(eoc_out)); // 변환 종료 신호 );
< Source, eoc_out의 Positive edge 얻기 >
// Get positive edge of eoc_out.
wire eoc_out_pedge;
edge_detector edge_detector_eoc_out (.clk(clk), .reset_p(reset_p), .cp(eoc_out), .p_edge(eoc_out_pedge));
- eoc_out 변수는 아날로그에서 디지털 변환이 끝났는지 여부를 나타내는 Flag이다.
- 디지털로 변환이 끝나면 eoc_out 값이 0 → 1로 변화하기 때문에 eoc_out 변수의 positive edge를 통해 변화가 끝났는지 여부를 확인할 수 있다.
< Source, 조이스틱의 스위치의 Positive edge 얻기 >
// Get positive edge of switch
wire sw_pedge;
btn_cntr switch (.clk(clk), .reset_p(reset_p), .btn(sw), .btn_pedge(sw_pedge));
< Source, 변환이 끝난 뒤, channel_out을 통해 변환된 디지털 값을 output으로 전달한다. >
// 조이스틱의 스위치가 눌리면 mode 변환하여 blue 값 조절
// red duty : x축, green duty : y 축, blue : x 축
// 변환이 끝나면 channel_out을 통해 몇 번 채널의 변환이 끝났는지 확인 후, 출력
always @(posedge clk or posedge reset_p) begin
if(reset_p) begin
red_duty = 0;
green_duty = 0;
blue_duty = 0;
red_blue = 1;
end
else if(eoc_out_pedge) begin
case(channel_out[3:0])
6 : begin
if(red_blue) red_duty = do_out[15:4];
else blue_duty = do_out[15:4];
end
15 : green_duty = do_out[15:4];
endcase
end
else if(sw_pedge) red_blue = ~red_blue;
end
endmodule
- eoc_out_pedge 를 통해 아날로그에서 디지털로 변환이 끝났는지 여부를 확인할 수 있기 때문에 eoc_out_pedge가 활성화되면 channel_out 변수를 통해 몇 번 채널의 변환이 끝났는지 여부를 확인하여 해당 채널의 디지털 값을 Output 으로 전달한다.
- Basys3는 6, 7, 14 ,15 채널을 지원하기 때문에 channel_out 변수에 4bit을 통해 몇 번 채널이 끝났는지 여부를 확인할 수 있다.
- sw_pedge 가 활성화 되면 red_blue 값을 Toggle 시킨도록 설계하였다.
- red_blue 값에 따라 변환된 디지털 값을 red duty에 전달할 지, blue duty에 전달할 지가 결정된다.
4. 전체 소스 코드
// Top module of xadc
module top_module_of_xadc (
input clk, reset_p,
input vauxp6, vauxn6,
input vauxp15, vauxn15,
input sw,
output [3:0] com,
output [7:0] seg_7 );
// Instance of adc converter
wire [11:0] red_duty, green_duty, blue_duty;
wire red_blue;
adc_converter_1_ch14_15 adc_convert (.clk(clk), .reset_p(reset_p),
.vauxp6(vauxp6), .vauxn6(vauxn6), .vauxp15(vauxp15), .vauxn15(vauxn15),
.sw(sw), .red_duty(red_duty), .green_duty(green_duty), .blue_duty(blue_duty), .red_blue(red_blue));
// Convert from binary to BCD
wire [15:0] red_duty_bcd, green_duty_bcd, blue_duty_bcd;
bin_to_dec bcd_red(.bin({6'b0, red_duty[11:6]}), .bcd(red_duty_bcd));
bin_to_dec bcd_green(.bin({6'b0, green_duty[11:6]}), .bcd(green_duty_bcd));
bin_to_dec bcd_blue(.bin({6'b0, blue_duty[11:6]}), .bcd(blue_duty_bcd));
// Select FND
wire [15:0] red_green, blue_green, fnd;
assign red_green = {red_duty_bcd[7:0], green_duty_bcd[7:0]};
assign blue_green = {blue_duty_bcd[7:0], green_duty_bcd[7:0]};
assign fnd = (red_blue) ? red_green : blue_green;
// FND Control
fnd_cntr control_fnd (.clk(clk), .reset_p(reset_p), .hex_value(fnd), .com(com), .seg_7(seg_7));
endmodule
// adc converter module
module adc_converter_1_ch14_15(
input clk, reset_p,
input vauxp6, vauxn6,
input vauxp15, vauxn15,
input sw,
output reg [11:0] red_duty, green_duty, blue_duty,
output reg red_blue);
// Declare variables.
wire eoc_out; // End of convert, 변환 종료 신호
wire [4:0] channel_out; // 현재 선택된 채널
wire [15:0] do_out;
// Instance of XADC Converter
xadc_wiz_0 adc_ch14_ch15 (
.daddr_in({2'b0, channel_out}), // XADC 레지스터에 접근하기 위한 주소를 지정
.dclk_in(clk), // xadc 모듈의 clk 설정
.den_in(eoc_out), // den_in는 eoc_out로 부터 디지털 변환 신호를 끝났다는 신호를
// 받으면 데이터 전송을 시작하게 된다.
.reset_in(reset_p), // 시스템 제어를 위한 리셋 신호
.vauxp6(vauxp6), // Auxiliary channel 14
.vauxn6(vauxn6),
.vauxp15(vauxp15), // Auxiliary channel 15
.vauxn15(vauxn15),
.channel_out(channel_out), // 채널 선택 출력, 현재 선택된 채널을 나타낸다.
.do_out(do_out), // 아날로그 신호를 디지털 값으로 변환된 결과 값
.eoc_out(eoc_out)); // 변환 종료 신호 );
// Get positive edge of eoc_out.
wire eoc_out_pedge;
edge_detector edge_detector_eoc_out (.clk(clk), .reset_p(reset_p), .cp(eoc_out), .p_edge(eoc_out_pedge));
// Get positive edge of switch
wire sw_pedge;
btn_cntr switch (.clk(clk), .reset_p(reset_p), .btn(sw), .btn_pedge(sw_pedge));
// 조이스틱의 스위치가 눌리면 mode 변환하여 blue 값 조절
// red duty : x축, green duty : y 축, blue : x 축
// 변환이 끝나면 channel_out을 통해 몇 번 채널의 변환이 끝났는지 확인 후, 출력
always @(posedge clk or posedge reset_p) begin
if(reset_p) begin
red_duty = 0;
green_duty = 0;
blue_duty = 0;
red_blue = 1;
end
else if(eoc_out_pedge) begin
case(channel_out[3:0])
6 : begin
if(red_blue) red_duty = do_out[15:4];
else blue_duty = do_out[15:4];
end
15 : green_duty = do_out[15:4];
endcase
end
else if(sw_pedge) red_blue = ~red_blue;
end
endmodule
// Button Control Module
module btn_cntr (
input clk, reset_p,
input btn,
output btn_pedge );
// temp register of button
reg reg_btn;
// 1ms one cycle pulse
wire clk_1usec, clk_1msec;
clk_div_100 clk_div_1usec (.clk(clk), .reset_p(reset_p), .clk_div_100_nedge(clk_1usec));
clk_div_1000 clk_div_1umsec (.clk(clk), .reset_p(reset_p), .clk_source(clk_1usec), .clk_div_1000_nedge(clk_1msec));
always @(posedge clk or posedge reset_p) begin
if(reset_p) reg_btn = 0;
else reg_btn = btn;
end
edge_detector ed_button (.clk(clk), .reset_p(reset_p), .cp(reg_btn), .p_edge(btn_pedge));
endmodule
// Clock divider 100
module clk_div_100 (
input clk, reset_p,
output clk_div_100,
output clk_div_100_nedge, clk_div_100_pedge );
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 edge_detector_clk_div_100 (.clk(clk), .reset_p(reset_p), .cp(clk_div_100),
.n_edge(clk_div_100_nedge), .p_edge(clk_div_100_pedge));
endmodule
// Clock divider 1000
module clk_div_1000 (
input clk, reset_p,
input clk_source,
output clk_div_1000,
output clk_div_1000_nedge, clk_div_1000_pedge );
wire clk_source_nedge;
edge_detector 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 edge_detector_1 (.clk(clk), .reset_p(reset_p), .cp(clk_div_1000),
.n_edge(clk_div_1000_nedge), .p_edge(clk_div_1000_pedge));
endmodule
// Edge detector
module edge_detector (
input clk, reset_p,
input cp,
output p_edge, n_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
// Convert from binary to BCD
module bin_to_dec(
input [11:0] bin,
output reg [15:0] bcd
);
reg [3:0] i;
always @(bin) begin
bcd = 0;
for (i=0;i<12;i=i+1)begin
bcd = {bcd[14:0], bin[11-i]};
if(i < 11 && bcd[3:0] > 4) bcd[3:0] = bcd[3:0] + 3;
if(i < 11 && bcd[7:4] > 4) bcd[7:4] = bcd[7:4] + 3;
if(i < 11 && bcd[11:8] > 4) bcd[11:8] = bcd[11:8] + 3;
if(i < 11 && bcd[15:12] > 4) bcd[15:12] = bcd[15:12] + 3;
end
end
endmodule
< Basys3의 xdc 파일 내에서 JXADC 포트 설정 >
5. 하드웨어 구현
'RTL Design > Verilog RTL 설계' 카테고리의 다른 글
Verilog RTL 설계(8월 22일 - 2, I2C 통신을 통한 LCD 컨트롤 - (2)) (0) | 2024.09.05 |
---|---|
Verilog RTL 설계(8월 22일 - 1, I2C 통신을 통한 LCD 컨트롤 - (1)) (0) | 2024.08.25 |
Verilog RTL 설계(8월 21일 - 2, I2C 통신 - 2) (0) | 2024.08.23 |
Verilog RTL 설계(8월 21일 - 1, I2C 통신 - 1) (0) | 2024.08.22 |
Verilog RTL 설계(7월 24일 - 1, HC-SR04 구현 ) (0) | 2024.08.21 |