fpga设计——spiflash启动之mc8051设计

author author     2022-08-20     160

关键词:

1. 概述

本设计采用FPGA技术,在FPGA中实现8051单片机的软核,将外部SPI Flash中的代码数据加载到FPGA内部ram,然后复位MC8051,实现外部flash启动MC8051。


2. 系统框图

8051采用Oregano Systems公司开源的MC8051软核。SPI Flash采用W25Q16芯片存储8051的代码程序。系统框图如下:

技术分享


3. MC8051简介

Oregano Systems的8051单片机采用VHDL语言开发,具有如下特点:

  • 采用完全同步设计

  • 指令集和标准 8051 微控制器完全兼容

  • 指令执行时间为 1~4 个时钟周期,执行性能优于标准 8051 微控制器 8 倍左右

  • 用户可选择定时器/计数器、串行接口单元的数量

  • 新增了特殊功能寄存器用于选择不同的定时器/计数器、串行接口单元

  • 可选择是否使用乘法器(乘法指令 MUL)

  • 可选择是否使用除法器(除法指令 DIV)

  • 可选择是否使用十进制调整功能(十进制调整指令 DA)

  • I/O 口不复用

  • 内部带 256Bytes RAM

  • 最多可扩展至 64Kbytes 的 ROM 和 64Kbytes 的 RAM

  • 最多可扩展至 64Kbytes 的 ROM 和 64Kbytes 的 RAM

MC8051 IP Core的顶层结构如下图所示:

技术分享


4. MC8051移植

在mc8051_p.vhd中,更改C_IMPL_N_TMR、C_IMPL_N_SIU、C_IMPL_N_EXT的值可以定义定时器和外部中断的数量。

  -----------------------------------------------------------------------------
  -- Select how many timer/counter units should be implemented
  -- Default: 1
  constant C_IMPL_N_TMR : integer := 1;
  -----------------------------------------------------------------------------

  -----------------------------------------------------------------------------
  -- Select how many serial interface units should be implemented
  -- Default: C_IMPL_N_TMR ---(DO NOT CHANGE!)---		     
  constant C_IMPL_N_SIU : integer := C_IMPL_N_TMR;
  -----------------------------------------------------------------------------
				     
  -----------------------------------------------------------------------------
  -- Select how many external interrupt-inputs should be implemented
  -- Default: C_IMPL_N_TMR ---(DO NOT CHANGE!)---
  constant C_IMPL_N_EXT : integer := C_IMPL_N_TMR;
  -----------------------------------------------------------------------------

在mc8051_p.vhd中,还可以选择需要的指令,可选的指令有MUL/DIV/DA。

  -----------------------------------------------------------------------------
  -- Select whether to implement (1) or skip (0) the multiplier
  -- Default: 1
  constant C_IMPL_MUL : integer := 1;
  -----------------------------------------------------------------------------

  -----------------------------------------------------------------------------
  -- Select whether to implement (1) or skip (0) the divider
  -- Default: 1
  constant C_IMPL_DIV : integer := 1;
  -----------------------------------------------------------------------------
				   
  -----------------------------------------------------------------------------
  -- Select whether to implement (1) or skip (0) the decimal adjustment command
  -- Default: 1
  constant C_IMPL_DA  : integer := 1;
  -----------------------------------------------------------------------------

在FPGA中用内部的ram资源构建一个rom和一个ram以供8051使用,其中rom需为双端口,用于spi_flash_controller加载flash中的程序。


5. SPI Flash简介

SPI Flash芯片是由8192个页组成,每页大小为256字节。16页组成一个扇区,128/256页组成一个块,其结构框图如下:

技术分享

SPI Flash的读写指令如下:

技术分享

技术分享


6. SPI Flash控制器设计

SPI Flash的读写时序如下:其他操作的时序可查看spi flash datasheet。

技术分享

技术分享

控制器状态机设计如下:

技术分享


SPI Flash加载控制逻辑代码如下:

//file name:	spi_flash_load.v
//author:		shugen.yin
//date:			2017.1.5
//function:		load code from spi flash to dram
//log:

module spi_flash_load(
	//Global signal
	input clk,
	input rst_n,

	//signal from and to SPI reader
	output reg rd_start,
	output reg [31:0] rd_addr,
	output reg [31:0] rd_length,
	input      [7:0] rd_data,
	input      rd_data_valid,
	input      read_busy,
	
	//signal to mc8051
	input      [15:0] rdaddress,
	output     [7:0]  data_out,
	output     reg    reset

);

reg [15:0] wraddress;

always @(posedge clk)
	if(rd_data_valid)
		wraddress <= wraddress + 1‘b1;
	else
		wraddress <= wraddress;
		

dpram	dpram_inst (
	.clock ( clk ),
	.data ( rd_data ),
	.rdaddress ( rdaddress ),
	.wraddress ( wraddress ),
	.wren ( rd_data_valid ),
	.q ( data_out )
	);

reg [15:0] spi_cnt;

always @(posedge clk)
	if(spi_cnt<=16‘h0fff)
		spi_cnt <= spi_cnt + 1‘b1;
	else
		spi_cnt <= spi_cnt;

always @(posedge clk)
	if(spi_cnt==1)
	begin
		rd_start <= 1‘b1;
		rd_addr  <= ‘h0;
		rd_length<= ‘h1000;
	end
	else
	begin
		rd_start <= 1‘b0;
		rd_addr  <= rd_addr;
		rd_length<= rd_length;	
	end	

	
always @(posedge clk)
	if(spi_cnt==16‘h1000)
	   reset <= 0;
	else
		reset <= 1‘b1;

endmodule


7. MC8051 C语言开发

这里采用Keil uVision4作为开发平台,用到MC8051的I/0和定时器设备,代码设计如下:

#include <reg51.h>

sbit P00=P0^0;

char i=100;

unsigned char led=0;

void Timer0_init(void)
{
	TMOD = 0x01;	//set timer0 as mode-1
	TH0  = 0xee;	
	TL0  = 0x00;
	P00  = 0;
	EA   = 1;		//enable interrupt
	ET0  = 1;		//enable timer0 interrupt
	TR0  = 1;		//Trigger Timer0	
}

void main(void)
{
	Timer0_init();

	while(1){};
}

void Timer0_int(void) interrupt 1
{
	TH0 = 0xee;
	TL0 = 0x00;
	i--;
	if(i<=0)
	{
		led  = ~led;
		i    = 100;
	}	
	P00 = led;
}

编译KEIL工程,得到hex文件:将KEIL生成的hex文件烧写道SPI Flash中。

技术分享


8. FPGA系统逻辑代码设计

FPGA系统逻辑代码顶层设计如下:

//file name			: top_fpga.v
//data				: 2017.1.9
//author			: shugen.yin
//function			: top of project
//log				:

module top_fpga(
	//global signal
	input clk,
	input rst_n,
	
	//led
	output [1:0] led
	);

//----------------MC8051------------------
wire int0_i;
wire int1_i;
wire all_t0_i;
wire all_t1_i;
wire [7:0] p0_i;
wire [7:0] p1_i;
wire [7:0] p2_i;
wire [7:0] p3_i;

(* keep *)wire [7:0] p0_o;
(* keep *)wire [7:0] p1_o;
(* keep *)wire [7:0] p2_o;
(* keep *)wire [7:0] p3_o;

mc8051_top mc8051_top_inst
(
	.clk(clk) ,	// input  clk_sig
	.reset(spi_load_reset) ,	// input  reset_sig
	.int0_i(int0_i) ,	// input [0:0] int0_i_sig
	.int1_i(int1_i) ,	// input [0:0] int1_i_sig
	.all_t0_i(1‘b0) ,	// input [0:0] all_t0_i_sig
	.all_t1_i(1‘b0) ,	// input [0:0] all_t1_i_sig
	.p0_i(p0_i) ,	// input [7:0] p0_i_sig
	.p1_i(p1_i) ,	// input [7:0] p1_i_sig
	.p2_i(p2_i) ,	// input [7:0] p2_i_sig
	.p3_i(p3_i) ,	// input [7:0] p3_i_sig
	.p0_o(p0_o) ,	// output [7:0] p0_o_sig
	.p1_o(p1_o) ,	// output [7:0] p1_o_sig
	.p2_o(p2_o) ,	// output [7:0] p2_o_sig
	.p3_o(p3_o) , 	// output [7:0] p3_o_sig
	
	.dram_adr_o(spi_load_address) ,	//output address
	.dram_data_i(spi_load_data)		//input data
);

assign led = {p0_o[0],~p0_o[0]};

//----------------SPI Flash------------------
wire 			rd_start;
wire [31:0] rd_addr;
wire [31:0] rd_length;
wire [7:0]  rd_data;
wire 		rd_data_valid;
wire		read_busy;

spi_flash_reader spi_flash_reader_inst
(
	//global signal
	.clk(clk),
	.rst_n(rst_n),
	
	//SPI master port
	.spi_dclk(flash_clk),
	.spi_cs_n(flash_cs_n),
	.spi_so(flash_mosi),
	.spi_si(flash_miso),
	
	//export port
	.rd_start(rd_start),
	.rd_addr(rd_addr),
	.rd_length(rd_length),
	.rd_data(rd_data),
	.rd_data_valid(rd_data_valid),
	.read_busy(read_busy)
);

wire [15:0] spi_load_address;
wire [7:0]  spi_load_data;
wire        spi_load_reset;

spi_flash_load spi_flash_load_inst
(
	.clk(clk) ,	                    // input  clk_sig
	.rst_n(rst_n) ,	                // input  rst_n_sig
	.rd_start(rd_start) ,           // output  rd_start_sig
	.rd_addr(rd_addr) ,	            // output [31:0] rd_addr_sig
	.rd_length(rd_length) ,         // output [31:0] rd_length_sig
	.rd_data(rd_data) ,	            // input [7:0] rd_data_sig
	.rd_data_valid(rd_data_valid) ,	// input  rd_data_valid_sig
	.read_busy(read_busy) ,	        // input  read_busy_sig
	.rdaddress(spi_load_address) ,	// output [11:0] rdaddress_sig
	.data_out(spi_load_data), 	    // output [7:0] data_out_sig
	.reset(spi_load_reset)
);

endmodule


9. 最终结果

在Quartus II 13.1平台下,编译完成后,将sof文件下载到板卡上,LED交替闪烁。

技术分享



本文出自 “shugenyin的博客” 博客,请务必保留此出处http://shugenyin.blog.51cto.com/4259554/1890407

fpga教程案例95机器学习2——基于fpga的svm支持向量机二分类系统实现之verilog编程设计

FPGA教程目录​​​​​​MATLAB教程目录目录1.软件版本2.SVM的FPGA实现准备3.Verilog实现 查看详情

fpga设计中遇到的奇葩问题之“芯片也要看出身”

...夜西风凋碧树。独上高楼,望尽天涯路2000年的时候,做设计基本都是使用Xilinx公司的Virtex和Virtex-E系列芯片。那时候Altera技术实力还比较弱,基于Altera的芯片做设计是要被大家diss的。昨夜西风凋碧树。独上高楼,望尽天涯路2000... 查看详情

(电工基地笔记)vivado固化至spiflash

如果从头开始做SPIFlash固化是有一些麻烦的,要在完成综合之后,打开 synthesizedDesign(图) (图)  然后在synthesizedDesign打开状态下,选择Tools->EditDeviceProperties编辑器件属性(图)  我们这个FPGA有16MFlash,... 查看详情

fpga技巧篇四fpga设计的四种常用思想与技巧之四:数据同步化

欢迎大家关注我的微信公众账号,支持程序媛写出更多优秀的文章 1输入数据同步化的原则(1)如果输入数据的节拍和本级芯片的处理时钟同频,可以直接用本级芯片的主时钟对输入数据寄存器采样,完成输入数据的同步化... 查看详情

zynq之fpga学习----vivado软件使用(代码片段)

...signSuite是Xilinx公司的综合性FPGA开发软件,可以完成从设计输入到硬件配置的完整FPGA设计流程。Vivado学习使用版本为Vivadov18.3Vivado软件使用流程:新建工程设计输入分析与综合约束输入设计实现生成和下载比特流1.1新建工... 查看详情

zynq之fpga学习----vivado功能仿真(代码片段)

...真阅读本文需先学习:FPGA学习----Vivado软件使用典型的FPGA设计流程,如图所示:图片来自《领航者ZYNQ之FPGA开发指南》Vivado设计套件内部集成了仿真器VivadoSimulator,能够在设计流程的不同阶段运行设计的功能仿真和时序... 查看详情

利用fpga实现外设通信接口之:利用fpga实现usb2.0通信接口

...ff0c;开发的风险小,而且性能稳定,因此被大部分设计者所采用。而第二种方式需要购买USB的IP核,门槛较高。如果自己开发基于FPGA的USB协议栈,风险高,而且兼容性和稳定性很难保证。目前市场上的USB 2.0接... 查看详情

zynq之fpga学习----uart串口实验(代码片段)

1UART串口简介UART串口基础知识学习:硬件设计基础----通信协议UART2实验任务上位机通过串口调试助手发送数据给Zynq,ZynqPL端通过RS232串口接收数据并将接收到的数据发送给上位机,完成串口数据环回,管脚分配如... 查看详情

oc8051项目启动

  查看详情

需要cpld和fpga的详细说明

...据各自需要而自行构造逻辑功能的数字集成电路。其基本设计方法是借助集成开发软件平台,用原理图、硬件描述语言等方法,生成相应的目标文件,通过下载电缆(“在系统”编程)将代码传送到目标芯片中,实现设计的数字... 查看详情

fpga中的哪个部分存放烧写的程序

...PGA需要重新烧写才能用。通常可以用把image烧到FPGA外部的spiflash中,上电后自动烧到FPGA中。好像记得spartan系列也有内部带有spiflash了。 参考技术B那个不是程序,可以说是编程,可以说存在整个芯片中。你去看看FPGA的原理吧 参... 查看详情

zynq之fpga学习----iic协议驱动模块仿真实验(代码片段)

1IIC通信协议简介IIC通信协议基础知识学习:硬件设计基础----通信协议IIC2实验任务设计IIC驱动模块,并进行仿真验证,观察仿真波形3实验设计3.1创建工程新建工程,操作如图所示:输入工程名和路径,如... 查看详情

固件远程更新之startupe2原语(fpga控制flash)

...串口之类的,像xilinx还有goldenimage,以防止远程更新失败启动不起来,它主要是flash存有两个启动文件,正常情况下启动默认的,当默认的被损坏,就从备用的启动。本文章主要讲解的是STARTUPE2原语,这和远程更新有什么关系呢... 查看详情

jlink使用技巧之烧写spiflash存储芯片(代码片段)

...ink可以烧写Hex文件,作为ARM仿真调试器,但是知道能烧写SPIFlash的人应该不多,本篇文章将介绍如何使用JLink来烧写或者读取SPIFlash存储器,JLink软件包含的工具中,有一个是JFlashSPI工具,这就是一个烧写和读取SPI存储器的工具了... 查看详情

仕兰微华为汉王凹凸科技南山之桥周立功等公司常见fpga面试题整理

目录南山之桥凹凸科技汉王华为面试题仕兰微周立功FPGA笔试题南山之桥1.多时域设计中,如何处理信号跨时域。(南山之桥 查看详情

fpga之时钟规划图解

...前言        对于vivado这类使用verilog语言的进行工程设计的工具,软件的时钟规划设计是至关重要的一个环节,下面将针对软件时钟规划的设计原理进行一些基础的说明,了解这个也能提高自己程序设计的可靠性&... 查看详情

三叔学fpga系列之1:cyclonev中的时钟资源

...经验和帮助,追求的是快速上手,所以不管对于硬件电路设计,还是verilog电路编程,甚至是FPGA内部的资源,都没来得及系统地学习,最近在做算法到电路的实现,正好系统学习,将感悟记于此,如有错误,欢迎指出、讨论。&nbs... 查看详情

spiflash与norflash的区别?

参考技术ANorFlash包含SPIFlash。SPIFlash是NorFlash的一部分。1、NorFLASH使用方便,易于连接,可以在芯片上直接运行代码,稳定性出色,传输速率高,在小容量时有很高的性价比,这使其很适合应于嵌入式系统中作为FLASHROM。2、在通信... 查看详情