前言:回校了,辦好手續就著手寫測試篇。初步的norflash控制器已經完成,通過硬件測試。目前的norflash完成扇区块擦除、单字节写、单字节读3个功能。博文最后附上源码。
总结:和之前的博文一样,里面的模块没有做时序分析,这一点会在今后的工程里面改进。另外在测试的过程中,发现写完一个字节后只需经过若干个系统时钟周期即可输出正确的写入内容(设置等待写完成的总线方向为输入,可以看到三态口的数据总线显示之前写入的数值,本人源码写入0xcc,可见stp2抓图)。这一点和手册里给的单字节写需要9us的等待时间写操作完成才能进入读不同。但是需要注意的是,手册给的是一个范围,其中9us仅仅是一个典型值,芯片温度、环境因素也将影响整个擦除所用的时间。
如果这时候有人说按照你实际测试值,读和写岂不是差不多相同的数量级?不是这样的,因为我在设计控制器的时候就是讲指令拆解成最小的原子操作,其实真正的写一个字节是包含擦差和写指令2部分,所以算起来用norflash来写东西实在是“慢”。这个过程中没有遇到什么太大的麻烦,norflash就是简单好写!
norflash控制器就先告一段落。
源码1:norflash控制器
1 `timescale 1 ns / 100 ps 2 //`define SIM 3 `define ASIZE 22 4 `define DSIZE 8 5 `define S29AL032D70TFI04 6 `define SYS_CLK 50000000 7 //version 0.0 8 //前级控制模块功能指令集 sys_cmd_i 9 //000:single byte read(1 cycle) 10 //001:single byte write(4 cycle) 11 //010:sect erase 12 module norflash_ctrl(//common 13 sys_clk, 14 sys_rst_n, 15 sys_cmd_i, 16 flash_req_i, 17 flash_ack_o, 18 //read 19 sys_rd_addr_i, 20 sys_data_o, 21 //write 22 sys_wr_addr_i, 23 sys_data_i, 24 //flash 25 flash_addr, 26 flash_data, 27 flash_ce_n, 28 flash_oe_n, 29 flash_we_n, 30 flash_rst_n 31 ); 32 `ifdef S29AL032D70TFI04 33 `define CLAP_WIDTH 3 //器件最小周期70ns,根据系统时钟此模块设置为80ns 34 `define CLAP 4 35 `define SECT_TIME 35000000 // 單次擦除需要0.7秒時間間隙,主時鐘20ns 36 `define BYTE_WR_TIME 452 //單字節寫需要9微妙時間間隙,主時鐘20ns 37 `endif 38 `ifdef SIM 39 parameter ST_WIDTH = 72; 40 parameter IDLE = "IDLE.....", 41 BYTE_RD = "BYTE_RD..", 42 BYTE_WR1 = "BYTE_WR1.", 43 BYTE_WR2 = "BYTE_WR2.", 44 BYTE_WR3 = "BYTE_WR3.", 45 BYTE_WR4 = "BYTE_WR4.", 46 SECT_ERA1 = "SECT_ERA1", 47 SECT_ERA2 = "SECT_ERA2", 48 SECT_ERA3 = "SECT_ERA3", 49 SECT_ERA4 = "SECT_ERA4", 50 SECT_ERA5 = "SECT_ERA5", 51 SECT_ERA6 = "SECT_ERA6", 52 SECT_WAIT = "SECT_WAIT", 53 BYTE_WR_WAIT = "BYTE_WR_W"; 54 `else 55 parameter ST_WIDTH = 14; 56 `define FSM 14 57 parameter IDLE = `FSM'b00_0000_0000_0001, 58 BYTE_RD = `FSM'b00_0000_0000_0010, 59 BYTE_WR1 = `FSM'b00_0000_0000_0100, 60 BYTE_WR2 = `FSM'b00_0000_0000_1000, 61 BYTE_WR3 = `FSM'b00_0000_0001_0000, 62 BYTE_WR4 = `FSM'b00_0000_0010_0000, 63 SECT_ERA1 = `FSM'b00_0000_0100_0000, 64 SECT_ERA2 = `FSM'b00_0000_1000_0000, 65 SECT_ERA3 = `FSM'b00_0001_0000_0000, 66 SECT_ERA4 = `FSM'b00_0010_0000_0000, 67 SECT_ERA5 = `FSM'b00_0100_0000_0000, 68 SECT_ERA6 = `FSM'b00_1000_0000_0000, 69 SECT_WAIT = `FSM'b01_0000_0000_0000, 70 BYTE_WR_WAIT = `FSM'b10_0000_0000_0000; 71 `endif 72 //common 73 input sys_clk; 74 input sys_rst_n; 75 input [2:0] sys_cmd_i; //前级控制指令变化 76 input flash_req_i; //前级控制指令请求脉冲,配合指令 77 output flash_ack_o; 78 //read 79 input [`ASIZE-1:0] sys_rd_addr_i; 80 output [`DSIZE-1:0] sys_data_o; 81 //write 82 input [`DSIZE-1:0] sys_data_i; 83 input [`ASIZE-1:0] sys_wr_addr_i; 84 //flash 85 output [`ASIZE-1:0] flash_addr; 86 inout [`DSIZE-1:0] flash_data; //暂时先设置为读方向 87 output flash_we_n; 88 output flash_ce_n; 89 output flash_oe_n; 90 output flash_rst_n; 91 92 //capture the posedge of flash_req_i; 93 reg flash_req_r = 0; 94 always @ (posedge sys_clk) begin 95 if(sys_rst_n == 1'b0) flash_req_r <= 0; 96 else flash_req_r <= flash_req_i; 97 end 98 wire rqst_edge = flash_req_i & ~flash_req_r;//检测上升沿 99 //decode cmd 指令译码 并生成 内部控制信号 100 reg do_byte_rd = 0; //单字节读 101 reg do_sect_era = 0; //整片擦出 102 reg do_byte_wr = 0; //单字节写 103 always @ (posedge sys_clk) begin 104 if(sys_rst_n == 1'b0) begin 105 do_byte_rd <= 0; 106 do_sect_era <= 0; 107 do_byte_wr <= 0;end 108 else if(flash_ack_o) begin 109 do_byte_rd <= 0; 110 do_sect_era <= 0; 111 do_byte_wr <= 0;end 112 else if(rqst_edge) begin 113 case(sys_cmd_i) 114 3'd0:begin 115 do_byte_rd <= 1; //读有效 116 do_sect_era <= 0; 117 do_byte_wr <= 0;end 118 3'd1:begin //写有效 119 do_byte_wr <= 1; 120 do_byte_rd <= 0; 121 do_sect_era <= 0;end 122 3'd2:begin //整片擦除有效 123 do_sect_era <= 1; 124 do_byte_wr <= 0; 125 do_byte_rd <= 0;end 126 default:begin 127 do_byte_rd <= 0; 128 do_sect_era <= 0; 129 do_byte_wr <= 0;end 130 endcase 131 end 132 else begin 133 do_byte_rd <= do_byte_rd; 134 do_sect_era <= do_sect_era; 135 do_byte_wr <= do_byte_wr;end 136 end 137 //combine all does 138 wire do_process = do_byte_rd|do_sect_era|do_byte_wr; 139 //GENERATE CLOCK CLAP 140 reg [`CLAP_WIDTH-1:0] clk_clap = `CLAP_WIDTH'd0; 141 always @ (posedge sys_clk) begin 142 if(sys_rst_n == 1'b0) clk_clap <= `CLAP_WIDTH'd0; 143 else if(flash_ack_o) clk_clap <= `CLAP_WIDTH'd0; 144 else if(clk_clap == `CLAP) clk_clap <= `CLAP_WIDTH'd1; 145 else if(do_process) clk_clap <= clk_clap + 1'd1; 146 else clk_clap <= clk_clap; 147 end 148 //fsm 149 reg [ST_WIDTH-1:0] c_st = IDLE; 150 reg [ST_WIDTH-1:0] n_st = IDLE; 151 reg [31:0] sect_time_cnt = 0; //延遲扇區擦除所需時間 152 //generate sect_time_cnt 153 //wire sect_era6 = ((c_st == SECT_ERA6)&&(clk_clap == `CLAP_WIDTH'd`CLAP))?1'b1:1'b0;//擦寫最後一個週期的最後一個脉衝 154 always @ (posedge sys_clk) begin 155 if(sys_rst_n == 1'b0) sect_time_cnt <= 0; 156 else if((c_st == SECT_WAIT)&&(sect_time_cnt < `SECT_TIME-1)) sect_time_cnt <= sect_time_cnt + 1'd1; 157 else if(sect_time_cnt == `SECT_TIME-1) sect_time_cnt <= 0; 158 else sect_time_cnt <= sect_time_cnt; 159 end 160 //GENERATE BYTE_WR_TIME_CNT 161 reg [8:0] byte_wr_time_cnt = 0; 162 always @ (posedge sys_clk) begin 163 if(sys_rst_n == 1'b0) byte_wr_time_cnt <= 0; 164 else if((c_st == BYTE_WR_WAIT)&&(byte_wr_time_cnt < `BYTE_WR_TIME-1)) byte_wr_time_cnt <= byte_wr_time_cnt + 1'd1; 165 else if(byte_wr_time_cnt == `BYTE_WR_TIME-1) byte_wr_time_cnt <= 0; 166 else byte_wr_time_cnt <= byte_wr_time_cnt; 167 end 168 //fsm-1 169 always @ (posedge sys_clk) begin 170 if(sys_rst_n == 1'b0) c_st <= IDLE; 171 else c_st <= n_st; 172 end 173 wire [2:0] do_type = {do_sect_era,do_byte_rd,do_byte_wr}; // 174 //fsm-2 175 always @ (*) begin 176 case(c_st) 177 IDLE:begin 178 case(do_type) 179 3'b001:n_st = BYTE_WR1; 180 3'b010:n_st = BYTE_RD; 181 3'b100:n_st = SECT_ERA1; 182 default:n_st = IDLE; 183 endcase 184 end 185 BYTE_RD:begin 186 n_st = (clk_clap == `CLAP_WIDTH'd`CLAP)?IDLE:BYTE_RD;end 187 BYTE_WR1:begin 188 n_st = (clk_clap == `CLAP_WIDTH'd`CLAP)?BYTE_WR2:BYTE_WR1;end 189 BYTE_WR2:begin 190 n_st = (clk_clap == `CLAP_WIDTH'd`CLAP)?BYTE_WR3:BYTE_WR2;end 191 BYTE_WR3:begin 192 n_st = (clk_clap == `CLAP_WIDTH'd`CLAP)?BYTE_WR4:BYTE_WR3;end 193 BYTE_WR4:begin 194 n_st = (clk_clap == `CLAP_WIDTH'd`CLAP)?BYTE_WR_WAIT:BYTE_WR4;end 195 BYTE_WR_WAIT:begin 196 n_st = ((clk_clap == `CLAP_WIDTH'd`CLAP)&&(byte_wr_time_cnt == `BYTE_WR_TIME-1))?IDLE:BYTE_WR_WAIT;end 197 SECT_ERA1:begin 198 n_st = (clk_clap == `CLAP_WIDTH'd`CLAP)?SECT_ERA2:SECT_ERA1;end 199 SECT_ERA2:begin 200 n_st = (clk_clap == `CLAP_WIDTH'd`CLAP)?SECT_ERA3:SECT_ERA2;end 201 SECT_ERA3:begin 202 n_st = (clk_clap == `CLAP_WIDTH'd`CLAP)?SECT_ERA4:SECT_ERA3;end 203 SECT_ERA4:begin 204 n_st = (clk_clap == `CLAP_WIDTH'd`CLAP)?SECT_ERA5:SECT_ERA4;end 205 SECT_ERA5:begin 206 n_st = (clk_clap == `CLAP_WIDTH'd`CLAP)?SECT_ERA6:SECT_ERA5;end 207 SECT_ERA6:begin 208 n_st = (clk_clap == `CLAP_WIDTH'd`CLAP)?SECT_WAIT:SECT_ERA6;end 209 SECT_WAIT:begin 210 n_st = ((clk_clap == `CLAP_WIDTH'd`CLAP)&&(sect_time_cnt == `SECT_TIME-1))?IDLE:SECT_WAIT;end 211 default:begin 212 n_st = IDLE;end 213 endcase 214 end 215 //fsm-3 216 reg [3:0] cmd_r = 0; 217 reg [`DSIZE-1:0] sys_data_o = 0; 218 reg [`ASIZE-1:0] flash_addr = 0; 219 reg [`DSIZE-1:0] data_buf = 0; 220 reg link = 0; 221 always @ (posedge sys_clk) begin 222 if(1'b0 == sys_rst_n) begin 223 cmd_r <= 4'b0011; 224 flash_addr <= 0; 225 data_buf <= 0; 226 sys_data_o <= 0; 227 link <= 0;end 228 else begin 229 case(n_st) 230 IDLE:begin 231 cmd_r <= 4'b0011; 232 flash_addr <= flash_addr; 233 data_buf <= data_buf; 234 sys_data_o <= sys_data_o; 235 link <= 0;end 236 BYTE_RD:begin 237 cmd_r <= 4'b0011; 238 flash_addr <= sys_rd_addr_i; 239 data_buf <= data_buf; //hold 240 sys_data_o <= (clk_clap == `CLAP_WIDTH'd2)?flash_data:sys_data_o; 241 link <= 0;end 242 SECT_ERA1:begin 243 cmd_r <= (clk_clap == `CLAP_WIDTH'd2||clk_clap ==`CLAP_WIDTH'd1)?4'b0101:4'b0111; 244 flash_addr <= `ASIZE'h000aaa; 245 data_buf <= `DSIZE'haa; 246 sys_data_o <= sys_data_o; 247 link <= 1;end 248 SECT_ERA2:begin 249 cmd_r <= (clk_clap == `CLAP_WIDTH'd2||clk_clap ==`CLAP_WIDTH'd1)?4'b0101:4'b0111; 250 flash_addr <= `ASIZE'h000555; 251 data_buf <= `DSIZE'h55; 252 sys_data_o <= sys_data_o; 253 link <= 1;end 254 SECT_ERA3:begin 255 cmd_r <= (clk_clap == `CLAP_WIDTH'd2||clk_clap ==`CLAP_WIDTH'd1)?4'b0101:4'b0111; 256 flash_addr <= `ASIZE'h000aaa; 257 data_buf <= `DSIZE'h80; 258 sys_data_o <= sys_data_o; 259 link <= 1;end 260 SECT_ERA4:begin 261 cmd_r <= (clk_clap == `CLAP_WIDTH'd2||clk_clap ==`CLAP_WIDTH'd1)?4'b0101:4'b0111; 262 flash_addr <= `ASIZE'h000aaa; 263 data_buf <= `DSIZE'haa; 264 sys_data_o <= sys_data_o; 265 link <= 1;end 266 SECT_ERA5:begin 267 cmd_r <= (clk_clap == `CLAP_WIDTH'd2||clk_clap ==`CLAP_WIDTH'd1)?4'b0101:4'b0111; 268 flash_addr <= `ASIZE'h000555; 269 data_buf <= `DSIZE'h55; 270 sys_data_o <= sys_data_o; 271 link <= 1;end 272 SECT_ERA6:begin 273 cmd_r <= (clk_clap == `CLAP_WIDTH'd2||clk_clap ==`CLAP_WIDTH'd1)?4'b0101:4'b0111; 274 flash_addr <= sys_wr_addr_i; //sector address 275 data_buf <= `DSIZE'h30; 276 sys_data_o <= sys_data_o; 277 link <= 1;end 278 SECT_WAIT:begin //wait for rphysical sector erase time 279 cmd_r <= 4'b1111; 280 flash_addr <= flash_addr; 281 data_buf <= data_buf; 282 sys_data_o <= sys_data_o; 283 link <= 0;end 284 BYTE_WR1:begin 285 cmd_r <= (clk_clap == `CLAP_WIDTH'd2||clk_clap ==`CLAP_WIDTH'd1)?4'b0101:4'b0111; 286 flash_addr <= `ASIZE'h000aaa; 287 data_buf <= `DSIZE'haa; 288 sys_data_o <= sys_data_o; 289 link <= 1;end 290 BYTE_WR2:begin 291 cmd_r <= (clk_clap == `CLAP_WIDTH'd2||clk_clap ==`CLAP_WIDTH'd1)?4'b0101:4'b0111; 292 flash_addr <= `ASIZE'h000555; 293 data_buf <= `DSIZE'h55; 294 link <= 1;end 295 BYTE_WR3:begin 296 cmd_r <= (clk_clap == `CLAP_WIDTH'd2||clk_clap ==`CLAP_WIDTH'd1)?4'b0101:4'b0111; 297 flash_addr <= `ASIZE'h000aaa; 298 data_buf <= `DSIZE'ha0; 299 sys_data_o <= sys_data_o; 300 link <= 1;end 301 BYTE_WR4:begin 302 cmd_r <= (clk_clap == `CLAP_WIDTH'd2||clk_clap ==`CLAP_WIDTH'd1)?4'b0101:4'b0111; 303 flash_addr <= sys_wr_addr_i; 304 data_buf <= sys_data_i; 305 sys_data_o <= sys_data_o; 306 link <= 1;end 307 BYTE_WR_WAIT:begin //wait for rphysical sPROGRAM time 308 cmd_r <= 4'b1111; 309 flash_addr <= flash_addr; 310 data_buf <= data_buf; 311 sys_data_o <= sys_data_o; 312 link <= 0;end 313 default:begin 314 cmd_r <= 4'b0011; 315 flash_addr <= flash_addr; 316 data_buf <= data_buf; 317 link <= link; 318 sys_data_o <= sys_data_o;end 319 endcase 320 end 321 end 322 //assign 323 assign flash_data = (link)?data_buf:`DSIZE'hzz; 324 wire flash_byte_rd_ack = ((c_st == BYTE_RD)&&(clk_clap == `CLAP_WIDTH'd`CLAP))?1'b1:1'b0; 325 wire flash_byte_wr_ack = ((c_st == BYTE_WR_WAIT)&&(byte_wr_time_cnt == `BYTE_WR_TIME-1))?1'b1:1'b0; 326 wire flash_sect_era_ack = ((c_st == SECT_WAIT)&&(sect_time_cnt == `SECT_TIME-1))?1'b1:1'b0; 327 wire flash_ack_o = flash_byte_rd_ack | flash_byte_wr_ack | flash_sect_era_ack; 328 assign {flash_ce_n,flash_oe_n,flash_we_n,flash_rst_n} = cmd_r; 329 330 endmodule
源码2:norflash驱动
1 `timescale 1 ns / 100 ps 2 `define ASIZE 22 3 `define DSIZE 8 4 module norflash_driver( 5 sys_clk, 6 sys_rst_n, 7 k1_n, 8 flash_req_o, 9 sys_cmd_o, 10 //read 11 sys_rd_addr_o, 12 //write 13 sys_wr_addr_o, 14 sys_wr_data_o 15 ); 16 input sys_clk; 17 input sys_rst_n; 18 input k1_n; 19 output flash_req_o; 20 output [2:0] sys_cmd_o; 21 //read 22 output [`ASIZE-1:0] sys_rd_addr_o; 23 //write 24 output [`ASIZE-1:0] sys_wr_addr_o; 25 output [`DSIZE-1:0] sys_wr_data_o; 26 27 //capture the negedge of k1_n 28 reg k1_r = 1; 29 always @ (posedge sys_clk) begin 30 if(sys_rst_n == 1'b0) k1_r <= 1; 31 else k1_r <= k1_n; 32 end 33 34 wire k1_neg = ~k1_n & k1_r; 35 36 //generate flash_req_o 37 reg flash_req_o = 0; 38 always @ (posedge sys_clk) begin 39 if(sys_rst_n == 1'b0) flash_req_o <= 0; 40 else if(k1_neg) flash_req_o <= 1; 41 else flash_req_o <= 0; 42 end 43 44 //generate sys_cmd_o and sys_rd_addr_o 45 reg [2:0] sys_cmd_o = 0; 46 reg [`ASIZE-1:0] sys_rd_addr_o = 0; 47 reg [`ASIZE-1:0] sys_wr_addr_o = 0; 48 reg [`DSIZE-1:0] sys_wr_data_o = 0; 49 reg [1:0] lut_index = 0; 50 51 //generate lut_index 52 always @ (posedge sys_clk) begin 53 if(sys_rst_n == 1'b0) begin 54 lut_index <= 0;end 55 else if(k1_neg) begin 56 lut_index <= lut_index + 1'd1;end 57 else begin 58 lut_index <= lut_index;end 59 end 60 61 always @ (posedge sys_clk) begin 62 case(lut_index) 63 2'd3:begin 64 sys_cmd_o <= 3'b000; // off set no meaning 65 sys_wr_addr_o <= sys_wr_addr_o; 66 sys_wr_data_o <= sys_wr_data_o; 67 sys_rd_addr_o <= sys_rd_addr_o;end 68 2'd0:begin 69 sys_cmd_o <= 3'b010; //sector eraser 70 sys_wr_addr_o[21:13] <= 9'b0_0000_0001;//sector1 71 sys_wr_addr_o[12:0] <= 13'd0; 72 sys_wr_data_o <= sys_wr_data_o; 73 sys_rd_addr_o <= `ASIZE'd0;end 74 2'd1:begin 75 sys_cmd_o <= 3'b001; //write 1 byte 76 sys_wr_addr_o[21:13] <= 9'b0_0000_0001;//sector1 77 sys_wr_addr_o[12:0] <= 13'd0; 78 sys_wr_data_o <= `DSIZE'hCC;//写數據內容 79 sys_rd_addr_o <= `ASIZE'h00;end 80 2'd2:begin 81 sys_cmd_o <= 3'b000; //read 1 byte 82 sys_wr_addr_o <= sys_wr_addr_o; 83 sys_wr_data_o <= sys_wr_data_o; 84 sys_rd_addr_o[21:13] <= 9'b0_0000_0001;//sector1 85 sys_rd_addr_o[12:0] <= 13'd0;end 86 endcase 87 end 88 89 endmodule
源码3:顶层文件
1 `timescale 1 ns / 100 ps 2 `define ASIZE 22 3 `define DSIZE 8 4 module norflash( 5 sys_clk, 6 sys_rst_n, 7 k1_n, 8 //flash 9 flash_data, 10 flash_addr, 11 flash_ce_n, 12 flash_oe_n, 13 flash_we_n, 14 flash_rst_n 15 ); 16 input sys_clk; 17 input sys_rst_n; 18 input k1_n; 19 //flash 20 inout [`DSIZE-1:0] flash_data; 21 output [`ASIZE-1:0] flash_addr; 22 output flash_ce_n; 23 output flash_oe_n; 24 output flash_we_n; 25 output flash_rst_n; 26 27 wire [2:0] sys_cmd; 28 wire flash_req; 29 wire [`ASIZE-1:0] sys_rd_addr; 30 wire [`DSIZE-1:0] sys_data_o; 31 32 wire [`ASIZE-1:0] sys_wr_addr; 33 wire [`DSIZE-1:0] sys_wr_data; 34 norflash_driver inst_driver( 35 .sys_clk(sys_clk), 36 .sys_rst_n(sys_rst_n), 37 .k1_n(k1_n), 38 .flash_req_o(flash_req), 39 .sys_cmd_o(sys_cmd), 40 .sys_rd_addr_o(sys_rd_addr), 41 //write 42 .sys_wr_addr_o(sys_wr_addr), 43 .sys_wr_data_o(sys_wr_data) 44 ); 45 46 wire flash_ack; 47 norflash_ctrl inst_ctrl(//common 48 .sys_clk(sys_clk), 49 .sys_rst_n(sys_rst_n), 50 .sys_cmd_i(sys_cmd), 51 .flash_req_i(flash_req), 52 .flash_ack_o(flash_ack), 53 //write 54 .sys_wr_addr_i(sys_wr_addr), 55 .sys_data_i(sys_wr_data), 56 //read 57 .sys_rd_addr_i(sys_rd_addr), 58 .sys_data_o(sys_data_o), 59 //flash 60 .flash_addr(flash_addr), 61 .flash_data(flash_data), 62 .flash_ce_n(flash_ce_n), 63 .flash_oe_n(flash_oe_n), 64 .flash_we_n(flash_we_n), 65 .flash_rst_n(flash_rst_n) 66 ); 67 68 69 endmodule