2024.9.11 수업날
< stopwatch_btn(myip) >
저번에 만들었던 stopwatch_btn Block Desgin에서 이번에는 버튼에 기능을 추가해본다.
vivado 진행 순서
board 부분에서 4 Puch Button을 끌어다가 Diagram에 추가한다.
Diagram 부분에서 수정한 부분이 있다면 Sources에서 수정한 Diagram의 wrapper를 갱신한다.
그 다음 bitstream을 실행하고 .xsa 파일을 만든다.
vitis 진행 순서
새롭게 만든 hardware platform에는 gpio(버튼 기능)이 있는 것을 확인할 수 있다.
Mblaze_stopwatch_btn -> helloworld.c 소스코드
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"
#include "xgpio.h"
#define BTN_ID XPAR_AXI_GPIO_0_DEVICE_ID
#define BTN_CHANNEL 1
#define STOPWATCH_BASEADDR XPAR_MYIP_STOPWATCH_0_S00_AXI_BASEADDR
int main()
{
init_platform();
print("Start!\n");
XGpio_Config *cfg_ptr;
XGpio btn_device;
u32 btn_value;
u32 lap_toggle = 1;
u32 start_toggle = 0b10;
cfg_ptr = XGpio_LookupConfig(BTN_ID);
XGpio_CfgInitialize(&btn_device, cfg_ptr, cfg_ptr->BaseAddress);
XGpio_SetDataDirection(&btn_device, BTN_CHANNEL, 0xffff);
volatile unsigned int *stopwatch_instance = (volatile unsigned int)STOPWATCH_BASEADDR;
xil_printf("Sanity check : %x \n", stopwatch_instance[7]); // 무결성 체크
while(1){
if(XGpio_DiscreteRead(&btn_device, BTN_CHANNEL)){ // 채터링 방지
MB_Sleep(1);
btn_value = XGpio_DiscreteRead(&btn_device, BTN_CHANNEL);
// lap: 0b01
if(btn_value == 0b0001){
stopwatch_instance[0] = stopwatch_instance[0] ^ lap_toggle; // bit toggle
lap_toggle = 0;
}
else if(btn_value == 0b0000){
lap_toggle = 1;
}
// start: 0b10, stop: 0b00
if(btn_value == 0b0010){
stopwatch_instance[0] = stopwatch_instance[0] ^ start_toggle; // bit toggle
start_toggle = 0;
}
else if(btn_value == 0b0000){
start_toggle = 0b10;
}
}
// if(btn_value == 0b0001 && (stopwatch_instance[0] & 0b01))
// stopwatch_instance[0] = stopwatch_instance[0] & 0b10; // bit clear
// else if(btn_value == 0b0001 && ~(stopwatch_instance[0] & 0b01))
// stopwatch_instance[0] = stopwatch_instance[0] | 1; // bit set
//
// // start: 0b10, stop: 0b00
// if(btn_value == 0b0001 && (stopwatch_instance[0]&0b10))stopwatch_instance[0] = 0b00;
// else if(btn_value == 0b0001 && ~(stopwatch_instance[0]&0b10))stopwatch_instance[0] = 0b10;
//
// // lap: 0b01
// else if(btn_value == 0b0010 && (stopwatch_instance[0]&0b1))stopwatch_instance[0] = 0b01;
// else if(btn_value == 0b0010 && ~(stopwatch_instance[0]&0b1))stopwatch_instance[0] = 0b00;
//stopwatch_instance[0] = 0b10;
// xil_printf("button %x\n", btn_value);
// xil_printf("control reg %x\n", stopwatch_instance[0]);
// print("Hello World!\n");
// MB_Sleep(1000);
}
cleanup_platform();
return 0;
}
< pwm_servo(myip) >
이번에는 pwm을 사용하여 servo motor를 제어하는 IP를 만들어본다.
Verilog 수업시간에 만들었던 pwm 모듈을 가지고 IP로 만든다.
pwm_256step_comparator_freq
//////////////////////////pwm 제어하기, 256분주기(100MHz로 나눈), 비교기 사용
// 서브모터는 50Hz
module pwm_256step_comparator_freq
#( parameter sys_clk_freq = 100_000_000, //시스템 클록, 100MHz
parameter pwm_freq = 50, //pwm 출력, 50Hz
parameter duty_step = 256, // 듀티 싸이클 1256로 설정
parameter temp = sys_clk_freq / pwm_freq / duty_step, // 타이머 카운트 주기, parameter 상수는 그냥 수이기 때문에 회로 만들때는 나누기 회로가 만들어지지 않음
parameter temp_half = temp / 2)
(
input clk, reset_p,
input [31:0]duty,
output reg pwm );
integer cnt; // 카운터 변수 선언
reg pwm_freqX256; // 128배 주파수를 가지는 PWM 신호를 저장하는 레지스터 선언
always @ (posedge clk or posedge reset_p) begin
if(reset_p) begin
pwm_freqX256 = 0;
cnt = 0;
end
else begin
if(cnt >= (temp - 1))cnt = 0; //78분주-->10,000/128
else cnt = cnt + 1;
//if(cnt < (pwmXduty_steps / 2)) pwm_freqX128 = 0; // 마찬가지로 상수이기 때문에 상관 없음
if(cnt < temp_half) pwm_freqX256 = 0;
else pwm_freqX256 = 1;
end
end
wire pwm_freqX256_nedge;
edge_detector_n ed(
.clk(clk), .reset_p(reset_p),
.cp(pwm_freqX256), .n_edge(pwm_freqX256_nedge));
integer cnt_duty;
always @ (posedge clk or posedge reset_p)begin
if(reset_p) begin
cnt_duty = 0;
pwm = 0;
end
else if(pwm_freqX256_nedge)begin
if(cnt_duty >= (duty_step - 1))cnt_duty= 0;
else cnt_duty = cnt_duty + 1;
if(cnt_duty < duty)pwm = 1;
else pwm = 0;
end
end
endmodule
vivado 진행 순서
Block Desgin에서 새로 생성하고 기본적인 Block Diagram까지 만든 후 IP를 만들면 된다.
아래와 같이 파일 추가
slave 모듈 수정해야할 부분
top 모듈 수정해야할 부분
package IP에서 초록 체크표시가 되지 않은 부분에서 노란 부분을 선택하면 초록 체크표시로 바뀐다.
마지막으로 re-package IP를 선택한다.
myip_pwm 추가된 모습
출력단에 출력을 추가해준다.
Block Design에서 Sources의 .xdc에 아래와 같이 수정한다.
wrapper를 갱신하고 bistream을 실행한 후 .xsa를 생성하면 된다.
vitis 진행 순서
Mblaze_pwm_servo -> helloworld.c 소스코드
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xparameters.h"
#define SERVO_BASEADDR XPAR_MYIP_PWM_0_S00_AXI_BASEADDR
int main()
{
char up_down = 1;
init_platform();
print("Start!\n");
volatile unsigned int *servo_instance = (volatile unsigned int)SERVO_BASEADDR;
xil_printf("Sanity check : %x \n", servo_instance[7]);
servo_instance[0] = 6;
while(1){
MB_Sleep(16);
if(up_down){
servo_instance[0]++;
if(servo_instance[0] >= 32) up_down = 0;
}
else{
servo_instance[0]--;
if(servo_instance[0] <= 6) up_down = 1;
}
// print("Hello World!\n");
// MB_Sleep(1000);
}
cleanup_platform();
return 0;
}
stopwatch_btn(myip), pwm_servo(myip) 끝!
'Harman 세미콘 아카데미 > SoC를 위한 Peripheral 설계' 카테고리의 다른 글
2024.9.12 [SoC를 위한 Peripheral 설계]6 - dht11_lcd(myip) (1) | 2024.09.15 |
---|---|
2024.9.12 [SoC를 위한 Peripheral 설계]5 - btn_intc(myip), iic(myip) (0) | 2024.09.12 |
2024.9.10 [SoC를 위한 Peripheral 설계]3 - bcd_fnd, stopwatch(myip) (0) | 2024.09.10 |
2024.9.6 [SoC를 위한 Peripheral 설계]2 - led 제어2, fnd, fnd cntr(myip) (0) | 2024.09.06 |
2024.9.5 [SoC를 위한 Peripheral 설계]1 - Vitis 사용법, button 제어, led_switch 제어 (0) | 2024.09.05 |