FPGA设计――SPI Flash启动之MC8051设计
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语言开发,具有如下特点:
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,//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交替闪烁。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |