1. Title
AMBA BUS (APB Protocol)
2. Category
"RISC-V", "AMBA BUS", "APB Protocol"
3. Key Concepts
APB Protocol을 Verilog로 구현한다.
4. Setup
CPU Course Review - 12. AMBA BUS (APB Protocol - GPO)
1. TitleAMBA BUS (APB Protocol)2. Category"RISC-V", "AMBA BUS", "APB Protocol" 3. Key ConceptsAPB Protocol을 Verilog로 구현한다. 4. Setup CPU Course Review - 11. AMBA BUS (APB Protocol)1. TitleAMBA BUS (APB Protocol)2. Category"RISC-V", "A
salmon1113.tistory.com
이전 게시글에서 GPO에 APB Interface를 추가한 것에 이어 APB Interface를 이용해 GPI를 구현한다.
5. Code Review
module gpi (
input logic [7:0] control,
input logic [7:0] inport,
output logic [7:0] data
);
genvar i;
generate
for(i = 0; i < 8; i++) begin
assign data[i] = control[i] ? inport[i] : 'z;
end
endgenerate
endmodule
GPI는 기본적으로 고임피던스(High-Z) 상태를 유지하다가 control 신호가 1이되면 데이터를 받아들인다.
module periph_gpi (
input logic PCLK, // APB CLK
input logic PRESET, // APB asynchronous RESET
// APB Interface Signals
input logic [31:0] PADDR,
input logic PWRITE,
input logic PSEL,
input logic PENABLE,
input logic [31:0] PWDATA,
output logic [31:0] PRDATA,
output logic PREADY,
// Internal Signals
input logic [7:0] inport
);
logic [7:0] control;
logic [7:0] data;
apb_slave_interface_gpi U_APB_SLAVE_INTERFACE(
.*,
.ddr(control),
.idr(data)
);
gpi U_GPI(
.control(control),
.data(data),
.inport(inport)
);
endmodule
module apb_slave_interface_gpi (
input logic PCLK, // APB CLK
input logic PRESET, // APB asynchronous RESET
// APB Interface Signals
input logic [31:0] PADDR,
input logic PWRITE,
input logic PSEL,
input logic PENABLE,
input logic [31:0] PWDATA,
output logic [31:0] PRDATA,
output logic PREADY,
// Internal Signals
output logic [7:0] ddr,
input logic [31:0] idr
);
localparam DDR_ADDR = 4'h0;
localparam IDR_ADDR = 4'h4;
logic [31:0] dd_reg, id_reg;
assign ddr = dd_reg[7:0];
assign id_reg = {24'b0, idr[7:0]};
always_ff @(posedge PCLK, posedge PRESET) begin
if (PRESET) begin
dd_reg <= 0;
end else begin
PREADY <= 1'b0;
if (PSEL && PENABLE && PWRITE) begin
PREADY <= 1'b1;
case (PADDR[3:0])
DDR_ADDR: dd_reg <= PWDATA;
IDR_ADDR: ;
default: ;
endcase
end else if (PSEL && PENABLE && !PWRITE) begin
PREADY <= 1'b1;
case (PADDR[3:0])
DDR_ADDR: PRDATA <= dd_reg;
IDR_ADDR: PRDATA <= id_reg;
default: PRDATA = 'x;
endcase
end
end
end
endmodule
CPU는 RAM과 협력하여 필요한 연산을 수행한 후, APB 인터페이스를 통해 GPO 모듈의 내부 레지스터(dd_reg 및 od_reg)에 접근한다.
APB 인터페이스는 CPU가 control과 data 레지스터에 값을 쓰거나 읽을 수 있도록 하며, 이를 통해 GPO의 출력을 제어한다.
7. Testing and Debugging
* Testing Tools: VIVADO, BASYS-3, Modelsim
#include <stdint.h>
#define APB_PERIPH_BASE 0X10000000
#define RAM_BASE (APB_PERIPH_BASE + 0X0000)
#define GPOA_BASE (APB_PERIPH_BASE + 0X1000)
#define GPIB_BASE (APB_PERIPH_BASE + 0X2000)
#define GPIO_BASE (APB_PERIPH_BASE + 0X3000)
#define GPOA_DDR *(volatile uint32_t *)(GPOA_BASE + 0x00)
#define GPOA_ODR *(volatile uint32_t *)(GPOA_BASE + 0x04)
#define GPIB_DDR *(volatile uint32_t *)(GPIB_BASE + 0x00)
#define GPIB_IDR *(volatile uint32_t *)(GPIB_BASE + 0x04)
void delay(int n);
int main()
{
uint32_t inData = 0x01;
GPOA_DDR = 0x000000ff;
GPIB_DDR = 0X000000ff;
while(1)
{
if(GPIB_IDR & 0x01){
inData = (inData >> 7) | (inData << 1);
} else{
inData = (inData << 7) | (inData >> 1);
}
GPOA_ODR = inData;
delay(500);
}
return 0;
}
void delay(int n)
{
uint32_t temp = 0;
for(int i = 0; i < n; i++)
{
for (int j = 0; j < 1000; j++)
{
temp ++;
}
}
}
코드 가독성을 높이기 위해 GPO, GPI의 ADDRESS를 DEFINE 처리하였다.
위 프로그램은 GPI로 사용되는 사용자 Input을 받아 만약 Input이 '1이면 LED를 왼쪽으로 SHIFT 시키고, '0'이면 LED를 오른쪽으로 SHIFT 시키는 프로그램이다.
'AI SOC COURSE > SYSTEM VERILOG (CPU 설계)' 카테고리의 다른 글
CPU Course Review - 15. AMBA BUS (APB Protocol - GPIO) (0) | 2025.02.26 |
---|---|
CPU Course Review - 14. Device Driver (0) | 2025.02.26 |
CPU Course Review - 12. AMBA BUS (APB Protocol - GPO) (0) | 2025.02.25 |
CPU Course Review - 11. AMBA BUS (APB Protocol - RAM) (0) | 2025.02.24 |
CPU Course Review - 10. Analysis of Assembly Language (Single Cycle RISC-V) (0) | 2025.02.21 |