您好,登錄后才能下訂單哦!
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<= 'h2000; end else begin rd_start <= 1'b0; rd_addr <= rd_addr; rd_length<= rd_length; end always @(posedge clk) if(spi_cnt==16'h2000) 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交替閃爍。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。