上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人
4.5 NandFlash控制器源代码分析
这是一个基本的NandFlash控制器,设计目标为硬件简化,完成基本的控制功能,而其他功能由软件完成,包括前向纠错。
4.5.1 输入输出信号
该NandFlash控制器兼容标准WISHBONE Slave接口标准和K9F2G08U0M NandFlash接口,输入输出信号如下:
module nfc_top( //WISHBONE从设备接口 clk_i,rst_i,adr_i,dat_o,dat_i,cyc_i,stb_i,sel_i,we_i,ack_o,rty_o,err_o, //nandflash side nf_data_io, //NandFlash数据输入输出,8比特 nf_cen, //NandFlash片选 nf_ale, //NandFlash地址锁定使能 nf_cle, //NandFlash命令锁定使能 nf_ren, //NandFlash读使能 nf_wen, //NandFlash写使能 nf_rb); //NandFlash准备好/忙
4.5.2 寄存器定义
NandFlash中各寄存器的定义及说明如表4-4~表4-8所示。
表4-4 NandFlash命令寄存器
表4-8 NandFlash状态寄存器
表4-5 NandFlash操作地址寄存器
表4-6 NandFlash数据寄存器
表4-7 NandFlash状态寄存器
4.5.3 源代码分析
设计文件列表如表4-9所示。
表4-9 设计文件列表
nfc_defines.v定义了基本命令,具体如下
//1.command define `define READ_FST 8'h00 `define READ_SEC 8'h30////wait Ttr `define READ_ID 8'h90 `define RESET 8'hff `define PPRAM_FST 8'h80 `define PPRAM_SEC 8'h10 `define BERASE_FST 8'h60 `define BERASE_SEC 8'hd0 //2.register address define `define NFCMD_ADR 16'h_0004 `define NFADDR_ADR 16'h0008 `define NFDATA_ADR 16'h000C `define NFSTAT_ADR 16'h0010 `define NFENDADDR_ADR 16'h0014
nfc_top.v是对NandFlash进行操作的状态机。其源代码如下:
`include "timescale.v" `include "nfc_defines.v" module nfc_top( //wishbone side clk_i,rst_i,adr_i,dat_o,dat_i,cyc_i,stb_i,sel_i,we_i,ack_o,rty_o,err_o, //NandFlash side nf_data_io,nf_cen,nf_ale,nf_cle,nf_ren,nf_wen,nf_rb); ……//此处省略了输入输出信号和部分内部信号定义 assign rty_o=1'b0; assign err_o=1'b0; wire access=cyc_i&stb_i&(!ack_o); wire cmd_write=(adr_i==`NFCMD_ADR)&we_i&access; wire addr_write=(adr_i==`NFADDR_ADR)&we_i&access; wire status_read=(adr_i==`NFSTAT_ADR)&(!we_i)&access; wire data_read=(adr_i==`NFDATA_ADR)& (!we_i)&access; wire data_write=(adr_i==`NFDATA_ADR)& (we_i)&access; wire end_addr=(adr_i==`NFENDADDR_ADR)&we_i&access; reg drive_data; reg [7:0] data_out; assign nf_data_io=drive_data?data_out:8'bzzzz_zzzz; //为简化代码行数而定义的宏 `define NFSIGNAL {nf_cen,nf_cle,nf_ale,nf_ren,nf_wen} `define NFSIGNAL_IDLE 5'b00011 `define NFSIGNAL_CMDWR 5'b01010 `define NFSIGNAL_CMDHOLD 5'b01011 `define NFSIGNAL_ADDR_IDLE 5'b00111 `define NFSIGNAL_ADDR_WR 5'b00110 `define NFSIGNAL_DATAWR 5'b00010 `define NFSIGNAL_DATARD 5'b00001 reg [3:0] wait_cnt; reg block_erase,read_id; reg [5:0] state;//主状态 parameter NF_IDLE=1,NF_CMD=2,NF_CMD_HOLD=3,NF_WAIT_ADDR=4,NF_ADDR1=5,NF_ADDR2=6, NF_ADDR3=7, NF_ADDR4=8, NF_ADDR5=9, NF_ADDR6=10, NF_ADDR7=11, NF_ADDR8=12, NF_ADDR9=13, NF_ADDR10=14,NF_END_ADDR=15, NF_STATUS=16,NF_WRITE_DATA1=17, NF_WRITE_DATA2=18,NF_WRITE_DATA3=19,NF_WRITE_DATA4=20, NF_WRITE_DATA5=21, NF_WRITE_DATA6=22,NF_WRITE_DATA7=23,NF_WRITE_DATA8=24,NF_READ_DATA1=25, NF_READ_DATA2=26,NF_READ_DATA3=27,NF_READ_DATA4=28,NF_READ_DATA5=29, NF_READ_DATA6=30,NF_READ_DATA7=31,NF_READ_DATA8=32,NF_TWR=33;always @(posedge clk_i or posedge rst) begin if(rst) begin state<=NF_IDLE;data_out<=8'b0; drive_data<=1'b0; `NFSIGNAL<=`NFSIGNAL_IDLE; wait_cnt<=0; ack_o<=0; length<=0; fast_mode<=0; {block_erase,read_id}<=2'b00; end else begin case(state) NF_IDLE:begin {nf_cen,nf_cle,nf_ren,nf_wen}<=4'b0011; //NandFlash的工作速度较慢,插入等待周期 wait_cnt<=2; drive_data<=1'b0; //根据不同的命令产生不同的状态。 if(cmd_write & (nf_rb)) begin state<=NF_CMD; end else if(addr_write &(nf_rb)) begin state<=NF_WAIT_ADDR; end else if(end_addr &(nf_rb)) begin state<=NF_END_ADDR; end else if(data_write &(nf_rb)) begin state<=NF_WRITE_DATA1; end else if(data_read&(nf_rb)) begin state<=NF_READ_DATA1; end else if (status_read&(nf_rb)) begin state<=NF_STATUS; end //对于来自主设备的错误请求,给出ack应答,避免造成总线死锁,给出err应答在一些场合更恰当。 else if(access) begin ack_o<=1'b1; end else ack_o<=1'b0; end NF_CMD:begin `NFSIGNAL<=`NFSIGNAL_CMDWR; drive_data<=1'b1; data_out<=dat_i[7:0]; fast_mode<=dat_i[8];//在该模式下,主设备可一次写入32位的地址 if(wait_cnt==0) begin wait_cnt<=2; state<=NF_CMD_HOLD; end else begin wait_cnt<=wait_cnt-1; end end NF_CMD_HOLD: begin `NFSIGNAL<=`NFSIGNAL_CMDHOLD; if(wait_cnt==0) begin wait_cnt<=2; state<=NF_IDLE; ack_o<=1; drive_data<=1'b0; end else begin wait_cnt<=wait_cnt-1; end end NF_WAIT_ADDR: begin `NFSIGNAL<=`NFSIGNAL_ADDR_IDLE; if(wait_cnt==0) begin wait_cnt<=2; state<=NF_ADDR1; drive_data<=1'b0; end else begin wait_cnt<=wait_cnt-1; end end NF_ADDR1:begin //写入地址的最低8位,即列地址1 `NFSIGNAL<=`NFSIGNAL_ADDR_WR; drive_data<=1'b1; data_out<=dat_i[7:0]; if(wait_cnt==0) begin wait_cnt<=2; state<=NF_ADDR2; end else begin wait_cnt<=wait_cnt-1; end end NF_ADDR2:begin //相邻写操作之间的空闲 `NFSIGNAL<=`NFSIGNAL_ADDR_IDLE; if(wait_cnt==0) begin wait_cnt<=2; //在快速模式下,连续分5次将地址写入NandFlash。 if(fast_mode) state<=NF_ADDR3; else begin state<=NF_IDLE;ack_o<=1'b1;end end else begin wait_cnt<=wait_cnt-1; end end NF_ADDR3:begin `NFSIGNAL<=`NFSIGNAL_ADDR_WR; drive_data<=1'b1; data_out<={4'b0,dat_i[11:8]}; if(wait_cnt==0) begin wait_cnt<=2; state<=NF_ADDR4; end else begin wait_cnt<=wait_cnt-1; end end NF_ADDR4:begin … end//写入列地址2 NF_ADDR5:begin … end//相邻地址操作之间的空闲 NF_ADDR6:begin … end//写入行地址1 NF_ADDR7:begin … end//相邻地址操作之间的空闲 NF_ADDR8:begin … end//写入行地址2 NF_ADDR9:begin … end//相邻地址操作之间的空闲 NF_ADDR10:begin//写入行地址3 `NFSIGNAL<=`NFSIGNAL_ADDR_IDLE; if(wait_cnt==0) begin wait_cnt<=2; ack_o<=1'b0; state<=NF_END_ADDR; end else begin wait_cnt<=wait_cnt-1; end end NF_END_ADDR:begin//地址写为完成 `NFSIGNAL<=`NFSIGNAL_IDLE; state<=NF_IDLE; ack_o<=1; drive_data<=1'b0; wait_cnt<=2; end NF_WRITE_DATA8:begin第4次数据写之后的空闲,回到NF_IDLE状态 `NFSIGNAL<=`NFSIGNAL_IDLE; drive_data<=1'b1; if(wait_cnt==0) begin wait_cnt<=2; state<=NF_IDLE; ack_o<=1'b1; end else begin wait_cnt<=wait_cnt-1; end end NF_READ_DATA1:begin //第一次读数据 `NFSIGNAL<=`NFSIGNAL_DATARD; drive_data<=1'b0; if(wait_cnt==0) begin wait_cnt<=2; state<=NF_READ_DATA2; dat_o<={24'b0,nf_data_io}; end else begin wait_cnt<=wait_cnt-1; end end NF_READ_DATA2:begin //相邻读数据之间的空隙 `NFSIGNAL<=`NFSIGNAL_IDLE; if(wait_cnt==0) begin wait_cnt<=2; if(fast_mode) state<=NF_READ_DATA3; else begin state<=NF_IDLE; ack_o<=1'b1; end end else begin wait_cnt<=wait_cnt-1; end end NF_READ_DATA3:begin……end //第2、3、4次数据读 ……// NF_TWR:begin //等待周期 `NFSIGNAL<=`NFSIGNAL_IDLE; ack_o<=0; if(wait_cnt==0) begin wait_cnt<=2; state<=NF_IDLE; end else begin wait_cnt<=wait_cnt-1; end end NF_WRITE_DATA1:begin //第一次写入数据 `NFSIGNAL<=`NFSIGNAL_DATAWR; drive_data<=1'b1; data_out<=dat_i[7:0]; if(wait_cnt==0) begin wait_cnt<=2; state<=NF_WRITE_DATA2; end else begin wait_cnt<=wait_cnt-1; end end NF_WRITE_DATA2:begin //写数据完成后的空闲 `NFSIGNAL<=`NFSIGNAL_IDLE; drive_data<=1'b1; if(wait_cnt==0) begin wait_cnt<=2; //快速模式下主机写1次,状态机写NandFlash 4 次 if(fast_mode) state<= NF_WRITE_DATA3; else begin state<=NF_IDLE; ack_o<=1'b1; end end else begin wait_cnt<=wait_cnt-1; end end NF_WRITE_DATA3:begin…end //第2、3、4次数据写 ……// NF_READ_DATA8:begin //第4次数据读之后的空闲 `NFSIGNAL<=`NFSIGNAL_IDLE; if(wait_cnt==0) begin wait_cnt<=2; state<=NF_IDLE; ack_o<=1'b1; end else begin wait_cnt<=wait_cnt-1; end end NF——STATUS:begin //读状态 dat_o<={1'b0,nf_cen,nf_cle,nf_ale,nf_ren,nf_wen,nf_rb};ack_o<=1'b1; state<=NF_IDLE; end default: begin state<=NF_IDLE; end endcase end end endmodule