华大半导体HC32F4A0系列ARM芯片EXMC并口通信时序的FPGA实现

华大半导体HC32F4A0系列ARM芯片EXMC并口通信时序的FPGA实现

EXMC简介

外部存储器控制器EXMC是一个用来访问各种片外存储器、实现数据交换的独立模块。EXMC通过配置可以把内部的AMBA协议接口转换为各种类型的专用片外存储器通信协议接口。
其中将 SRAM/PSRAM/NOR Flash 控制器定义为 SMC(Static Memory Controller)、SDRAM 控制器定义为 DMC(Dynamic Memory Controller)、NAND Flash 控制器定义为NFC(NAND Flash Memory Controller),本文章将在FPGA上实现三种模式中的SMC模式。

EXMC-SMC读时序分析

在这里插入图片描述
如图4-2为ARM芯片EXMC并口的读时序,其中并口与FPGA通信的数据位宽可分为8位、16位、32位。具体的,本文将以16位宽接收数据(一次接收2个字节数据)为例进行分析。
首先需要了解图中接口信号的含义。信号SMC_CS表示为片选信号、SMC_OE为读使能信号、SMC_BLS为字节选通信号(本设计中不用该信号)、SMC_ADD为地址信号、SMC_DATA为16位数据。
接下来就是对图中的时序进行分析了,由图可知,在整个读数据的过程中片选信号SMC_CS是一直保持低电平的,而在读使能信号SMC_OE的每个下降沿时将进行锁地址操作(每个下降沿锁一个地址),在SMC_OE的每一个上升沿将读取数据(每个上升沿读一个16bit数据),这样一来将上述分析内容转化为Verilog代码就比较简单了。

EXMC-SMC写时序分析

在这里插入图片描述
如图4-3为为ARM芯片EXMC并口的写时序,其中并口与FPGA通信的数据位宽可分为8位、16位、32位。同样本文将以16位宽发送数据(一次发送2个字节数据)为例进行分析。
其中信号SMC_CS表示为片选信号、SMC_WE为写使能信号、SMC_BLS为字节选通信号(本设计中不用该信号)、SMC_ADD为地址信号、SMC_DATA为16位数据。
由图可知,在整个写数据的过程中片选信号SMC_CS是一直保持低电平的,在写使能信号SMC_WE的下降沿将进行锁地址操作,在这里需要注意的是。在进行一次锁地址操作时它会连续给出4个地址(如图中的Add、Add+1、Add+2、Add+3),但此时只有第一个地址Add对应的数据有效,而后三个地址对应的数据全部都为不定态X,因此在写时序中,在每个写使能的下降沿我们只锁第一个地址,并且将此地址对应的数据写出。接下来为EXMC读写时序的Verilog实现。

EXMC-SMC读写时序Verilog实现

module HC32_EXMC_SMC #(
	parameter AD_WIDTH = 12,
	parameter DATA_WIDTH = 16,
)(
	input wire clk,
	input wire rst,	
	inout wire [15:0] ARM_DATA_Inout,
	input wire [AD_WIDTH -1:0] ARM_ADDR_In,
	input wire ARM_NOE_In,
	input wire ARM_NWE_In,
	input wire ARM_NCE_In,
	
	output reg [AD_WIDTH -1:0] FPGA_ad,
	input wire [DATA_WIDTH -1:0] FPGA_data_in,
	output reg [DATA_WIDTH -1:0] FPGA_data_out
);

reg noe;
reg noe_dly1;
reg noe_diy2;
reg nwe_dly1;
reg nwe_diy2;
reg nce_dly1;
reg nce_diy2;
reg noe_neg;
reg nce_neg;
reg nwe_neg;
reg nwe_cnt;

//第一步:取片选、读写使能边沿、打拍防止亚稳态
always @(posedge clk)
begin
	if(rst)
	begin
		noe_dly1 <= 1;
		noe_dly2 <= 1;
	end
	else
	begin
		noe_dly1 <= ARM_NOE_In;						//读使能打两拍
		noe_dly2 <= noe_dly1  ;
		noe_neg  <= noe_dly2  & ~noe_dly1;		//取读使能下降沿
		noe_pos  <= ~noe_dly2  & noe_dly1;		//取读使能上升沿
	end
end

always @(posedge clk)
begin
	if(rst)
	begin
		nwe_dly1 <= 1;
		nwe_dly2 <= 1;
		nce_dly1 <= 1;
		nce_dly2 <= 1;
	end
	else
	begin
		nce_dly1 <= ARM_NCE_In;					//片选信号打两拍
		nce_dly2 <= nce_dly1  ;
		nce_neg  <= nce_dly2  & ~nce_dly1;	//取片选下降沿

		nwe_dly1 <= ARM_NWE_In;				//写使能打两拍
		nwe_dly2 <= nwe_dly1  ;
		nwe_neg  <= nwe_dly2  & ~nwe_dly1;	//取写使能下降沿
	end
end

//第二步:锁读写地址
always @(posedge clk)
begin
	if(rst)
		nwe_cnt <= 2'b0;
	else if(nce_neg)
		nwe_cnt <= 2'b0;
	else if(nwe_neg && !nce_dly1)	
		nwe_cnt <= nwe_cnt +1'b1;	
	else if(nwe_cnt== 2'd4)				//会给出连续4个地址,只锁第一个地址,后三个地址无效
		nwe_cnt <= 2'b0;				
	else
		nwe_cnt <=nwe_cnt ;				
end

always @(posedge clk)
begin
	if(nce_dly1 == 0)
	begin
		if((noe_neg) || (nwe_neg && (nwe_cnt  == 0)))			//会给出连续4个地址,只锁第一个地址,后三个地址无效
		begin
			FPGA_ad <= ARM_ADDR_In;				
		end
	end			
end

//写数据
always @(posedge clk)
begin
	if(nce_dly1 == 0)
	begin
		if(nwe_neg  && (nwe_cnt  == 0))			
		begin
			FPGA_data_out<= ARM_DATA_Inout;				
		end
	end			
end

//读数据
always @(posedge clk)
begin
	if(rst)
	begin
		noe <= 1;
	end
	else
	begin
		if(!nce_dly1 && noe_pos)
		begin
			noe <= 0;
		end
		else if(nce_dly1 && !noe_pos)
			noe <= 1;
		else
			noe <= noe;
	end		
end

assign ARM_DATA_Inout = (ARM_NCE_In ==0 && noe == 0) ? FPGA_data_in :'bz;

endmodule

EXMC读写时序仿真波形图

在这里插入图片描述

如图即为EXMC接口的读写时序仿真波形图,与数据手册中的时序一致。

猜你喜欢

转载自blog.csdn.net/m0_51575600/article/details/130712494
今日推荐