ARM Cortex-M0 全可编程SoC原理及实现笔记(1)

这篇具有很好参考价值的文章主要介绍了ARM Cortex-M0 全可编程SoC原理及实现笔记(1)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

对应全书的第九章

一、Cortex-M0架构的全貌是什么

  Cortex-M0架构分为硬件和软件部分,整个片上系统的内部结构如图1.1所示。
arm m0参考手册,与ARM有关的一切,fpga开发,嵌入式硬件

图1.1

1.1硬件部分

硬件部分在FPGA上由纯数字逻辑实现,主要模块包括:
  (1)系统时钟生成器(pll核)
  (2)ARM Cortex-M0微处理器
  (3)AHB-Lite系统总线:
   控制信号,用于同步和识别交易,如:准备,写、读以及传输模式信号
   32位地址总线,用于选择一个外设,或者一个外设中的一个寄存器
   32位数据总线,用于交换数据信息
  (4)两个AHB外设:
   程序存储器,通过FPGA内的块存储器实现
   LED外设
整个硬件部分的设计如图1.2
arm m0参考手册,与ARM有关的一切,fpga开发,嵌入式硬件

图1.2

1.2软件部分

Hello world程序:
  (1)在Keil μVision5中,使用汇编语言对Cortex-M0处理器编程
  (2)建立(build)汇编语言设计文件,生成十六进制的编程文件

1.3AHB_Lite总线

1.3.1AHB_Lite总线操作

总线操作过程如图1.3所示
arm m0参考手册,与ARM有关的一切,fpga开发,嵌入式硬件

图1.3
处理器访问一个AHB-Lite外设的过程

  (1)处理器提供要访问外设的地址信息
  (2)通过地址译码器生成目标外设的选择信号,同时处理器输出一个控制信号,如读写、传输数据的数量等
  (3)若处理器输出的是读控制信号,则待从设备ready之后读数据

1.3.2AHB-Lite主设备接口

  AHB-Lite主设备接口如图1.4和表1.1所示
arm m0参考手册,与ARM有关的一切,fpga开发,嵌入式硬件

图1.4AHB-Lite主设备接口
表1.1AHB-Lite主设备接口信号

arm m0参考手册,与ARM有关的一切,fpga开发,嵌入式硬件
  AHB-Lite有四种基本传输类型,如表1.2,交易的同步和识别由处理器的控制信号给出.

表1.2 AHB-Lite交易类型
交易 访问 描述
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所示

表1.3 交易对齐方式

arm m0参考手册,与ARM有关的一切,fpga开发,嵌入式硬件

1.4Cortex-M0处理器端口描述

arm m0参考手册,与ARM有关的一切,fpga开发,嵌入式硬件
arm m0参考手册,与ARM有关的一切,fpga开发,嵌入式硬件

1.5处理器存储器映射属性

arm m0参考手册,与ARM有关的一切,fpga开发,嵌入式硬件
arm m0参考手册,与ARM有关的一切,fpga开发,嵌入式硬件

二、Cortex-M0架构在数字逻辑上怎么实现

看代码,怎么才算看懂代码或者数学公式?能用中文说出来就算看懂

2.1顶层文件AHBLITE_SYS

  代码如下


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

2.2系统主时钟IP核

输出20MHz时钟作为系统主时钟

2.3AHB总线地址译码器AHBDCD

  注意该模块为纯组合逻辑,没有全局时钟和复位信号

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
表2.1
  该表是各外设在ram中的地址映射,每个外设都分配了16MB的地址,注意s0外设的起始位与其他的不一样,外设与ram中的地址映射可参考CM0-DS手册,其中HSEL_S0与HSEL_S1将分别与外部存储器和LED模块相连。   对于32位地址信号HADDR,0x40000000~0x5FFFFFFF的部分是推荐给外设使用的。

2.4 AHB总线从设备多路复用器

  选择从设备的读数据和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

2.5 AHB片上存储器外设

  软件程序最终会被翻译为机器指令,片上存储器就是存储机器指令的地方,由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

2.6 AHB LED外设

  将写数据的低八位显示在8个LED灯上文章来源地址https://www.toymoban.com/news/detail-787633.html

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


到了这里,关于ARM Cortex-M0 全可编程SoC原理及实现笔记(1)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 可编程网关:如何助力智慧工厂实现智能化管理

    一个具体的实际案例,详细说明可编程网关在某汽车零部件智慧工厂中的应用细节: 案例背景: 某大型汽车零部件制造企业,致力于提升生产效率、降低运营成本、确保产品质量,决定对其传统工厂进行全面数字化改造,构建智慧工厂。其中,可编程网关作为关键组件,被

    2024年04月08日
    浏览(27)
  • Verilog实现FPGA可编程电路中的RAM存储器

    Verilog实现FPGA可编程电路中的RAM存储器 在FPGA可编程电路的设计中,RAM存储器通常被广泛使用。而手写RAM存储器则可以提供更加灵活、高效的设计方案。本文将介绍如何使用Verilog语言来手写FPGA中的RAM存储器。 首先,我们需要确定RAM存储器的大小和宽度。假设我们需要实现一个

    2024年02月04日
    浏览(36)
  • 【ARM微控制器】STM32L486VGT6【FPGA】XC3S700A-4FTG256I现场可编程门阵列基本介绍

    STM32L486VGT6是超低功耗微控制器,基于高性能的 ARM®Cortex®-M4 32 位 RISC 内核,工作频率高达 80MHz。Cortex-M4 内核具有单浮点单元(SFPU)精度,支持所有 ARM 单精度数据处理指令与数据类型。同时执行全套 DSP 指令和存储保护单元(MPU),增强应用安全性。 核心处理器:ARM® Cort

    2023年04月09日
    浏览(28)
  • 用可编程逻辑器件FPGA LCMXO2-4000HC-6MG132I 实现智能汽车解决方案设计

    LCMXO2-4000HC-6MG132I lattice莱迪斯深力科 MachXO2 可编程逻辑器件 (PLD) 由六个超低功耗、即时启动、非易失性 PLD 组成,可提供 256 至 6864 个查找表 (LUT) 的密度。 MachXO2 系列 PLD 提供多种特性,例如嵌入式块 RAM (EBR)、分布式 RAM 和用户闪存 (UFM),这些特性使这些器件能够用于低成本、

    2024年02月07日
    浏览(28)
  • DPU — 完全可编程网络

    类比的,完全可编程平台就像 “智能手机” 一样,手机(硬件)是一个平台,上面的 APP(业务)完全由用户自己决定。 完全可编程的原则: 软件定义一切,硬件加速一切。 业务逻辑可实现。 抽象硬件,编程接口统一。 但实际上,目前的 DPU 产品仍处于 “功能机” 的阶段

    2023年04月08日
    浏览(30)
  • 可编程逻辑阵列PLA

    一、集成电路的发展和现状        随着电子技术的发展,人类社会已进入数字时代,数字系统广泛应用于计算机、数据处理、通信与测量等领域,在我们日常生活中起着越来越重要的作用。由于数字系统比模拟系统有更高的精确度和可靠性,以前用模拟系统完成的许多任务

    2023年04月08日
    浏览(21)
  • UnityShader——03图形硬件简史与可编程管线

    GPU英文全称Graphic Processing Unit,中文翻译为“图形处理器”,在现代计算机系统中的作用变得越来越重要 20世纪六七十年代,受硬件条件的限制,图形显示器只是计算机输出的一种工具,限于硬件发展水平。人们只是纯粹从软件实现的角度来考虑图形用户界面的规范问题,此

    2024年02月19日
    浏览(26)
  • 可编程逻辑器件之数码管显示实验

    一、实验目标 能够熟练的进行可编程逻辑器件开发,能够通过具体工程需求进行需求分析、模块划分、代码编写、功能仿真、综合分析、板级验证,能够独立正确的进行实验操作,培养学生的工程实践研究能力和动手实践能力,具备借助可编程逻辑器件开发平台和仿真工具科

    2024年02月02日
    浏览(91)
  • 什么是 FPGA(现场可编程门阵列)?

    现场编程门阵列是一种由半导体材料制成的集成电路,用户购买后可以重新编程或配置,而不是单独由原始设备制造商(OEM)进行。 现场可编程门阵列 (FPGA) 是一种半导体器件,由与可编程互连相结合的可配置逻辑块 (CLB) 网格构成。制造完成后,FPGA 可以重新编程以满足特定

    2024年02月19日
    浏览(37)
  • SG-8201CJA(汽车可编程晶体振荡器)

    nbsp; nbsp; nbsp; nbsp; nbsp;爱普生的SG-8021CJA是一款符合AEC-Q100标准的晶体振荡器,专为要求苛刻的汽车/ADAS应用(如激光雷达和相机ECU)而设计。它采用爱普生的内部低噪声小数NPLL,输出nbsp;频率高达170MHz,相位抖动小于1/25,稳定性比之前的产品SG-8101CGA高出约2倍。此外,2.0*1.6m

    2024年02月21日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包