对应全书的第九章
Cortex-M0架构分为硬件和软件部分,整个片上系统的内部结构如图1.1所示。
硬件部分在FPGA上由纯数字逻辑实现,主要模块包括:
(1)系统时钟生成器(pll核)
(2)ARM Cortex-M0微处理器
(3)AHB-Lite系统总线:
控制信号,用于同步和识别交易,如:准备,写、读以及传输模式信号
32位地址总线,用于选择一个外设,或者一个外设中的一个寄存器
32位数据总线,用于交换数据信息
(4)两个AHB外设:
程序存储器,通过FPGA内的块存储器实现
LED外设
整个硬件部分的设计如图1.2
Hello world程序:
(1)在Keil μVision5中,使用汇编语言对Cortex-M0处理器编程
(2)建立(build)汇编语言设计文件,生成十六进制的编程文件
(1)处理器提供要访问外设的地址信息
(2)通过地址译码器生成目标外设的选择信号,同时处理器输出一个控制信号,如读写、传输数据的数量等
(3)若处理器输出的是读控制信号,则待从设备ready之后读数据
AHB-Lite有四种基本传输类型,如表1.2,交易的同步和识别由处理器的控制信号给出.
交易 | 访问 | 描述 |
---|---|---|
HSTRANS[1:0]=2’b00 | 空闲 | 处理器不希望处理任何交易 |
HSTRANS[1:0]=2’b10 HPROT[0]=1’b0 HSIZE[1:0]=2’b10 HWRITE=1’b0 |
取指 | 处理器取指操作,处理器一次性从存储器取出32位指令 |
HSTRANS[1:0]=2’b10 HPROT[0]=1’b1 HSIZE[1:0]=2’b00 |
字节 | 处理器希望一个8位数据访问操作,该操作由LDRB,LDRBS,STRB指令生成。加载执行将驱动HWRITE信号为低,保存指令将驱动HWRITE指令为高 |
HSTRANS[1:0]=2’b10 HPROT[0]=1’b1 HSIZE[1:0]=2’b01 |
半字 | 处理器希望一个16位数据访问操作,该操作由LDRH,LDRHS,STRH指令生成。加载执行将驱动HWRITE信号为低,保存指令将驱动HWRITE指令为高 |
HSTRANS[1:0]=2’b10 HPROT[0]=1’b1 HSIZE[1:0]=2’b10 |
字 | 处理器希望执行一个由LDR,LDM,POP,STR,STM,PUSH指令,或者异常入口的一部分,或者返回所产生的32位数据访问操作,加载执行将驱动HWRITE信号为低,保存指令将驱动HWRITE指令为高 |
其中各指令和异常、返回的概念在软件部分介绍
Cortex-M0处理器总是工作在小端模式,所有交易总是自然对齐,怎么对齐如表1.3所示
看代码,怎么才算看懂代码或者数学公式?能用中文说出来就算看懂
代码如下
module AHBLITE_SYS(
//CLOCKS & RESET
input wire CLK,
input wire RESET,
//TO BOARD LEDs
output wire [7:0] LED
);
//AHB-LITE SIGNALS
//Gloal Signals
wire HCLK;
wire HRESETn;
//Address, Control & Write Data Signals
wire [31:0] HADDR;
wire [31:0] HWDATA;
wire HWRITE;
wire [1:0] HTRANS;
wire [2:0] HBURST;
wire HMASTLOCK;
wire [3:0] HPROT;
wire [2:0] HSIZE;
//Transfer Response & Read Data Signals
wire [31:0] HRDATA;
wire HRESP;
wire HREADY;
//SELECT SIGNALS
wire [3:0] MUX_SEL;
wire HSEL_MEM;
wire HSEL_LED;
//SLAVE READ DATA
wire [31:0] HRDATA_MEM;
wire [31:0] HRDATA_LED;
//SLAVE HREADYOUT
wire HREADYOUT_MEM;
wire HREADYOUT_LED;
//CM0-DS Sideband signals
wire LOCKUP;
wire TXEV;
wire SLEEPING;
wire [15:0] IRQ;
//SYSTEM GENERATES NO ERROR RESPONSE
assign HRESP = 1'b0;
//CM0-DS INTERRUPT SIGNALS
assign IRQ = {16'b0000_0000_0000_0000};
// Clock divider, divide the frequency by two, hence less time constraint
clk_wiz_0 Inst_clk_wiz_0
(
// Clock in ports
.clk_in1(CLK), // input clk_in1
// Clock out ports
.clk_out1(HCLK), // output clk_out1
// Status and control signals
.reset(RESET), // input reset
.locked(HRESETn)); // output locked
// INST_TAG_END ------ End INSTANTIATION Template ---------
//AHBLite MASTER --> CM0-DS
CORTEXM0DS u_cortexm0ds (
//Global Signals
.HCLK (HCLK),
.HRESETn (HRESETn),
//Address, Control & Write Data
.HADDR (HADDR[31:0]),
.HBURST (HBURST[2:0]),
.HMASTLOCK (HMASTLOCK),
.HPROT (HPROT[3:0]),
.HSIZE (HSIZE[2:0]),
.HTRANS (HTRANS[1:0]),
.HWDATA (HWDATA[31:0]),
.HWRITE (HWRITE),
//Transfer Response & Read Data
.HRDATA (HRDATA[31:0]),
.HREADY (HREADY),
.HRESP (HRESP),
//CM0 Sideband Signals
.NMI (1'b0),
.IRQ (IRQ[15:0]),
.TXEV (),
.RXEV (1'b0),
.LOCKUP (LOCKUP),
.SYSRESETREQ (),
.SLEEPING ()
);
//Address Decoder
AHBDCD uAHBDCD (
.HADDR(HADDR[31:0]),
.HSEL_S0(HSEL_MEM),
.HSEL_S1(HSEL_LED),
.HSEL_S2(),
.HSEL_S3(),
.HSEL_S4(),
.HSEL_S5(),
.HSEL_S6(),
.HSEL_S7(),
.HSEL_S8(),
.HSEL_S9(),
.HSEL_NOMAP(HSEL_NOMAP),
.MUX_SEL(MUX_SEL[3:0])
);
//Slave to Master Mulitplexor
AHBMUX uAHBMUX (
.HCLK(HCLK),
.HRESETn(HRESETn),
.MUX_SEL(MUX_SEL[3:0]),
.HRDATA_S0(HRDATA_MEM),
.HRDATA_S1(HRDATA_LED),
.HRDATA_S2(),
.HRDATA_S3(),
.HRDATA_S4(),
.HRDATA_S5(),
.HRDATA_S6(),
.HRDATA_S7(),
.HRDATA_S8(),
.HRDATA_S9(),
.HRDATA_NOMAP(32'hDEADBEEF),
.HREADYOUT_S0(HREADYOUT_MEM),
.HREADYOUT_S1(HREADYOUT_LED),
.HREADYOUT_S2(1'b1),
.HREADYOUT_S3(1'b1),
.HREADYOUT_S4(1'b1),
.HREADYOUT_S5(1'b1),
.HREADYOUT_S6(1'b1),
.HREADYOUT_S7(1'b1),
.HREADYOUT_S8(1'b1),
.HREADYOUT_S9(1'b1),
.HREADYOUT_NOMAP(1'b1),
.HRDATA(HRDATA[31:0]),
.HREADY(HREADY)
);
// AHBLite Peripherals
//AHBLite Slave
AHB2MEM uAHB2MEM (
//AHBLITE Signals
.HSEL(HSEL_MEM),
.HCLK(HCLK),
.HRESETn(HRESETn),
.HREADY(HREADY),
.HADDR(HADDR),
.HTRANS(HTRANS[1:0]),
.HWRITE(HWRITE),
.HSIZE(HSIZE),
.HWDATA(HWDATA[31:0]),
.HRDATA(HRDATA_MEM),
.HREADYOUT(HREADYOUT_MEM)
//Sideband Signals
);
//AHBLite Slave
AHB2LED uAHB2LED (
//AHBLITE Signals
.HSEL(HSEL_LED),
.HCLK(HCLK),
.HRESETn(HRESETn),
.HREADY(HREADY),
.HADDR(HADDR),
.HTRANS(HTRANS[1:0]),
.HWRITE(HWRITE),
.HSIZE(HSIZE),
.HWDATA(HWDATA[31:0]),
.HRDATA(HRDATA_LED),
.HREADYOUT(HREADYOUT_LED),
//Sideband Signals
.LED(LED[7:0])
);
endmodule
输出20MHz时钟作为系统主时钟
注意该模块为纯组合逻辑,没有全局时钟和复位信号
module AHBDCD(
input wire [31:0] HADDR,
output wire HSEL_S0,
output wire HSEL_S1,
output wire HSEL_S2,
output wire HSEL_S3,
output wire HSEL_S4,
output wire HSEL_S5,
output wire HSEL_S6,
output wire HSEL_S7,
output wire HSEL_S8,
output wire HSEL_S9,
output wire HSEL_NOMAP,
output reg [3:0] MUX_SEL
);
reg [15:0] dec;
//REFER CM0-DS REFERENC MANUAL FOR RAM & PERIPHERAL MEMORY MAP
// //MEMORY MAP --> START ADDR END ADDR SIZE
assign HSEL_S0 = dec[0]; //MEMORY MAP --> 0x0000_0000 to 0x00FF_FFFF 16MB
assign HSEL_S1 = dec[1]; //MEMORY MAP --> 0x5000_0000 to 0x50FF_FFFF 16MB
assign HSEL_S2 = dec[2]; //MEMORY MAP --> 0x5100_0000 to 0x51FF_FFFF 16MB
assign HSEL_S3 = dec[3]; //MEMORY MAP --> 0x5200_0000 to 0x52FF_FFFF 16MB
assign HSEL_S4 = dec[4]; //MEMORY MAP --> 0x5300_0000 to 0x53FF_FFFF 16MB
assign HSEL_S5 = dec[5]; //MEMORY MAP --> 0x5400_0000 to 0x54FF_FFFF 16MB
assign HSEL_S6 = dec[6]; //MEMORY MAP --> 0x5500_0000 to 0x55FF_FFFF 16MB
assign HSEL_S7 = dec[7]; //MEMORY MAP --> 0x5600_0000 to 0x56FF_FFFF 16MB
assign HSEL_S8 = dec[8]; //MEMORY MAP --> 0x5700_0000 to 0x57FF_FFFF 16MB
assign HSEL_S9 = dec[9]; //MEMORY MAP --> 0x5800_0000 to 0x58FF_FFFF 16MB
assign HSEL_NOMAP = dec[15]; //REST OF REGION NOT COVERED ABOVE
always@*
begin
case(HADDR[31:24])
8'h00: //MEMORY MAP --> 0x0000_0000 to 0x00FF_FFFF 16MB
begin
dec = 16'b0000_0000_00000001;
MUX_SEL = 4'b0000;
end
8'h50: //MEMORY MAP --> 0x5000_0000 to 0x50FF_FFFF 16MB
begin
dec = 16'b0000_0000_0000_0010;
MUX_SEL = 4'b0001;
end
8'h51: //MEMORY MAP --> 0x5100_0000 to 0x51FF_FFFF 16MB
begin
dec =16'b0000_0000_0000_0100;
MUX_SEL = 4'b0010;
end
8'h52: //MEMORY MAP --> 0x5200_0000 to 0x52FF_FFFF 16MB
begin
dec = 16'b0000_0000_0000_1000;
MUX_SEL = 4'b0011;
end
8'h53: //MEMORY MAP --> 0x5300_0000 to 0x53FF_FFFF 16MB
begin
dec = 16'b0000_0000_0001_0000;
MUX_SEL = 4'b0100;
end
8'h54: //MEMORY MAP --> 0x5400_0000 to 0x54FF_FFFF 16MB
begin
dec = 16'b0000_0000_0010_0000;
MUX_SEL = 4'b0101;
end
8'h55: //MEMORY MAP --> 0x5500_0000 to 0x55FF_FFFF 16MB
begin
dec = 16'b0000_0000_0100_0000;
MUX_SEL = 4'b0110;
end
8'h56: //MEMORY MAP --> 0x5600_0000 to 0x56FF_FFFF 16MB
begin
dec = 16'b0000_0000_1000_0000;
MUX_SEL = 4'b0111;
end
8'h57: //MEMORY MAP --> 0x5700_0000 to 0x57FF_FFFF 16MB
begin
dec = 16'b0000_0001_0000_0000;
MUX_SEL = 4'b1000;
end
8'h58: //MEMORY MAP --> 0x5800_0000 to 0x58FF_FFFF 16MB
begin
dec = 16'b0000_0010_0000_0000;
MUX_SEL = 4'b1001;
end
default: //NOMAP
begin
dec = 16'b1000_0000_00000000;
MUX_SEL = 4'b1111;
end
endcase
end
endmodule
AHB地址译码器模块根据地址信号的高八位HADDR[31:24]来输出十个外设使能HSEL与NOMAP信号,和使能外设地址号MUX_SEL,其中各信号映射如表2.1。
HADDR[31:24] | dec | MUX_SEL | MEMORY MAP |
---|---|---|---|
8’h00 | HSEL_S0 | 0 | 0x0000_0000 to 0x00FF_FFFF 16MB |
8’h50 | HSEL_S1 | 1 | 0x5000_0000 to 0x00FF_FFFF 16MB |
8’h51 | HSEL_S2 | 2 | 0x5100_0000 to 0x00FF_FFFF 16MB |
8’h52 | HSEL_S3 | 3 | 0x5200_0000 to 0x00FF_FFFF 16MB |
8’h53 | HSEL_S4 | 4 | 0x5300_0000 to 0x00FF_FFFF 16MB |
8’h54 | HSEL_S5 | 5 | 0x5400_0000 to 0x00FF_FFFF 16MB |
8’h55 | HSEL_S6 | 6 | 0x5500_0000 to 0x00FF_FFFF 16MB |
8’h56 | HSEL_S7 | 7 | 0x5600_0000 to 0x00FF_FFFF 16MB |
8’h57 | HSEL_S8 | 8 | 0x5700_0000 to 0x00FF_FFFF 16MB |
8’h58 | HSEL_S9 | 9 | 0x5800_0000 to 0x00FF_FFFF 16MB |
default | HSEL_NOMAP | 15 | none |
选择从设备的读数据和ready信号给主设备。在地址阶段锁存MUX_SEL,在数据阶段输出READY(RESPONSE貌似外设都没用到)和RDATA。由代码可知,S0(即片上存储器)必须先READY
module AHBMUX(
//GLOBAL CLOCK & RESET
input wire HCLK,
input wire HRESETn,
//MUX SELECT FROM ADDRESS DECODER
input wire [3:0] MUX_SEL,
//READ DATA FROM ALL THE SLAVES
input wire [31:0] HRDATA_S0,
input wire [31:0] HRDATA_S1,
input wire [31:0] HRDATA_S2,
input wire [31:0] HRDATA_S3,
input wire [31:0] HRDATA_S4,
input wire [31:0] HRDATA_S5,
input wire [31:0] HRDATA_S6,
input wire [31:0] HRDATA_S7,
input wire [31:0] HRDATA_S8,
input wire [31:0] HRDATA_S9,
input wire [31:0] HRDATA_NOMAP,
//READYOUT FROM ALL THE SLAVES
input wire HREADYOUT_S0,
input wire HREADYOUT_S1,
input wire HREADYOUT_S2,
input wire HREADYOUT_S3,
input wire HREADYOUT_S4,
input wire HREADYOUT_S5,
input wire HREADYOUT_S6,
input wire HREADYOUT_S7,
input wire HREADYOUT_S8,
input wire HREADYOUT_S9,
input wire HREADYOUT_NOMAP,
//MULTIPLEXED HREADY & HRDATA TO MASTER
output reg HREADY,
output reg [31:0] HRDATA
);
reg [3:0] APHASE_MUX_SEL; // LATCH THE ADDRESS PHASE MUX_SELECT
// TO SEND THE APPROPRIATE RESPONSE & RDATA
// IN THE DATA PHASE
always@ (posedge HCLK or negedge HRESETn)
begin
if(!HRESETn)
APHASE_MUX_SEL <= 4'h0;
else if(HREADY) // NOTE: ALL THE CONTROL SIGNALS ARE VALID ONLY IF HREADY = 1'b1
APHASE_MUX_SEL <= MUX_SEL;
end
always@*
begin
case(APHASE_MUX_SEL)
4'b0000: begin // SELECT SLAVE0 RESPONSE & DATA IF PREVIOUS APHASE WAS FOR S0
HRDATA = HRDATA_S0;
HREADY = HREADYOUT_S0;
end
4'b0001: begin
HRDATA = HRDATA_S1;
HREADY = HREADYOUT_S1;
end
4'b0010: begin
HRDATA = HRDATA_S2;
HREADY = HREADYOUT_S2;
end
4'b0011: begin
HRDATA = HRDATA_S3;
HREADY = HREADYOUT_S3;
end
4'b0100: begin
HRDATA = HRDATA_S4;
HREADY = HREADYOUT_S4;
end
4'b0101: begin
HRDATA = HRDATA_S5;
HREADY = HREADYOUT_S5;
end
4'b0110: begin
HRDATA = HRDATA_S6;
HREADY = HREADYOUT_S6;
end
4'b0111: begin
HRDATA = HRDATA_S7;
HREADY = HREADYOUT_S7;
end
4'b1000: begin
HRDATA = HRDATA_S8;
HREADY = HREADYOUT_S8;
end
4'b1001: begin
HRDATA = HRDATA_S9;
HREADY = HREADYOUT_S9;
end
default: begin
HRDATA = HRDATA_NOMAP;
HREADY = HREADYOUT_NOMAP;
end
endcase
end
endmodule
软件程序最终会被翻译为机器指令,片上存储器就是存储机器指令的地方,由FPGA上的BRAM(块存储器)实现
// --
module AHB2MEM
#(parameter MEMWIDTH = 10) // SIZE = 1KB = 256 Words
(
//AHBLITE INTERFACE
//Slave Select Signals
input wire HSEL,
//Global Signal
input wire HCLK,
input wire HRESETn,
//Address, Control & Write Data
input wire HREADY,
input wire [31:0] HADDR,
input wire [1:0] HTRANS,
input wire HWRITE,
input wire [2:0] HSIZE,
input wire [31:0] HWDATA,
// Transfer Response & Read Data
output wire HREADYOUT,
output wire [31:0] HRDATA,
//LED Output
output wire [7:0] LED
);
assign HREADYOUT = 1'b1; // Always ready
// Registers to store Adress Phase Signals
reg APhase_HSEL;
reg APhase_HWRITE;
reg [1:0] APhase_HTRANS;
reg [31:0] APhase_HADDR;
reg [2:0] APhase_HSIZE;
// Memory Array
reg [31:0] memory[0:(2**(MEMWIDTH-2)-1)];
initial
begin
(*rom_style="block"*) $readmemh("code.hex", memory);
end
// Sample the Address Phase
always @(posedge HCLK or negedge HRESETn)
begin
if(!HRESETn)
begin
APhase_HSEL <= 1'b0;
APhase_HWRITE <= 1'b0;
APhase_HTRANS <= 2'b00;
APhase_HADDR <= 32'h0;
APhase_HSIZE <= 3'b000;
end
else if(HREADY)
begin
APhase_HSEL <= HSEL;
APhase_HWRITE <= HWRITE;
APhase_HTRANS <= HTRANS;
APhase_HADDR <= HADDR;
APhase_HSIZE <= HSIZE;
end
end
// Decode the bytes lanes depending on HSIZE & HADDR[1:0]
wire tx_byte = ~APhase_HSIZE[1] & ~APhase_HSIZE[0];
wire tx_half = ~APhase_HSIZE[1] & APhase_HSIZE[0];
wire tx_word = APhase_HSIZE[1];
wire byte_at_00 = tx_byte & ~APhase_HADDR[1] & ~APhase_HADDR[0];
wire byte_at_01 = tx_byte & ~APhase_HADDR[1] & APhase_HADDR[0];
wire byte_at_10 = tx_byte & APhase_HADDR[1] & ~APhase_HADDR[0];
wire byte_at_11 = tx_byte & APhase_HADDR[1] & APhase_HADDR[0];
wire half_at_00 = tx_half & ~APhase_HADDR[1];
wire half_at_10 = tx_half & APhase_HADDR[1];
wire word_at_00 = tx_word;
wire byte0 = word_at_00 | half_at_00 | byte_at_00;
wire byte1 = word_at_00 | half_at_00 | byte_at_01;
wire byte2 = word_at_00 | half_at_10 | byte_at_10;
wire byte3 = word_at_00 | half_at_10 | byte_at_11;
// Writing to the memory
// Student Assignment: Write a testbench & simulate to spot bugs in this Memory module
always @(posedge HCLK)
begin
if(APhase_HSEL & APhase_HWRITE & APhase_HTRANS[1])
begin
if(byte0)
memory[APhase_HADDR[MEMWIDTH:2]][7:0] <= HWDATA[7:0];
if(byte1)
memory[APhase_HADDR[MEMWIDTH:2]][15:8] <= HWDATA[15:8];
if(byte2)
memory[APhase_HADDR[MEMWIDTH:2]][23:16] <= HWDATA[23:16];
if(byte3)
memory[APhase_HADDR[MEMWIDTH:2]][31:24] <= HWDATA[31:24];
end
end
// Reading from memory
assign HRDATA = memory[APhase_HADDR[MEMWIDTH:2]];
// Diagnostic Signal out
assign zeroth_location = 0;
assign LED = memory[zeroth_location][7:0];
endmodule
分析下面这一段代码,若将表1.3中的7种情况编号,则byte0表示第1、5、7种情况,byte1表示第2、5、7种情况,byte2表示第3、6、7种情况,byte1表示第4、6、7种情况。
APhase_HADDR[MEMWIDTH:2]表示把输入的地址除以4,为什么要这样做?因为一个字有四个字节。S0端口号对应的地址范围为0x00000000~0x00FFFFFF,而片上存储器只有1kb,所以其地址范围为0x00000000~0x000003FF,即MEMWIDTH那么多位的空间,但要右移2位,再写入对应的字节通道,因为一个字有四个字节。所以知道为什么C++要字节对齐了吧。
wire byte0 = word_at_00 | half_at_00 | byte_at_00;
wire byte1 = word_at_00 | half_at_00 | byte_at_01;
wire byte2 = word_at_00 | half_at_10 | byte_at_10;
wire byte3 = word_at_00 | half_at_10 | byte_at_11;
// Writing to the memory
// Student Assignment: Write a testbench & simulate to spot bugs in this Memory module
always @(posedge HCLK)
begin
if(APhase_HSEL & APhase_HWRITE & APhase_HTRANS[1])
begin
if(byte0)
memory[APhase_HADDR[MEMWIDTH:2]][7:0] <= HWDATA[7:0];
if(byte1)
memory[APhase_HADDR[MEMWIDTH:2]][15:8] <= HWDATA[15:8];
if(byte2)
memory[APhase_HADDR[MEMWIDTH:2]][23:16] <= HWDATA[23:16];
if(byte3)
memory[APhase_HADDR[MEMWIDTH:2]][31:24] <= HWDATA[31:24];
end
end
其中这一段,是将程序文件预加载到硬件中,因为要将生成的软件程序镜像文件与硬件文件合并。但是为什么这里memory加载了软件程序后还能赋值HWDATA呢? 后续揭晓
initial
begin
(*rom_style="block"*) $readmemh("code.hex", memory);
end
将写数据的低八位显示在8个LED灯上
module AHB2LED(
//AHBLITE INTERFACE
//Slave Select Signals
input wire HSEL,
//Global Signal
input wire HCLK,
input wire HRESETn,
//Address, Control & Write Data
input wire HREADY,
input wire [31:0] HADDR,
input wire [1:0] HTRANS,
input wire HWRITE,
input wire [2:0] HSIZE,
input wire [31:0] HWDATA,
// Transfer Response & Read Data
output wire HREADYOUT,
output wire [31:0] HRDATA,
//LED Output
output wire [7:0] LED
);
//Address Phase Sampling Registers
reg rHSEL;
reg [31:0] rHADDR;
reg [1:0] rHTRANS;
reg rHWRITE;
reg [2:0] rHSIZE;
reg [7:0] rLED;
//Address Phase Sampling
always @(posedge HCLK or negedge HRESETn)
begin
if(!HRESETn)
begin
rHSEL <= 1'b0;
rHADDR <= 32'h0;
rHTRANS <= 2'b00;
rHWRITE <= 1'b0;
rHSIZE <= 3'b000;
end
else if(HREADY)
begin
rHSEL <= HSEL;
rHADDR <= HADDR;
rHTRANS <= HTRANS;
rHWRITE <= HWRITE;
rHSIZE <= HSIZE;
end
end
//Data Phase data transfer
always @(posedge HCLK or negedge HRESETn)
begin
if(!HRESETn)
rLED <= 8'b0000_0000;
else if(rHSEL & rHWRITE & rHTRANS[1])
rLED <= HWDATA[7:0];
end
//Transfer Response
assign HREADYOUT = 1'b1; //Single cycle Write & Read. Zero Wait state operations
//Read Data
assign HRDATA = {24'h0000_00,rLED};
assign LED = rLED;
endmodule