AHB-Lite
: Advanced High Performance Bus-Lite
ARM AMBA[Advanced Microcontroller Bus Architecture] 버스 프로토콜의 lite 버전이다.
- 싱글 마스터 : 마스터 1개가 버스를 제어하고, 여러 슬레이브 장치와 통신한다.
- 고성능 : 고속 데이터 전송을 지원하며, 주로 고성능 마이크로컨트롤러와 프로세서에서 사용된다.

- HWDATA [AHB Write Data] : 쓰기 명령 시, 마스터는 이 신호를 통해 스레이브로 데이터를 전송한다.
- HADDR [AHB Address] : 읽기/쓰기 작업에서, 마스터는 이 신호를 통해 접근하고자 하는 슬레이브의 주소를 지정한다.
- HSEL [AHB Select] : 여러 슬레이브 중 어느 하나를 어느 하나를 선택하기 위해 사용된다.
- HRDATA [AHB Read Data] : 읽기 명령 시, 슬레이브는 이 신호를 통해 마스터로 데이터를 전송한다.
- HREADY [AHB Ready] : 슬레이브가 현재 전송을 완료할 준비가 되었음을 나타내며, 마스터는 이 신호가 높을 때만 다음 전송을 시작한다.
Memory Mapping
: 메모리 주소 공간을 특정 하드웨어 장치나 메모리 위치와 연결하는 기술이ㅏㄷ.

DataMemory → assign rdata = ram[addr[7:2]];
한 영역에 분별되는 주소 값을 얻기 위하여 공통되는 하위 비트 2개를 제외하여 사용한다.
ex)
int main()
{
*(int *) (0x00002100) = 0x01;
return 0;
}

defines.sv
`define OP_TYPE_R 7'b0110011
`define OP_TYPE_IL 7'b0000011
`define OP_TYPE_I 7'b0010011
`define OP_TYPE_S 7'b0100011
`define OP_TYPE_B 7'b1100011
`define OP_TYPE_J 7'b1101111
`define OP_TYPE_JI 7'b1100111
`define OP_TYPE_U 7'b0110111
`define OP_TYPE_UA 7'b0010111
`define ADD 4'b0000
`define SUB 4'b1000
`define SLL 4'b0001
`define SRL 4'b0101
`define SRA 4'b1101
`define SLT 4'b0010
`define SLTU 4'b0011
`define XOR 4'b0100
`define OR 4'b0110
`define AND 4'b0111
`define BEQ 4'b0000
`define BNE 4'b0001
`define BLT 4'b0100
`define BGE 4'b0101
`define BLTU 4'b0110
`define BGEU 4'b0111
DataMemory.sv
`timescale 1ns / 1ps
module DataMemory ( // RAM
input logic clk,
input logic ce,
input logic we,
input logic [ 7:0] addr,
input logic [31:0] wdata,
output logic [31:0] rdata
);
logic [31:0] ram[0:2**6-1];
initial begin
int i;
for (i = 0; i < 2 ** 6; i++) begin
ram[i] = 100 + i;
end
end
assign rdata = ram[addr[7:2]];
always_ff @(posedge clk) begin
if (we & ce) ram[addr[7:2]] <= wdata;
end
endmodule
DataPath.sv
`timescale 1ns / 1ps
`include "defines.sv"
module DataPath (
input logic clk,
input logic reset,
input logic [31:0] machineCode,
input logic regFileWe,
input logic [ 3:0] aluControl,
output logic [31:0] instrMemRAddr,
output logic [31:0] dataMemRAddr,
output logic [31:0] dataMemWData,
input logic [31:0] dataMemRData,
input logic AluSrcMuxSel,
input logic [ 2:0] extType,
input logic [ 2:0] RFWriteDataSrcMuxSel,
input logic branch,
input logic [ 1:0] PCMuxSel
);
logic [31:0] w_ALUResult, w_RegFileRData1, w_RegFileRData2, w_PC_Data, w_PC_IMM_Data;
logic [31:0] w_extendOut, w_AluSrcMuxOut, w_RFWriteDataSrcMuxOut;
logic [31:0] w_PCAdderSrcMuxOut, w_PC_out, w_PC_Adder;
logic w_btaken, w_PCAdderSrcMuxSel;
assign dataMemRAddr = w_ALUResult;
assign dataMemWData = w_RegFileRData2;
Register U_PC (
.clk (clk),
.reset(reset),
.d (w_PC_out),
.q (instrMemRAddr)
);
assign w_PCAdderSrcMuxSel = branch & w_btaken;
mux_2x1 U_PCAdderSrcMux (
.sel(w_PCAdderSrcMuxSel),
.a (32'd4),
.b (w_extendOut),
.y (w_PCAdderSrcMuxOut)
);
adder U_Adder_PC (
.a(instrMemRAddr),
.b(w_PCAdderSrcMuxOut),
.y(w_PC_Data)
);
RegisterFile U_RegisterFile (
.clk (clk),
.we (regFileWe),
.RAddr1(machineCode[19:15]),
.RAddr2(machineCode[24:20]),
.WAddr (machineCode[11:7]),
.WData (w_RFWriteDataSrcMuxOut),
.RData1(w_RegFileRData1),
.RData2(w_RegFileRData2)
);
mux_2x1 U_ALUSrcMux (
.sel(AluSrcMuxSel),
.a (w_RegFileRData2),
.b (w_extendOut),
.y (w_AluSrcMuxOut)
);
alu U_ALU (
.a (w_RegFileRData1),
.b (w_AluSrcMuxOut),
.aluControl(aluControl),
.result (dataMemRAddr),
.btaken (w_btaken)
);
mux_5x1 U_RFWriteDataSrcMux (
.sel(RFWriteDataSrcMuxSel),
.a (dataMemRAddr),
.b (dataMemRData),
.c (w_extendOut), // u-type
.d (w_PC_IMM_Data), // ua-type
.e (w_PC_Adder), // j-type, i-type
.y (w_RFWriteDataSrcMuxOut)
);
extend U_Extend (
.extType(extType),
.instr (machineCode[31:7]), // except opcode
.immext (w_extendOut)
);
adder U_Adder_PC_IMM (
.a(w_extendOut),
.b(instrMemRAddr),
.y(w_PC_IMM_Data)
);
mux_3x1 U_PC_Mux (
.sel(PCMuxSel),
.a(w_PC_Data),
.b(w_PC_IMM_Data),
.c(dataMemRAddr),
.y(w_PC_out)
);
adder U_PC_Adder_4 (
.a(32'd4),
.b(instrMemRAddr),
.y(w_PC_Adder)
);
endmodule
module RegisterFile (
input logic clk,
input logic we,
input logic [ 4:0] RAddr1,
input logic [ 4:0] RAddr2,
input logic [ 4:0] WAddr,
input logic [31:0] WData,
output logic [31:0] RData1,
output logic [31:0] RData2
);
logic [31:0] RegFile[0:31];
initial begin
RegFile[0] = 32'd0;
RegFile[1] = 32'd1;
RegFile[2] = 32'd2;
RegFile[3] = 32'd3;
RegFile[4] = 32'd4;
RegFile[5] = 32'd5;
end
always_ff @(posedge clk) begin
if (we) RegFile[WAddr] <= WData;
end
assign RData1 = (RAddr1 != 0) ? RegFile[RAddr1] : 0;
assign RData2 = (RAddr2 != 0) ? RegFile[RAddr2] : 0;
endmodule
module Register (
input logic clk,
input logic reset,
input logic [31:0] d,
output logic [31:0] q
);
always_ff @(posedge clk, posedge reset) begin
if (reset) q <= 0;
else q <= d;
end
endmodule
module alu ( // logic : unsigned 4 bit -> signed(-) change unsigned(+)
input logic [31:0] a,
input logic [31:0] b,
input logic [3:0] aluControl,
output logic btaken,
output logic [31:0] result
);
always_comb begin
case (aluControl)
`ADD: result = a + b;
`SUB: result = a - b;
`SLL: result = a << b;
`SRL: result = a >> b; // only unsigned
`SRA: result = $signed(a) >>> b; // Shiftt Right Arith (unsigned & signed)
`SLT: result = ($signed(a) < $signed(b)) ? 1 : 0; // Set Less Than (unsigned & signed)
`SLTU: result = (a < b) ? 1 : 0; // Set Less Than (only unsigned)
`XOR: result = a ^ b;
`OR: result = a | b;
`AND: result = a & b;
default: result = 32'bx;
endcase
end
always_comb begin : comparator // B-Type
case (aluControl[2:0])
3'b000: btaken = (a == b); // BEQ: if (rs1 == rs2) PC += imm
3'b001: btaken = (a != b); // BNE: if (rs1 != rs2)
3'b100: btaken = ($signed(a) < $signed(b)); // BLT: if (rs1 < rs2)
3'b101: btaken = ($signed(a) >= $signed(b)); // BGE: if (rs1 >= rs2)
3'b110: btaken = (a < b); // BLTU: if (rs1 < rs2) (U)
3'b111: btaken = (a >= b); // BGEU: if (rs1 >= rs2) (U)
default: btaken = 1'bx;
endcase
end
endmodule
module adder (
input logic [31:0] a,
input logic [31:0] b,
output logic [31:0] y
);
assign y = a + b;
endmodule
module extend ( // immext
input logic [ 2:0] extType,
input logic [31:7] instr, // except opcode
output logic [31:0] immext
);
always_comb begin
case (extType)
3'b000: immext = {{21{instr[31]}}, instr[31:20]}; // I-Type
3'b001:
immext = {{21{instr[31]}}, instr[30:25], instr[11:7]}; // S-Type
3'b010:
immext = {
{20{instr[31]}}, instr[7], instr[30:25], instr[11:8], 1'b0
}; // B-Type
3'b011: immext = {instr[31:12], {12{1'b0}}}; // U-Type
3'b100:
immext = {
{12{instr[31]}},
instr[19:12],
instr[20],
instr[30:25],
instr[24:21],
1'b0
}; // J-Type
3'b111:
immext = {
{27{instr[24]}}, instr[24:20]
};
endcase
end
endmodule
module mux_2x1 (
input logic sel,
input logic [31:0] a,
input logic [31:0] b,
output logic [31:0] y
);
always_comb begin
case (sel)
1'b0: y = a;
1'b1: y = b;
default: y = 32'bx;
endcase
end
endmodule
module mux_3x1 (
input logic [ 1:0] sel,
input logic [31:0] a,
input logic [31:0] b,
input logic [31:0] c,
output logic [31:0] y
);
always_comb begin
case (sel)
2'b00: y = a;
2'b01: y = b;
2'b10: y = c;
default: y = 32'bx;
endcase
end
endmodule
module mux_5x1 (
input logic [ 2:0] sel,
input logic [31:0] a,
input logic [31:0] b,
input logic [31:0] c,
input logic [31:0] d,
input logic [31:0] e,
output logic [31:0] y
);
always_comb begin
case (sel)
3'b000: y = a;
3'b001: y = b;
3'b010: y = c;
3'b011: y = d;
3'b100: y = e;
default: y = 32'bx;
endcase
end
endmodule
CPU_Core.sv
`timescale 1ns / 1ps
module CPU_Core (
input logic clk,
input logic reset,
input logic [31:0] machineCode,
output logic [31:0] instrMemRAddr,
output logic dataMemWe,
output logic [31:0] dataMemRAddr,
output logic [31:0] dataMemWData,
input logic [31:0] dataMemRData
);
logic w_regFileWe, w_AluSrcMuxSel, w_branch;
logic [3:0] w_aluControl;
logic [2:0] w_extType, w_RFWriteDataSrcMuxSel;
logic [1:0] w_PCMuxSel;
ControlUnit U_ControlUnit (
.op (machineCode[6:0]),
.funct3 (machineCode[14:12]),
.funct7 (machineCode[31:25]),
.regFileWe (w_regFileWe),
.AluSrcMuxSel (w_AluSrcMuxSel),
.RFWriteDataSrcMuxSel(w_RFWriteDataSrcMuxSel),
.dataMemWe (dataMemWe),
.aluControl (w_aluControl),
.extType (w_extType),
.branch (w_branch),
.PCMuxSel (w_PCMuxSel)
);
DataPath U_DataPath (
.clk (clk),
.reset (reset),
.machineCode (machineCode),
.regFileWe (w_regFileWe),
.aluControl (w_aluControl),
.instrMemRAddr (instrMemRAddr),
.AluSrcMuxSel (w_AluSrcMuxSel),
.RFWriteDataSrcMuxSel(w_RFWriteDataSrcMuxSel),
.dataMemRAddr (dataMemRAddr),
.dataMemRData (dataMemRData),
.extType (w_extType),
.dataMemWData (dataMemWData),
.branch (w_branch),
.PCMuxSel (w_PCMuxSel)
);
endmodule
ControlUnit.sv
`timescale 1ns / 1ps
`include "defines.sv"
module ControlUnit (
input logic [6:0] op,
input logic [2:0] funct3,
input logic [6:0] funct7,
output logic regFileWe,
output logic AluSrcMuxSel,
output logic [2:0] RFWriteDataSrcMuxSel,
output logic dataMemWe,
output logic [2:0] extType,
output logic [3:0] aluControl,
output logic branch,
output logic [1:0] PCMuxSel
);
logic [11:0] controls;
// logic [1:0] w_AluOp;
assign {regFileWe, AluSrcMuxSel, RFWriteDataSrcMuxSel, dataMemWe, extType, branch, PCMuxSel} = controls;
always_comb begin : main_decoder
case (op) // Opcode
// regFisleWe, AluSrcMuxSel, RFWriteDataSrcMuxSel, dataMemWe, extType, branch, PCMuxSel
`OP_TYPE_R: controls = 12'b1_0_000_0_xxx_0_00;
`OP_TYPE_IL: controls = 12'b1_1_001_0_000_0_00;
`OP_TYPE_I:
if (funct3 == 3'b001 || funct3 == 3'b101) begin
controls = 12'b1_1_000_0_111_0_00;
end
else begin
controls = 12'b1_1_000_0_000_0_00;
end
`OP_TYPE_S: controls = 12'b0_1_xxx_1_001_0_00;
`OP_TYPE_B: controls = 12'b0_0_xxx_0_010_1_00;
`OP_TYPE_J: controls = 12'b1_x_100_0_100_0_01;
`OP_TYPE_JI: controls = 12'b1_1_100_0_000_0_10;
`OP_TYPE_U: controls = 12'b1_x_010_0_011_0_00;
`OP_TYPE_UA: controls = 12'b1_x_011_0_011_0_00;
default: controls = 12'bx;
endcase
end
always_comb begin : alu_control_signal
case (op)
`OP_TYPE_R: aluControl = {funct7[5], funct3};
`OP_TYPE_IL: aluControl = {1'b0, 3'b000}; // only Add
`OP_TYPE_I:
if (funct3 == 3'b001 || funct3 == 3'b101) begin
aluControl = {funct7[5], funct3};
end
else begin
aluControl = {1'b0, 3'b000};
end
`OP_TYPE_S: aluControl = {1'b0, 3'b000}; // only Add
`OP_TYPE_B: aluControl = {1'b0, funct3};
`OP_TYPE_J: aluControl = {1'b0, 3'b000};
`OP_TYPE_JI: aluControl = {1'b0, 3'b000};
default: aluControl = 4'bx;
endcase
end
endmodule
InstructionMemory.sv
`timescale 1ns / 1ps
module InstructionMemory (
input logic [31:0] addr, // 1 byte standard
output logic [31:0] data
);
logic [31:0] rom[0:63];
initial begin
$readmemh("inst.mem", rom); // hex code instruction
end
// use 4 byte (32bit)
assign data = rom[addr[31:2]]; // 0, 4, 8 ...
endmodule
Bus_Interconnector.sv
`timescale 1ns / 1ps
module BUS_Interconnector (
input logic [31:0] address,
output logic [ 2:0] slave_sel,
input logic [31:0] slave_rdata1,
input logic [31:0] slave_rdata2,
input logic [31:0] slave_rdata3,
output logic [31:0] master_rdata
);
decoder U_Decoder(
.x(address),
.y(slave_sel)
);
mux U_Mux(
.sel(address),
.a(slave_rdata1),
.b(slave_rdata2),
.c(slave_rdata3),
.y(master_rdata)
);
endmodule
module decoder (
input logic [31:0] x,
output logic [ 2:0] y
);
always_comb begin : decoder
case (x[31:8])
24'h0000_10: y = 3'b001;
24'h0000_20: y = 3'b010;
24'h0000_21: y = 3'b100;
default: y = 3'b0;
endcase
end
endmodule
module mux (
input logic [31:0] sel,
input logic [31:0] a,
input logic [31:0] b,
input logic [31:0] c,
output logic [31:0] y
);
always_comb begin : decoder
case (sel[31:8])
24'h0000_10: y = a;
24'h0000_20: y = b;
24'h0000_21: y = c;
default: y = 32'bx;
endcase
end
endmodule
GPO.sv
`timescale 1ns / 1ps
module GPO (
input logic clk,
input logic reset,
input logic ce,
input logic we,
input logic [ 1:0] addr,
input logic [31:0] wdata,
output logic [31:0] rdata,
output logic [ 3:0] outPort
);
// GPO Register
logic [31:0] ODR;
// output logic
assign outPort = ODR[3:0];
// write logic
always_ff @(posedge clk, posedge reset) begin : GPO
if (reset) begin
ODR <= 0;
end else begin
if (ce & we) ODR <= wdata;
end
end
// read logic
assign rdata = ODR;
endmodule
RV32I.sv
`timescale 1ns / 1ps
module RV32I (
input logic clk,
input logic reset,
output logic [3:0] outPortA
);
logic [31:0] w_InstrMemAddr, w_InsrtMemData;
logic w_We;
logic [31:0] w_Addr, w_dataMemRData, w_WData;
logic [31:0] w_MasterRData, w_GPORData;
logic [2:0] w_slave_sel;
CPU_Core U_CPU_Core (
.clk (clk),
.reset (reset),
.machineCode (w_InsrtMemData),
.instrMemRAddr(w_InstrMemAddr),
.dataMemWe (w_We),
.dataMemRAddr (w_Addr),
.dataMemRData (w_MasterRData),
.dataMemWData (w_WData)
);
BUS_Interconnector U_BUS_InterConn (
.address (w_Addr),
.slave_sel (w_slave_sel),
.slave_rdata1(w_dataMemRData),
.slave_rdata2(w_GPORData),
.slave_rdata3(),
.master_rdata(w_MasterRData)
);
GPO U_GPO (
.clk (clk),
.reset (reset),
.ce (w_slave_sel[1]),
.we (w_We),
.addr (w_Addr[1:0]),
.wdata (w_WData),
.rdata (w_GPORData),
.outPort(outPortA)
);
DataMemory U_RAM (
.clk (clk),
.ce (w_slave_sel[0]),
.we (w_We),
.addr (w_Addr[7:0]),
.wdata(w_WData),
.rdata(w_dataMemRData)
);
InstructionMemory U_ROM (
.addr(w_InstrMemAddr),
.data(w_InsrtMemData)
);
endmodule
tb_RISC_V
`timescale 1ns / 1ps
module tb_RISC_V ();
logic clk;
logic reset;
logic [3:0] outPortA;
RV32I dut(.*);
always #5 clk = ~clk;
initial begin
clk = 0;
reset = 1;
#50 reset = 0;
end
endmodule
Inst.mem
00000133
000017b7
10078793
00f10133
ff010113
00112623
00812423
01010413
000027b7
00f00713
00e7a023
00a00513
018000ef
000027b7
0007a023
00a00513
008000ef
fddff06f
fd010113
02812623
03010413
fca42e23
fe042623
0400006f
fe042423
01c0006f
fec42783
00178793
fef42623
fe842783
00178793
fef42423
fe842703
000187b7
69f78793
fce7dee3
fdc42783
fff78793
fcf42e23
fdc42783
fcf040e3
00000013
02c12403
03010113
00008067
schematic

simulation

constraint
## Clock signal
set_property -dict { PACKAGE_PIN W5 IOSTANDARD LVCMOS33 } [get_ports { clk }]; #IO_L12P_T1_MRCC_34 ,Sch=CLK100MHZ
create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]
## LEDs
set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { outPortA[0] }]; #IO_L23N_T3_A02_D18_14 ,Sch=LED0
set_property -dict { PACKAGE_PIN E19 IOSTANDARD LVCMOS33 } [get_ports { outPortA[1] }]; #IO_L3N_T0_DQS_EMCCLK_14 ,Sch=LED1
set_property -dict { PACKAGE_PIN U19 IOSTANDARD LVCMOS33 } [get_ports { outPortA[2] }]; #IO_L15P_T2_DQS_RDWR_B_14 ,Sch=LED2
set_property -dict { PACKAGE_PIN V19 IOSTANDARD LVCMOS33 } [get_ports { outPortA[3] }]; #IO_L15N_T2_DQS_DOUT_CSO_B_14 ,Sch=LED3
##Buttons
set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { reset }]; #IO_L18N_T2_A11_D27_14 ,Sch=BTNC
'[하만]세미콘 아카데미 > verilog' 카테고리의 다른 글
0614 AMBA AXI BUS 00 | 2024.07.10 |
---|---|
0604 RISC-v GPO GPI GPIO 0 | 2024.07.10 |
0530~0531 RISCV_Type 0 | 2024.07.09 |
0523 Team Project 0 | 2024.07.09 |
0529 DedicatedProcessor stackSum 0 | 2024.07.09 |