FPGA设计——SPI Flash启动之MC8051设计

简介:

1. 概述

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


2. 系统框图

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

wKiom1hzKsSAa3_iAABHO8So9II344.jpg


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的顶层结构如下图所示:

wKiom1hzK_ijretGAACSF5cD3LI646.jpg


4. MC8051移植

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
   -----------------------------------------------------------------------------
   -- 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。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
   -----------------------------------------------------------------------------
   -- 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页组成一个块,其结构框图如下:

wKiom1hzL5-RJK6rAAJ7zmSW5O0666.jpg

SPI Flash的读写指令如下:

wKiom1hzMLTR496LAADlQgotXyQ714.jpg

wKioL1hzMLXA7Ml4AAErQzm_NKU053.jpg


6. SPI Flash控制器设计

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

wKioL1hzMmPzX9vkAADSU9g8Ejs556.jpg

wKiom1hzMmSzWuCQAADH3hPyhJA182.jpg

控制器状态机设计如下:

wKiom1hzMr7xzzozAADNBE4d4jM840.jpg


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
//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和定时器设备,代码设计如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#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中。

wKiom1hzNXzR7VWyAAAvPLcpwAI993.jpg


8. FPGA系统逻辑代码设计

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//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交替闪烁。

wKioL1hzOByQbjL3AAEGLxYf7Is750.jpg


本文转自 shugenyin 51CTO博客,原文链接:http://blog.51cto.com/shugenyin/1890407


相关文章
|
8月前
|
异构计算 内存技术
FPGA进阶(1):基于SPI协议的Flash驱动控制(二)
FPGA进阶(1):基于SPI协议的Flash驱动控制
83 0
|
8月前
|
异构计算 内存技术
FPGA进阶(1):基于SPI协议的Flash驱动控制(一)
FPGA进阶(1):基于SPI协议的Flash驱动控制(一)
280 0
|
存储 芯片 异构计算
Xilinx FPGA SPI配置芯片都支持哪些型号
Xilinx FPGA SPI配置芯片都支持哪些型号
594 0
Xilinx FPGA SPI配置芯片都支持哪些型号
|
存储 芯片 异构计算
FPGA-利用SPI总线进行flash操作
FPGA-利用SPI总线进行flash操作
452 0
FPGA-利用SPI总线进行flash操作
|
2月前
|
算法 数据安全/隐私保护 异构计算
基于FPGA的变步长LMS自适应滤波器verilog实现,包括testbench
### 自适应滤波器仿真与实现简介 本项目基于Vivado2022a实现了变步长LMS自适应滤波器的FPGA设计。通过动态调整步长因子,该滤波器在收敛速度和稳态误差之间取得良好平衡,适用于信道均衡、噪声消除等信号处理应用。Verilog代码展示了关键模块如延迟单元和LMS更新逻辑。仿真结果验证了算法的有效性,具体操作可参考配套视频。
131 74
|
3月前
|
算法 数据安全/隐私保护 异构计算
基于FPGA的16QAM调制+软解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
本项目基于FPGA实现了16QAM基带通信系统,包括调制、信道仿真、解调及误码率统计模块。通过Vivado2019.2仿真,设置不同SNR(如8dB、12dB),验证了软解调相较于传统16QAM系统的优越性,误码率显著降低。系统采用Verilog语言编写,详细介绍了16QAM软解调的原理及实现步骤,适用于高性能数据传输场景。
182 69
|
3月前
|
移动开发 算法 数据安全/隐私保护
基于FPGA的QPSK调制+软解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
本文介绍了基于FPGA的QPSK调制解调系统,通过Vivado 2019.2进行仿真,展示了在不同信噪比(SNR=1dB, 5dB, 10dB)下的仿真效果。与普通QPSK系统相比,该系统的软解调技术显著降低了误码率。文章还详细阐述了QPSK调制的基本原理、信号采样、判决、解调及软解调的实现过程,并提供了Verilog核心程序代码。
100 26
|
2月前
|
存储 编解码 算法
基于FPGA的直接数字频率合成器verilog实现,包含testbench
本项目基于Vivado 2019.2实现DDS算法,提供完整无水印运行效果预览。DDS(直接数字频率合成器)通过数字信号处理技术生成特定频率和相位的正弦波,核心组件包括相位累加器、正弦查找表和DAC。相位累加器在每个时钟周期累加频率控制字,正弦查找表根据相位值输出幅度,DAC将数字信号转换为模拟电压。项目代码包含详细中文注释及操作视频。
|
4月前
|
算法 异构计算
基于FPGA的4ASK调制解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
本文介绍了基于FPGA的4-ASK调制解调系统的算法仿真效果、理论基础及Verilog核心程序。仿真在Vivado2019.2环境下进行,分别测试了SNR为20dB、15dB、10dB时的性能。理论部分概述了4-ASK的工作原理,包括调制、解调过程及其数学模型。Verilog代码实现了4-ASK调制器、加性高斯白噪声(AWGN)信道模拟、解调器及误码率计算模块。
99 8
|
4月前
|
算法 物联网 异构计算
基于FPGA的4FSK调制解调系统,包含testbench,高斯信道模块,误码率统计模块,可以设置不同SNR
本文介绍了基于FPGA的4FSK调制解调系统的Verilog实现,包括高斯信道模块和误码率统计模块,支持不同SNR设置。系统在Vivado 2019.2上开发,展示了在不同SNR条件下的仿真结果。4FSK调制通过将输入数据转换为四个不同频率的信号来提高频带利用率和抗干扰能力,适用于无线通信和数据传输领域。文中还提供了核心Verilog代码,详细描述了调制、加噪声、解调及误码率计算的过程。
133 11

热门文章

最新文章