📄 newsd.v
字号:
`define init_delay 14'd15000`define init_refresh_time 2'd7`define tMRD_delay 1'd1`define refresh_cnt_time 11'd1500 //64ms刷新4096次 定时器实现 //参考sdram的datasheet (64ms/系统时钟)/4096 `define burst_cnt_time_write 4'd7 //突发次数 (1——2——4——8)可用3位`define burst_cnt_time_read 4'd9 //读突发次数 (1——2——4——8)可用3位 FPGA读SDRAM的数,现没有用//根据DATASHEET的控制延时`define tDAL_delay 3'd4 // 5 个周期 读写完成到下一次激活命令的周期数`define tRCD_delay 2'd0 // 1 个周期 激活命令到读写命令的延迟周期数`define tRP_delay 2'd2 // 3个周期 `define tCAS_delay 2'd2 // 3个周期 读命令到总线出现数据的延迟周期数`define tRFC_delay 4'd6 // 7个周期 仅初始化时两次自刷新操作的最小间隔周期数module sd_ctrl(clk,rst_n,sd_cke,sd_cs_n,sd_ras_n,sd_cas_n,sd_we_n,sd_dqm,addr,ba,data,irq,state_led,rst_led,hbr_n,hbg_n,rd_en,fifo_rd,fifo_full,rst_v2);input clk,rst_n,hbg_n;output sd_cke,sd_ras_n,sd_cas_n,sd_we_n;output state_led; // 总线控制权output rst_led; // rst output [1:0] sd_dqm;output [11:0] addr;output [1:0] ba;inout [63:0] data;output [3:0] sd_cs_n;output [3:0] irq; //irq signal to DSPsoutput hbr_n;output rd_en,rst_v2;input fifo_full;input [63:0] fifo_rd;reg rden,rstv2;assign rd_en=rden;assign rst_v2=rstv2;reg hbr; //总线仲裁输出 FPGA获reg [11:0] addro;assign hbr_n=hbr;reg [3:0] irq_reg; //IRQ信号寄存器assign irq=irq_reg;reg [63:0] datatest; //内部产生的测试数据reg [63:0] datao; //向SDRAM 输出的数据reg ioro; //三态控制assign data = ioro?datao:64'hzzzzzzzzzzzzzzzz;reg [12:0] state; // 状态机 的状态寄存器reg [3:0] add_count;reg [63:0] data_read; // 从SDRAM 输入reg rst_flag,hbg_flag; //复位时亮 获得总线控制权时亮assign state_led=hbg_flag;assign rst_led=rst_flag; always @ (posedge clk) if (!rst_n) rst_flag<=1'b1; else rst_flag<=1'b0; always @ (negedge clk) if (hbg_n) hbg_flag<=1'b1; else hbg_flag<=1'b0; reg [8:0] wrtime; //写SDRAM的次数reg [2:0] sd_cmd; assign {sd_ras_n,sd_cas_n,sd_we_n} = sd_cmd; //发命令字parameter cmd_nop = 3'b111, //RAS、CAS、WE cmd_refresh = 3'b001, // fpga刷新 :201的集成SDRAM控制器负责刷 // fpga中仅在初始化时刷新(发此刷新命令两次), //不再像一般操作中需在数据操作过程中定时刷 cmd_active = 3'b011, // 激活 cmd_read_a = 3'b101, // 读命令 (数据流向FPGA) cmd_write_a = 3'b100, // 写命令 cmd_precharge = 3'b010, // 预充电 cmd_mode_set = 3'b000; // 模式设置 assign sd_cke = 1'b1; //SDRAM时钟使能 cke上电一直有效assign sd_cs_n = 4'b0000; //SDRAM片选 cs_n上电一直有效assign sd_dqm = 2'b00; //高低16位掩码,dqm上reg [11:0] addr; //12根地址线,行列复用 行4096 列 256reg [1:0] ba; //块 共4个块 4096 × 列 256)reg [3:0] burst_cnt; //突发次数reg [2:0] tDAL_cnt; //tDAL计数reg [1:0] tRCD_cnt,tRP_cnt,tCAS_delay_cnt; //tRCD,tRP计数,tCAS_delay reg [3:0] tRFC_cnt; //tRFC计数reg read_write;reg init_delay_cnt_en,init_delay_over; //reg [13:0] init_delay_cnt; //初始化计数器 值100~200usreg [1:0] init_refresh_cnt; //初始化刷新计数器reg refresh_req; // 定时刷新计数器 的 刷新请求 (现定时刷新计数器没用,由TS201替代)reg refresh_ack; //定时刷新计数器 的 刷新reg [10:0] refresh_cnt; // 定 的计数值reg tMRD_cnt; //MRD 发“reg test_finish; // 测试完256个数向SDRAM //主状态机 状态parameter idle = 13'b0111111111111, // power_on = 13'b1011111111111, //????????? auto_refresh = 13'b1101111111111, //???????? mode_set = 13'b1110111111111, //?????? precharge = 13'b1111011111111, //????? tRFC = 13'b1111101111111, //RFC???? tRP = 13'b1111110111111, //RP???? tMRD = 13'b1111111011111, //MRD???? finish = 13'b1111111101111, n_idle = 13'b1000000000000, //???? n_auto_refresh = 13'b0100000000000, //????? n_active = 13'b0010000000000, //????? n_write_a = 13'b0001000000000, //???????? n_finish = 13'b0000100000000, //???????? n_precharge = 13'b0000010000000, //????? n_tCAS_delay = 13'b0000001000000, //CAS delay?? n_tRCD = 13'b0000000100000, //RCD???? n_tRP = 13'b0000000010000, //RP???? n_tRFC = 13'b0000000001000, //RFC???? n_tDAL = 13'b0000000000100, //DAL???? n_read_data = 13'b0000000000010, //????? n_write_data = 13'b0000000000001; //?????always @ (negedge clk or negedge rst_n) if(!rst_n) //复位 操作 begin state <= power_on; init_delay_cnt_en <= 1'b0; init_refresh_cnt <= 2'b00; tRFC_cnt <= 3'b000; tRP_cnt<= 1'b0; tMRD_cnt <= 1'b0; burst_cnt <= 4'b0000; tRFC_cnt <= 3'b000; tDAL_cnt <= 3'b000; tRP_cnt <= 1'b0; tRCD_cnt <= 1'b0; tCAS_delay_cnt <= 1'b0; read_write <= 1'b0; test_finish<=1'b0; ioro<=1'b0; wrtime<=0; datao<=0; irq_reg<=4'b1111; rstv2<=0; rden<=0; end else case(state) //状态转换 //////////////////////////////////////////////// power_on: begin sd_cmd<=cmd_nop; addr[11:0]<=12'hfff; init_delay_cnt_en <= 1'b1; init_refresh_cnt <= 2'b00; tRP_cnt<= 1'b0; tMRD_cnt <= 1'b0; burst_cnt <= 4'b0000; tRFC_cnt <= 3'b000; tDAL_cnt <= 3'b000; tRP_cnt <= 1'b0; tRCD_cnt <= 1'b0; tCAS_delay_cnt <= 1'b0; read_write <= 1'b0; test_finish<=1'b0; hbr<=1'b0; //总 addro<=12'b010000000000; add_count<=0; if(init_delay_over) //初始化等待 100us begin init_delay_cnt_en <= 1'b0; state <= precharge; end else begin state <= power_on; sd_cmd<=cmd_nop; end end //////////////////////////////////////////////// idle: begin datao<=64'hffffffffffffffff; state<=n_idle; addr[11:0]<=12'hfff; sd_cmd<=cmd_nop; end //////////////////////////////////////////////// auto_refresh: begin sd_cmd <= cmd_refresh; addr[11:0]<=12'hfff; ba<=2'b00; if(init_refresh_cnt == `init_refresh_time) //???????????? begin state <= tRFC; end else begin init_refresh_cnt <= init_refresh_cnt + 2'b01; state <= tRFC; end end //////////////////////////////////////////////// mode_set: begin if(test_finish) begin init_refresh_cnt <= 2'b00; sd_cmd <= cmd_mode_set; addr[11:0]<=12'b000000100111; //CL=2,full-page burst,to match the TS201 SDram controller state <= tMRD; end else begin init_refresh_cnt <= 2'b00; sd_cmd <= cmd_mode_set; addr[11:0]<=12'b000000100011; //CL=2,8 burst,to match the TS201 SDram controller state <= tMRD; end end //////////////////////////////////////////////// precharge: begin state <= tRP; sd_cmd <= cmd_precharge; addr[10]<=1'b1; end tRP: begin sd_cmd <= cmd_nop; addr[11:0]<=12'hfff; if(tRP_cnt == `tRP_delay) begin tRP_cnt <= 2'b00; state <= auto_refresh; end else begin tRP_cnt <= tRP_cnt + 2'b01; state <= tRP; end end //////////////////////////////////////////////// tRFC: begin sd_cmd <= cmd_nop; if(tRFC_cnt == `tRFC_delay) begin tRFC_cnt <= 4'b0000; if(init_refresh_cnt == 2'b11) state <= mode_set; else begin init_refresh_cnt <= init_refresh_cnt + 2'b01; state <= auto_refresh; end end else begin tRFC_cnt <= tRFC_cnt + 4'b0001; state <= tRFC; end end //////////////////////////////////////////////// tMRD: begin if(test_finish) begin sd_cmd <= cmd_nop; if(tMRD_cnt == `tMRD_delay) begin tMRD_cnt <= 1'b0; state <= n_finish; addr<=0; end else begin tMRD_cnt <= 1'b1; state <= tMRD; end end else begin sd_cmd <= cmd_nop; if(tMRD_cnt == `tMRD_delay) begin tMRD_cnt <= 1'b0; state <= n_idle; addr<=0; end else begin tMRD_cnt <= 1'b1; state <= tMRD; end end end //////////////////////////////////////////////// n_idle: // begin// if(add_count>7)// begin// test_finish<=1;// state<=precharge;// end// else begin datao<=64'hffffffffffffffff; sd_cmd <= cmd_nop; if (wrtime>=32) if(add_count==7) begin test_finish<=1; state<=precharge; end else begin add_count<=add_count+1; state<=n_active; addro<=12'b010000000000; wrtime<=0; end else begin hbr<=1'b0; state <= n_active; end end //////////////////////////////////////////////// n_auto_refresh: begin sd_cmd <= cmd_refresh; refresh_ack <= 1'b0; state <= n_tRFC; end //////////////////////////////////////////////// n_active: begin datao<=64'hffffffffffffffff; addr<=add_count; ba<=2'b00; sd_cmd <= cmd_active; state <= n_tRCD; end //////////////////////////////////////////////// n_write_a: begin sd_cmd <= cmd_write_a; addr<=addro; datao<=datatest; ioro<=1'b1; state <= n_write_data; end //////////////////////////////////////////////// n_finish: begin sd_cmd <= cmd_active; //use "active" to break full-page burst addr<=33; irq_reg<=4'b0000; ioro<=1'b0; addr<=12'bzzzzzzzzzzzz; sd_cmd<=3'bzzz; hbr<=1'b1; state<=finish; end //////////////////////////////////////////////// finish: begin sd_cmd <= 3'bzzz; irq_reg<=4'b1111; ioro<=1'b0; addr<=12'bzzzzzzzzzzzz; sd_cmd<=3'bzzz; state <= finish; hbr<=1'b1; end //////////////////////////////////////////////// n_precharge: begin sd_cmd <= cmd_precharge; state <= n_tRP; end //////////////////////////////////////////////// n_tRP: begin sd_cmd <= cmd_nop; if(tRP_cnt == `tRP_delay) begin tRP_cnt <= 2'b00; state <= n_auto_refresh; end else begin tRP_cnt <= tRP_cnt + 2'b01; state <= n_tRP; end end //////////////////////////////////////////////// n_tRFC: begin sd_cmd <= cmd_nop; if(tRFC_cnt == `tRFC_delay) begin tRFC_cnt <= 4'b0000; state <= n_idle; end else begin tRFC_cnt <= tRFC_cnt + 4'b0001; state <= n_tRFC; end end //////////////////////////////////////////////// n_tRCD: begin sd_cmd <= cmd_nop; if(tRCD_cnt == `tRCD_delay) begin tRCD_cnt <= 2'b00; state <= n_write_a; end else begin tRCD_cnt <= tRCD_cnt + 2'b01; state <= n_tRCD; end end //////////////////////////////////////////////// n_tDAL: begin //4个周期 sd_cmd <= cmd_nop; if(tDAL_cnt == `tDAL_delay) begin tDAL_cnt <= 3'b000; state <= n_idle; addro[11:0]<=addro+8; end else begin tDAL_cnt <= tDAL_cnt + 3'b001; state <= n_tDAL; end end //////////////////////////////////////////////// n_write_data: begin sd_cmd <= cmd_nop; datao<=datatest; if(burst_cnt == `burst_cnt_time_write) begin burst_cnt <= 4'b0000; state <= n_tDAL; wrtime<=wrtime+1; end else begin burst_cnt <= burst_cnt + 4'b0001; state <= n_write_data; end end default: state <= power_on; endcase //////////初始化计数器/////////////////////// always @ (negedge clk or negedge rst_n) //初始化计数150us if(!rst_n) begin init_delay_over <= 1'b0; init_delay_cnt <= 14'd0; end else if(init_delay_cnt_en) if(init_delay_cnt == `init_delay) //150us约15000个周期 begin init_delay_over <= 1'b1; init_delay_cnt <= 14'd0; end else init_delay_cnt <= init_delay_cnt + 14'd1; else init_delay_cnt <= 14'd0;//////////生成测试数据/////////////////////// always @ (posedge clk) if (state==power_on) datatest<=64'h8080000010000000; else begin if(state==n_write_data) begin datatest<=datatest+1; end else ; //完整的IF结构 编程风 end///////////////////////////////// //always @ (negedge clk or negedge rst_n)// if (!rst_n)// begin// refresh_req <= 1'b0;// refresh_cnt <= 11'b00000000000;// end// else// begin// // if(refresh_cnt == `refresh_cnt_time) //64ms??8192???1015.625??,1000// begin// refresh_cnt <= 11'b00000000000;// refresh_req <= 1'b1;// end// else// begin// refresh_cnt <= refresh_cnt + 11'b00000000001;// end// if(refresh_ack)// refresh_req <= 1'b0;// else// ;// endendmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -