银杏科技有限公司旗下技术文档发布平台 | |||
技术支持电话 | 0379-69926675-801 | ||
技术支持邮件 | Gingko@vip.163.com | ||
版本 | 日期 | 作者 | 修改内容 |
---|---|---|---|
V1.0 | 2020-02-15 | gingko | 初次建立 |
//--------------------Init_FSM-------------------------------// reg [4:0] cnt_clk_i = 5'd0;//初始化时钟计数器 reg [4:0] Init_State_r = 5'd0;//初始化状态寄存器 always @(posedge SDRAM_CLK or negedge RST_n) if (!RST_n) begin cnt_clk_i <= 5'd0; Init_State_r <= `Init_NOP;//上电复位后处于NOP状态 end else case (Init_State) `Init_NOP: begin cnt_clk_i <= 5'd0; if (done_200us)//200us稳定期完成 Init_State_r <= `Init_PCH;//进入所有Bank预充电状态 else Init_State_r <= `Init_NOP; end `Init_PCH: begin if (cnt_clk_i == 5'd9)//预充电占用10个周期 begin Init_State_r <= `Init_AR1;//进入8次自动刷新状态 cnt_clk_i <= 5'd0; end else begin Init_State_r <= `Init_PCH; cnt_clk_i <= cnt_clk_i + 1'd1; end end `Init_AR1: begin //第一次自动刷新 if (cnt_clk_i == 5'd9)//自动刷新占用10个周期 begin Init_State_r <= `Init_AR2; cnt_clk_i <= 5'd0; end else begin Init_State_r <= `Init_AR1; cnt_clk_i <= cnt_clk_i + 1'd1; end end `Init_AR2: begin //第二次自动刷新 if (cnt_clk_i == 5'd9) begin Init_State_r <= `Init_AR3; cnt_clk_i <= 5'd0; end else begin Init_State_r <= `Init_AR2; cnt_clk_i <= cnt_clk_i + 1'd1; end end `Init_AR3: begin //第三次 if (cnt_clk_i == 5'd9) begin Init_State_r <= `Init_AR4; cnt_clk_i <= 5'd0; end else begin Init_State_r <= `Init_AR3; cnt_clk_i <= cnt_clk_i + 1'd1; end end `Init_AR4: begin //第四次 if (cnt_clk_i == 5'd9) begin Init_State_r <= `Init_AR5; cnt_clk_i <= 5'd0; end else begin Init_State_r <= `Init_AR4; cnt_clk_i <= cnt_clk_i + 1'd1; end end `Init_AR5: begin //第五次 if (cnt_clk_i == 5'd9) begin Init_State_r <= `Init_AR6; cnt_clk_i <= 5'd0; end else begin Init_State_r <= `Init_AR5; cnt_clk_i <= cnt_clk_i + 1'd1; end end `Init_AR6: begin //第六次 if (cnt_clk_i == 5'd9) begin Init_State_r <= `Init_AR7; cnt_clk_i <= 5'd0; end else begin Init_State_r <= `Init_AR6; cnt_clk_i <= cnt_clk_i + 1'd1; end end `Init_AR7: begin //第七次 if (cnt_clk_i == 5'd9) begin Init_State_r <= `Init_AR8; cnt_clk_i <= 5'd0; end else begin Init_State_r <= `Init_AR7; cnt_clk_i <= cnt_clk_i + 1'd1; end end `Init_AR8: begin //第八次 if (cnt_clk_i == 5'd9) begin Init_State_r <= `Init_MRS; cnt_clk_i <= 5'd0; end else begin Init_State_r <= `Init_AR8; cnt_clk_i <= cnt_clk_i + 1'd1; end end `Init_MRS: begin //模式寄存器设置状态 if (cnt_clk_i == 5'd4) //占用5个周期 begin Init_State_r <= `Init_DONE; //初始化完成 cnt_clk_i <= 5'd0; end else begin Init_State_r <= `Init_MRS; cnt_clk_i <= cnt_clk_i + 1'd1; end end `Init_DONE: begin //初始化完成 Init_State_r <= `Init_DONE; end default: Init_State_r <= `Init_NOP; endcase
//--------------------Work_FSM-------------------------------// reg [2:0] Work_State_r = 3'd0;//工作状态寄存器 reg [8:0] cnt_clk_w = 9'd0;//工作状态时钟计数器 reg wr_sig; always @(posedge SDRAM_CLK or negedge RST_n) if (!RST_n) Work_State_r <= `Work_IDLE;//上电复位处于IDLE状态 else case (Work_State_r) `Work_IDLE: begin cnt_clk_w <= 9'd0; if (SD_Init_Done && SD_RD_Req) //初始化完成且 Work_State_r <= `Work_ACT_RD; //有读请求,进入读ACT状态 else if (SD_Init_Done && SD_WR_Req) //有写请求,进入写ACT状态 Work_State_r <= `Work_ACT_WR; else if (SD_Init_Done && REF_Req) //初始化完成且有刷新请求 Work_State_r <= `Work_AR; //进入刷新状态 else Work_State_r <= `Work_IDLE; end `Work_ACT_RD: begin if (cnt_clk_w == 9'd3)//ACT占用3个周期 begin cnt_clk_w <= 9'd0; //时钟计数器清零 Work_State_r <= `Work_RD; //根据读写信号 end //决定是进入WR状态还是RD状态 else begin cnt_clk_w <= cnt_clk_w + 1'd1; //自加1 Work_State_r <= `Work_ACT_RD; end end `Work_ACT_WR: begin if (cnt_clk_w == 9'd2) //ACT占用3个周期 begin cnt_clk_w <= 9'd0; //时钟计数器清零 Work_State_r <= `Work_WR; //根据读写信号 end //决定是进入WR状态还是RD状态 else begin cnt_clk_w <= cnt_clk_w + 1'd1;//自加1 Work_State_r <= `Work_ACT_WR; end end `Work_WR: begin//写状态 if (cnt_clk_w == 9'd258) //写状态占用258个周期,发送写命令滞后占用1个周期 begin //写操作占用256个周期,写入最后一个数据的同时 cnt_clk_w <= 9'd0; //发生BST(突发停止)命令,然后预充电占用1个周期 Work_State_r <= `Work_IDLE; end else begin cnt_clk_w <= cnt_clk_w + 1'd1; Work_State_r <= `Work_WR; end end `Work_RD: begin //读状态 if (cnt_clk_w == 9'd5) //读状态占用260个周期,发送读命令滞后占用1个周期 begin //CL延时占用3个周期,读操作占用256个周期 cnt_clk_w <= 9'd0; //BST和预充电命令在CL延时的3个周期内发送,不额外占用时间 Work_State_r <= `Work_IDLE;//读完成后进入空闲状态 end else begin cnt_clk_w <= cnt_clk_w + 1'd1; Work_State_r <= `Work_RD; end end `Work_AR: begin //自动刷新状态 if (cnt_clk_w == 9'd9) //占用10个周期 begin cnt_clk_w <= 9'd0; Work_State_r <= `Work_IDLE;//刷新完成后进入空闲状态 end else begin cnt_clk_w <= cnt_clk_w + 1'd1; Work_State_r <= `Work_AR; end end default: begin cnt_clk_w <= 9'd0; Work_State_r <= `Work_IDLE; end endcase
always @(posedge SDRAM_CLK or negedge RST_n) if (!RST_n) begin SD_BA_r <= 2'b11; SD_AB_r <= 12'hFFF; SD_CMD <= `CMD_Init;//上电复位后,发送命令Init end else case (Init_Stste) `Init_NOP: begin SD_BA_r <= 2'b11; SD_AB_r <= 12'hFFF; SD_CMD <= `CMD_NOP; //空闲状态发送NOP命令 end `Init_PCH: begin if (Init_Cnt_CLK == 5'd0) //进入预充电状态后第一个上升沿发送命令 begin //即为之前注释的发送命令滞后1个周期 SD_BA_r <= 2'b11; SD_AB_r <= 12'hFFF; SD_CMD <= `CMD_PCH; //发送PCH命令 end else SD_CMD <= `CMD_NOP; end `Init_AR1,`Init_AR2,`Init_AR3,`Init_AR4, `Init_AR5,`Init_AR6,`Init_AR7,`Init_AR8: begin if (Init_Cnt_CLK == 5'd0) begin SD_BA_r <= 2'b11; SD_AB_r <= 12'hFFF; SD_CMD <= `CMD_REF; //刷新状态发送刷新命令 end else SD_CMD <= `CMD_NOP; end `Init_MRS: begin//模式寄存器设置状态 if (Init_Cnt_CLK == 5'd0)//同PCH状态 begin SD_BA_r <= 2'b00; //必须为00 SD_AB_r <= {2'b00, //必须为00 1'b1, //写模式,0为突发读突发写,1为突发读单次写 2'b00, //必须为0 3'b011, //CL值,010为2,011为3 1'b0, //访问模式,0为顺序模式,1为交错模式 3'b000};//BL值,000为1,001为2,010为4,011为8,111为全页 SD_CMD <= `CMD_MRS; //进入MRS状态后,滞后1个周期发送MRS命令 end else SD_CMD <= `CMD_NOP; end
always @(posedge SDRAM_CLK or negedge RST_n) if (!RST_n) begin i <= 4'd0; SD_WR_Req_r <= 1'd0; WR_AB <= 20'd0; RD_AB <= 20'd0; Sys_Data_out_r <= 16'd0; BANK <= 2'd0; bank <= 2'd0; data_in <= 20'd0; data_out <= 20'd0; led1 <= 1'd1; led2 <= 1'd1; led3 <= 1'd1; p <= 20'd0; q <= 4'd0; counter <= 28'd0; end else case(i) 4'd0: begin if ((!SD_Busy) && (cnt >= 24'hfffff)) begin BANK <= bank; WR_AB <= data_in; Sys_Data_out_r <= data_in[15:0]; SD_WR_Req_r <= 1'd1; //发出写请求,同时发出写地址 led1 <= 1'd0; i <= 4'd1; end else i <= 4'd0; end 4'd1: begin if (SD_WR_Ack) //等待SDRAM控制模块发出写应答信号 begin if (data_in == 20'hfffff) begin if(bank == 2'd3) begin data_in <= 20'd0; SD_WR_Req_r <= 1'd0;//写请求信号撤销 bank <= 2'd0; i <= 4'd2; end else begin data_in <= 20'd0; SD_WR_Req_r <= 1'd0;//写请求信号撤销 bank <= bank + 1'd1; i <= 4'd0; end end else begin SD_WR_Req_r <= 1'd0;//写请求信号撤销 i <= 4'd0; data_in <= data_in + 1'd1; end end else i <= 4'd1; end 4'd2: begin if((!SD_Busy) && (cnt >= 24'hfffff))//等待SDRAM控制模块不忙 begin SD_RD_Req_r <= 1'd1;//发出读请求信号,同时发出读地址 RD_AB <= data_out; BANK <= bank; i <= 4'd3; end else i <= 4'd2; end 4'd3: begin if(SD_RD_Ack) //等待SDRAM控制模块发出读应答信号 begin SD_RD_Req_r <= 1'd0; //读请求信号撤销 i <= 4'd4; end else i <= 4'd3; end 4'd4: begin if (q == 4'd7) begin q <= 4'd0; i <= 4'd5; end else begin i <= 4'd4; q <= q + 1'd1; end end 4'd5: begin if (SDRAM_Data_out == data_out[15:0])//判断数据是否正确 begin if (data_out == 20'hfffff) begin if (bank == 2'd3) begin data_out <= 20'd0; i <= 4'd7; end else begin data_out <= 20'd0; bank <= bank + 1'd1; i <= 4'd2; end end else begin data_out <= data_out + 1'd1; i <= 4'd2; end end else i <= 4'd8; end 4'd7: //结束 begin if(counter == 28'h4000000) begin led1 <= 1'd0; led2 <= 1'd1; led3 <= 1'd1; end else if(counter == 28'h8000000) begin led1 <= 1'd1; led2 <= 1'd0; led3 <= 1'd1; end else if(counter == 28'hC000000) begin led1 <= 1'd1; led2 <= 1'd1; led3 <= 1'd0; end if(counter == 28'hC000000) begin counter <= 28'd0; end else begin counter <= counter + 1'd1; end end 4'd8: //报错 begin if (p == 20'd1000000) begin p <= 20'd0; i <= 4'd8; end else begin p <= p + 1'd1; led1 <= 1'd0; led3 <= 1'd0; led2 <= 1'd0; end end default: i <= 4'd0; endcase
观察iCore3开发板,可以看到FPGA_LED灯红绿蓝三种颜色依次循环闪烁,表示实验验证成功。