📄 nand_flash_ctl.v
字号:
if (reset) access_cnt<=0;
else if (d_ctl_st!=2) access_cnt<=0;
else if (!(q_ctl_st==2 & access_cnt==0)) access_cnt<=access_cnt+1;
always @(q_ctl_st or in_efm_r or efm_addr or quarter_hit or end_w_cmd or
pulse_change or rb_ or ecc_done or data2efm or access_cnt or
ecc_data0 or efm_ack or bf_h or page_quarter_plus1 or page_hit or
page_quarter) begin
d_ctl_st=q_ctl_st; d_cmd_adr=0; sel_cmd=0;
h2f=0; d_efm_ack=0; d_data2efm=data2efm;
case (q_ctl_st)
0: if (rb_ & in_efm_r & efm_addr[31:22]==0) begin
if (quarter_hit) d_ctl_st=2;
// else if (page_hit & bf_h==page_quarter) d_ctl_st=15; //nxt quarter
else d_ctl_st=1; //LF
end
1: begin d_cmd_adr=0; sel_cmd=1;
if (end_w_cmd) d_ctl_st=8;
end //rd cmd(00)
2: begin d_cmd_adr=0; //rd data in 512B bf
if (efm_ack) d_ctl_st=0;
else case (access_cnt)
0: begin d_data2efm[31:24]=ecc_data0; d_efm_ack=1; end
1: begin d_data2efm[7:0]=ecc_data0; end
2: begin d_data2efm[15:8]=ecc_data0; end
3: begin d_data2efm[23:16]=ecc_data0; end
endcase
end
3: begin d_ctl_st=0; end
4: begin h2f=1; d_ctl_st=0; end
// 8: begin d_cmd_adr={efm_addr[7:2],2'b0}; sel_cmd=1;
8: begin d_cmd_adr=0; sel_cmd=1; //ca7~0
if (end_w_cmd) d_ctl_st=9;
end //1st adr
//qi 9: begin d_cmd_adr={5'b0,efm_addr[10:8]}; sel_cmd=1; //ca10:8
9: begin d_cmd_adr={5'b0,efm_addr[10:9],1'b0}; sel_cmd=1; //ca10:8
if (end_w_cmd) d_ctl_st=10;
end //2nd adr
// 10: begin d_cmd_adr=efm_addr[19:12]; sel_cmd=1;
10: begin d_cmd_adr={4'b0,efm_addr[18:17],efm_addr[14:11]}; sel_cmd=1;
if (end_w_cmd) d_ctl_st=11;
end //3rd adr
11: begin d_cmd_adr=0; sel_cmd=1;
// 11: begin d_cmd_adr={6'b0,efm_addr[21:20]}; sel_cmd=1;
// 11: begin d_cmd_adr=efm_addr[27:20]; sel_cmd=1;
if (end_w_cmd) d_ctl_st=12;
end //4th adr
// 12: begin d_cmd_adr={7'b0,efm_addr[28]}; sel_cmd=1;
12: begin d_cmd_adr=0; sel_cmd=1;
if (end_w_cmd) d_ctl_st=13;
end //5th adr
13: begin d_cmd_adr='h30; sel_cmd=1;
if (end_w_cmd) d_ctl_st=14;
end //2nd cmd(30)
14: if (!rb_) d_ctl_st=15;
15: if (rb_) begin
// if (ecc_done & (bf_h==page_quarter_plus1)) d_ctl_st=2;
if (ecc_done) d_ctl_st=2;
end
endcase
end
always @(posedge clk or posedge reset)
if (reset) r_cmd <=0;
else if (!r_cmd & mcu_r & {mcu_adr,2'b0}=='hfff5_0008 & !q_end_512B |
// !r_cmd & q_ctl_st==15 & rb_ & pulse_change & !ram_adr0[9]
!r_cmd & q_ctl_st==15 & rb_ & pulse_change & ram_adr0<528
) r_cmd <=1;
else if (pulse_cnt==cmd_width) r_cmd <=0;
always @(posedge clk or posedge reset)
if (reset) pulse_cnt <=0;
else if (pulse_cnt==cmd_width) pulse_cnt <= 0;
else if (q_ctl_st!=0 & q_ctl_st!=2 | q_mctl_st!=0) pulse_cnt <= pulse_cnt+1;
else pulse_cnt <=0;
reg [7:0] q_data;
wire [7:0] #1 d_data_dly= d_data;
wire #1 mcu_w_dly = mcu_w & ({mcu_adr,2'b0}=='hfff5_0000 |{mcu_adr,2'b0}=='hfff5_0004 | {mcu_adr,2'b0}=='hfff5_0008 );
always @(posedge clk)
if (q_mctl_st==0 & sel_cmd & pulse_change) q_data<=cmd_adr;
else if (q_mctl_st==0 & !sel_cmd & pulse_change) q_data<= ecc_data0 ;
//qi else if (mcu_w & pulse_change) q_data<=d_data;
else if (mcu_w_dly) q_data<=d_data_dly;
reg out_en;
always @(posedge clk or posedge reset)
if (reset) out_en<=0;
else if (w_cmd) out_en<=1;
else if (q_ctl_st==14 & pulse_change) out_en<=0;
//assign data0 = (out_en)? q_data : 8'hz;
assign t_data = q_data;
reg [1:0] q_ce;
reg q_re_,f_en;
wire d_cle = w_cmd & q_mctl_st==1 |
//wire d_cle = mcu_w & {mcu_adr,2'b0}=='hfff5_0000 |
w_cmd & (q_ctl_st==1 | q_ctl_st==13);
wire d_ale = w_cmd & q_mctl_st==2 |
//wire d_ale = mcu_w & {mcu_adr,2'b0}=='hfff5_0004 |
w_cmd & (q_ctl_st==8 | q_ctl_st==9 | q_ctl_st==10 | q_ctl_st==11 | q_ctl_st==12);
wire pulse_cntI = pulse_cnt==2;
always @(posedge clk or posedge reset)
if (reset) begin q_ce <= 0; f_en<=0; end
else if (in_efm_r & efm_addr[31:22]==0) begin q_ce<='h1; f_en<=1; end
// else if (mcu_w & {mcu_adr,2'b0}=='hfff5_0004) begin q_ce<=mcu_di[31:30]; f_en<=1; end
else if (mcu_w & {mcu_adr,2'b0}=='hfff5_0004) begin q_ce<=1; f_en<=1; end
reg q_ale,q_cle;
always @(posedge clk or posedge reset)
if (reset) q_ale<=0;
else if (d_ale) q_ale<=1;
else if (w_cmd==0 & pulse_cntI | q_mctl_st==0) q_ale<=0;
always @(posedge clk or posedge reset)
if (reset) q_cle<=0;
else if (d_cle) q_cle<=1;
else if (w_cmd==0 & pulse_cntI | q_mctl_st==0) q_cle<=0;
reg q_we_;
always @(posedge clk) q_we_ = !w_cmd;
always @(posedge clk or posedge reset)
if (reset) q_re_<=1;
else if (mcu_r & {mcu_adr,2'b0}=='hfff5_0008 | r_cmd) q_re_<=0;
else q_re_<=1;
wire mcu_w0 = mcu_w & {mcu_adr,2'b0}=='hfff5_0008;
/*
wire ce0_ = (f_en)? !q_ce[0] : 1'bz;
wire ce1_ = (f_en)? !q_ce[1] : 1'bz;
wire re_ = (f_en)? q_re_ : 1'bz;
wire we_ = (f_en)? q_we_ : 1'bz;
wire ale = (f_en)? q_ale : 1'bz;
wire cle = (f_en)? q_cle : 1'bz;
*/
wire ce0_ = !q_ce[0] ;
wire ce1_ = !q_ce[1] ;
wire re_ = q_re_ ;
wire we_ = q_we_ ;
wire ale = q_ale ;
wire cle = q_cle ;
wire [1:0] ecc_st0;
wire [1:0] quarter_page_num;
always @(posedge clk or posedge reset)
if (reset) bf_h <=0;
else if (end_512B & !q_end_512B) bf_h<=bf_h+1;
reg [31:0] q_mcu_di;
reg [31:0] bfo;
always @(posedge clk ) begin
case (mcu_adr[4:2])
'h2: q_mcu_di<={ecc_st0[1:0]}; //h08
'h3: q_mcu_di<={q_mctl_st[2:0],2'b0}; //h0c
'h5: q_mcu_di<={ecc_st0}; //h14
default: q_mcu_di<=bfo;
endcase
end
reg [31:0] mcu_di;
always @(q_mcu_di)
mcu_di = q_mcu_di;
reg [7:0] data2f;
always @(ram_adr0[1:0])
case (ram_adr0[1:0])
0: data2f = mcu_do[7:0];
1: data2f = mcu_do[15:8];
2: data2f = mcu_do[23:16];
3: data2f = mcu_do[31:24];
endcase
wire [7:0] ecc_d0i= (h2f)? data2f : data0;
reg ecc_req0;
always @(posedge clk) ecc_req0 <= !r_cmd & !q_re_ ;
wire e_reset=reset | ale;
wire f2h = q_ctl_st==15 & rb_;
ecc8p ecc8_0 (.clk(clk),.reset(e_reset),
.dat8_i0(ecc_d0i), .dat8_i1(8'b0), .dat8_i2(8'b0), .dat8_i3(8'b0),
.rd(f2h),.wt(h2f),
.dat_o0(data0_o), .dat_o1(), .dat_o2(), .dat_o3(),
.ram_we0(ram_we0),.ram_adr0(ram_adr0),
.ram_we1(),.ram_adr1(),
.ram_we2(),.ram_adr2(),
.ram_we3(),.ram_adr3(),
.ecc_dat_i0(data0t), .ecc_dat_i1(8'b0), .ecc_dat_i2(8'b0), .ecc_dat_i3(8'b0),
.ecc_status0(ecc_st0), .ecc_status1(),
.ecc_status2(), .ecc_status3(),
.ecc_done(ecc_done), .req(ecc_req0),
.rdy(ecc_rdy0), .q_ram_adr_i(q_ram_adr),.q_ram_adr_o(q_ram_adr) );
always @(q_ctl_st or efm_addr or access_cnt) begin
if (q_ctl_st==2) f_adr={efm_addr[8:2],access_cnt[1:0]};
else f_adr={efm_addr[8:2],access_cnt[1:0]};
end
wire mcu_ack=mcu_r & mcu_adr[31:16]=='hfff5; //tzt:
//wire mcu_ack=mcu_w & cle & mcu_do[7:0]=='h10;
wire xram_we0=(f2h & !q_re_ | ram_we0)? 1 : (h2f)? ecc_req0 : 0;
/*
RAMB16_S9_S9 u_0 (.DOA(ecc_data0), .DOB(data0t), .DOPA(), .DOPB(), .ADDRB({bf_h,ram_adr0[8:0]}), .ADDRA({2'b0,f_adr[8:0]}),
.CLKA(clk), .CLKB(clk), .DIA(data2f), .DIB(data0_o), .DIPA(1'b0), .DIPB(1'b0),
.ENA(1'b1), .ENB(1'b1), .SSRA(1'b0), .SSRB(1'b0), .WEA(mcu_w0), .WEB(xram_we0));
*/
wire [7:0] data0t_mem;
RAMB16_S9_S9 u_0 (.DOA(ecc_data0), .DOB(data0t_mem), .DOPA(), .DOPB(), .ADDRB({2'b0,ram_adr0[8:0]}), .ADDRA({2'b0,f_adr[8:0]}),
.CLKA(clk), .CLKB(clk), .DIA(data2f), .DIB(data0_o), .DIPA(1'b0), .DIPB(1'b0),
.ENA(1'b1), .ENB(!ram_adr0[9]), .SSRA(1'b0), .SSRB(1'b0), .WEA(mcu_w0), .WEB(xram_we0));
reg [7:0] B512_527[15:0];
reg [7:0] data0t_ffA,data0t_ffB;
wire [8:0] ram_adr8_0=ram_adr0[8:0];
wire [3:0] ram_adr3_0=ram_adr0[3:0];
always @(posedge clk)
if (ram_adr0[9] & xram_we0) B512_527[ram_adr3_0] <=data0_o;
always @(ram_adr0) //portB
if (ram_adr0[9]) data0t_ffB=B512_527[ram_adr3_0];
else data0t_ffB=data0t_mem[ram_adr8_0];
assign data0t = data0t_ffB;
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -