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

对应全书的第九章

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

  Cortex-M0架构分为硬件和软件部分,整个片上系统的内部结构如图1.1所示。
在这里插入图片描述

图1.1

1.1硬件部分

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

图1.2

1.2软件部分

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

1.3AHB_Lite总线

1.3.1AHB_Lite总线操作

总线操作过程如图1.3所示
在这里插入图片描述

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

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

1.3.2AHB-Lite主设备接口

  AHB-Lite主设备接口如图1.4和表1.1所示
在这里插入图片描述

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

在这里插入图片描述
  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 交易对齐方式

在这里插入图片描述

1.4Cortex-M0处理器端口描述

在这里插入图片描述
在这里插入图片描述

1.5处理器存储器映射属性

在这里插入图片描述
在这里插入图片描述

二、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]decMUX_SELMEMORY MAP
8’h00HSEL_S000x0000_0000 to 0x00FF_FFFF 16MB
8’h50HSEL_S110x5000_0000 to 0x00FF_FFFF 16MB
8’h51HSEL_S220x5100_0000 to 0x00FF_FFFF 16MB
8’h52HSEL_S330x5200_0000 to 0x00FF_FFFF 16MB
8’h53HSEL_S440x5300_0000 to 0x00FF_FFFF 16MB
8’h54HSEL_S550x5400_0000 to 0x00FF_FFFF 16MB
8’h55HSEL_S660x5500_0000 to 0x00FF_FFFF 16MB
8’h56HSEL_S770x5600_0000 to 0x00FF_FFFF 16MB
8’h57HSEL_S880x5700_0000 to 0x00FF_FFFF 16MB
8’h58HSEL_S990x5800_0000 to 0x00FF_FFFF 16MB
defaultHSEL_NOMAP15none
表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灯上

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


  • 11
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: ARM Cortex-M0是一种可编程SOC(系统级芯片),它的原理是将处理器、内存、外设等多个功能模块集成在一个芯片上,实现了高度集成化的设计。Cortex-M0采用了ARM架构,具有低功耗、高性能、易于编程等特点,广泛应用于物联网、智能家居、工业控制等领域。 实现Cortex-M0 SOC需要进行多个步骤,包括设计芯片架构、选择器件、编写软件等。首先,需要确定芯片的功能需求和性能指标,设计出合适的架构。然后,选择适合的器件,包括处理器、存储器、外设等,进行芯片的布局和布线。最后,编写软件,包括底层驱动程序、操作系统、应用程序等,实现芯片的功能。 总之,ARM Cortex-M0可编程SOC实现需要进行多个步骤,包括芯片架构设计、器件选择和软件编写等,需要具备丰富的硬件和软件开发经验。 ### 回答2: ARM Cortex-M0是一种精简型微控制器(MCU)的处理器核心,广泛应用于普通消费电子产品、智能物联网、低功耗应用等多个领域。ARM Cortex-M0采用3级流水线的指令执行架构和16/32位的总线结构,在搭载外设、调度内部资源和处理I/O操作等方面表现优异,同时还具有低功耗性、强大的数据处理能力和高效的价格性能比。ARM Cortex-M0 可编程SOC原理实现正是基于ARM Cortex-M0处理器核心的MCU核心,具有以下几个关键特征: 首先,ARM Cortex-M0可编程性是其最大的特点之一。SOC可编程性通常包括芯片基础可编程、可重构逻辑实现可编程存储器等,ARM Cortex-M0采用的可编程方案是基于其流水线架构和编程模型。MCU核心芯片通过开放的软件编程接口(API)向外界提供可编程的开放式体系结构。这样,用户可以将其功能需求通过编程进行灵活的配置和扩展。 其次,ARM Cortex-M0可编程SOC依赖于外设和内核资源的完美协调。ARM Cortex-M0可编程SOC一般被设计成包括多个IO、通信、控制和运算等外设单元,同时还包括中央处理单元(CPU)、DMA控制器、定时器和触摸控制器等多种内核资源。这些内核资源和外设单元靠编程方式连接到一起,CPUCPU通过中断机制、DMA控制器与I/O设备直接交换数据,实现了数据在外设间的传输,提高系统运行效率。 最后,ARM Cortex-M0可编程SOC实现依赖于设计工具和技术的支持。ARM Cortex-M0可编程SOC实现需要用到各种先进的技术和设计工具,如芯片设计技术、加密算法和嵌入式软件开发技术等。此外,各种先进的设计工具如MATLAB、Cortex-M0开发板和仿真工具等可以帮助开发者轻松实现ARM Cortex-M0可编程SOC的各项功能,提高产品的研发速度和效率。 总之,ARM Cortex-M0可编程SOC是基于现有技术和芯片设计工具,依托ARM Cortex-M0处理器核心、外设和高效的软件编程接口(API)实现的一种可编程型微控制器(MCU)核心。其优势在于灵活的编程体验、高效的数据传输能力和图形化的编程工具支持,从而为设计者提供了更多的创意空间和产品实现方案。 ### 回答3: ARM Cortex-M0可编程SOC是一种低功耗的嵌入式处理器系统。该处理器系统包含了ARMCortex-M0内核,还包括了片上内存、外设、以及通信接口等。其实现方式可以分为两个方面:硬件实现和软件实现。 硬件实现方面,ARM Cortex-M0可编程SOC采用了先进的28纳米工艺,以及一些先进的设备。在系统中,ARM Cortex-M0内核与片上外设之间通过总线进行连接。而通信接口则是通过串口或者USB实现,在系统设计过程中可以根据需求选择适合的通信接口。此外,该系统还包含有SRAM,FLASH等片上内存组件。其中,SRAM是用于存储栈空间、寄存器和其他变量的,而FLASH则是用于存储应用程序和数据的。 软件实现方面,ARM Cortex-M0可编程SOC通过ARM的软件开发工具链进行开发。其中,主要的开发工具包括C/C++编译器、调试器、仿真器等。系统设计者可以使用这些工具进行应用程序的编译、调试和仿真等操作。此外,还可以使用ARM的软件库来加速应用程序的开发。这些软件库包括CMSIS(Cortex Microcontroller Software Interface Standard)、HAL(Hardware Abstraction Layer)等。这些库提供了许多已经被验证的软件组件,可以使系统设计者更加快速、简单地开发基于ARM Cortex-M0可编程SOC的应用程序。 总之,ARM Cortex-M0可编程SOC可以提供强大的处理性能、通信接口和片上外设,同时还可以基于ARM开发工具链和软件库快速地开发应用程序。这使得它成为了众多嵌入式设备的理想选择。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值