Sie sind auf Seite 1von 9

My SDRAM controller is set at 30 MHz and latency=1 clock.

I use the verilog.


-----------------------------------------------------------------------`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////////
//
// Company:
// Engineer:
//
// Create Date: 20:21:49 09/03/2009
// Design Name:
// Module Name: sd_ctrl
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
////////////////////////////////////////////////////////////////////////////////
//
module sd_ctrl(clk,rst,address,RAS,CAS,WE,CS,CKE,A,DQM,re ad,write,mode,host_dat
a,ready,D,sdread_data);
input clk,rst;
//to sdram
output RAS,CAS,WE,CS,CKE;
output [11:0]A;
output [1:0]DQM;
//from host
input read,write;
input [2:0]mode;
input [19:0]address;
input [15:0]host_data;
output ready;
output [15:0]sdread_data;
//inout
inout [15:0]D;
//element
reg RAS,CAS,WE,CS,CKE;
reg [11:0]A;
reg [1:0]DQM;
reg ready;
wire [15:0]D;
reg [13:0]counter;
reg [19:0]autorefresh_counter;//auto refresh counter
reg zero;
reg [15:0]sdread_data;

reg [11:0]addr_A;
reg [9:0]mode_A;
reg
reg
reg
reg
reg

enrefresh,en_autorefresh_counter;
do_write,down_write;
en_write;
en_read;
row,col;

reg [4:0]state;
reg [4:0]next;
//inout line
assign D=en_write?host_data:16'hzzzz;
//parameter
parameter power_on=5'd0;
parameter precharge_all=5'd1;
parameter trp1=5'd2;
parameter mrs=5'd3;
parameter autorefresh1=5'd4;
parameter autorefresh_nop1=5'd5;
parameter autorefresh2=5'd6;
parameter autorefresh_nop2=5'd7;
parameter idle=5'd8;
parameter active=5'd9;
parameter trcd1=5'd10;
parameter fsm_write1=5'd11;
parameter fsm_write2=5'd12;
parameter fsm_write3=5'd13;
parameter fsm_write4=5'd14;
parameter tdal1=5'd15;
parameter tdal2=5'd16;
parameter fsm_read=5'd17;
parameter read_data1=5'd18;
parameter read_data2=5'd19;
parameter read_data3=5'd20;
parameter read_data4=5'd21;
parameter autoprecharge1=5'd22;
parameter aautorefresh1=5'd23;
parameter aautorefresh_nop1=5'd24;
parameter aautorefresh2=5'd25;
parameter aautorefresh_nop2=5'd26;
always @ *//data & address form host to sdram controller
begin
addr_A[11]=address[19];// select bank
case({row,col})
2'b10:addr_A[10:0]=address[18:8];
2'b01:addr_A[10:0]={3'b000,address[7:0]};
default:addr_A[10:0]=11'd0;
endcase
end
always @ *//mode
begin
case(mode)
3'b000:mode_A=10'b1_00_001_0_000;//1
3'b001:mode_A=10'b0_00_001_0_001;//2

3'b010:mode_A=10'b0_00_001_0_010;//4
3'b011:mode_A=10'b0_00_001_0_011;//8
3'b100:mode_A=10'b0_00_001_0_111;//full page
default:mode_A=10'b1_00_001_0_000;//1
endcase
end
always @ (posedge clk)//do_write data control
begin
if(write)
do_write<=1'b1;
else if(down_write)
do_write<=1'b0;
end
always @(posedge clk)// read data from sdram to sdramcrl
begin
if(en_read)
sdread_data<=D;
end
always @(posedge clk)//counter
begin
if(zero)
counter<=14'd0;
else if(rst)
counter<=14'd0;
else
counter<=counter+14'd1;
end
always @ (posedge clk)//autorefresh_counter
begin
if(en_autorefresh_counter)
autorefresh_counter<=autorefresh_counter+20'd1;
else
autorefresh_counter<=20'd0;
end
always @ *//control autorefresh
begin
if(autorefresh_counter[19:0]==20'b11101010011001100000) //32ms do auto refresh
enrefresh<=1'b1;
else
enrefresh<=1'b0;
end
always @ (posedge clk)//fsm
begin
if(rst)
state <= power_on;
else
state <= next;
end
always@*//fsm
begin
//sdram device deselect
CKE=1'b1;

CS=1'b1;
RAS=1'bx;
CAS=1'bx;
WE=1'bx;
A[11]=1'bx;
A[10]=1'bx;
A[9:0]=addr_A[10:0];
DQM=2'b00;
//control line
ready=1'b0;
zero=1'b1;
en_autorefresh_counter=1'b0;
en_write=1'b0;
down_write=1'b0;
en_read=1'b0;
row=1'b0;
col=1'b0;
case(state)
power_on:
begin
DQM=2'b11;
zero=1'b0;
begin
if(counter==14'd6000)//wait 200us
next=precharge_all;
else
next=power_on;
end
end
precharge_all:
begin
CKE=1'b1;
CS=1'b0;
RAS=1'b0;
CAS=1'b1;
WE=1'b0;
A[11]=1'bx;
A[10]=1'b1;
A[9:0]=10'bxxxxx_xxxxx;
DQM=2'b11;
next=trp1;
end
trp1://min 30ns
begin
DQM=2'b11;
next=autorefresh1;
end
autorefresh1:
begin
CKE=1'b1;
CS=1'b0;
RAS=1'b0;
CAS=1'b0;
WE=1'b1;
A[11]=1'bx;
A[10]=1'bx;

A[9:0]=10'bxxxxx_xxxxx;
DQM=2'b11;
next=autorefresh_nop1;
end
autorefresh_nop1://trc min 90
begin
DQM=2'b11;
zero=1'b0;
begin
if(counter==14'd2)
next=autorefresh2;
else
next=autorefresh_nop1;
end
end
autorefresh2:
begin
CKE=1'b1;
CS=1'b0;
RAS=1'b0;
CAS=1'b0;
WE=1'b1;
A[11]=1'bx;
A[10]=1'bx;
A[9:0]=10'bxxxxx_xxxxx;
DQM=2'b11;
next=autorefresh_nop2;
end
autorefresh_nop2://trc min 90
begin
DQM=2'b11;
zero=1'b0;
begin
if(counter==14'd2)
next=mrs;
else
next=autorefresh_nop2;
end
end
mrs:
begin
CKE=1'b1;
CS=1'b0;
RAS=1'b0;
CAS=1'b0;
WE=1'b0;
A[11]=1'b0;
A[10]=1'b0;
A[9:0]=mode_A;
DQM=2'b11;
next=idle;
end
idle:
begin
CKE=1'b1;

CS=1'b0;
DQM=2'b00;
en_autorefresh_counter=1'b1;
ready=1'b1;
case({enrefresh,read,write})
3'b100:next=aautorefresh1;
3'b101:next=aautorefresh1;
3'b110:next=aautorefresh1;
3'b111:next=aautorefresh1;
3'b000:next=idle;
3'b011:next=idle;
3'b001:next=active;
3'b010:next=active;
default:next=idle;
endcase
end
active://do row precharge
begin
CKE=1'b1;
CS=1'b0;
RAS=1'b0;
CAS=1'b1;
WE=1'b1;
A[11]=addr_A[11];//active bank A
A[10]=addr_A[10];
A[9:0]=addr_A[9:0];
DQM=2'b00;
row=1'b1;
next=trcd1;
end
trcd1://trcd min 30
begin
DQM=2'b00;
begin
if(do_write)
next=fsm_write1;
else
next=fsm_read;
end
end
fsm_write1://write cmd in & write data
begin
CKE=1'b1;
CS=1'b0;
RAS=1'b1;
CAS=1'b0;
WE=1'b0;
A[11]=addr_A[11];//write in bank A
A[10]=1'b1;
A[9:0]=addr_A[9:0];
DQM=2'b00;
en_write=1'b1;
down_write=1'b1;
col=1'b1;
next=fsm_write2;
end

fsm_write2://nop
begin
DQM=2'b00;
en_write=1'b1;
next=fsm_write3;
end
fsm_write3://nop
begin
DQM=2'b00;
en_write=1'b1;
next=fsm_write4;
end
fsm_write4://nop
begin
DQM=2'b00;
en_write=1'b1;
next=tdal1;
end
tdal1://twr
begin
DQM=2'b00;
next=tdal2;
end
tdal2://trp
begin
DQM=2'b00;
next=idle;
end
fsm_read://read cmd in
begin
CKE=1'b1;
CS=1'b0;
RAS=1'b1;
CAS=1'b0;
WE=1'b1;
A[11]=addr_A[11];//read from bank A
A[10]=1'b1;
A[9:0]=addr_A[9:0];
DQM=2'b00;
en_read=1'b1;
col=1'b1;
next=read_data1;
end
read_data1://latency=1
begin
DQM=2'b00;
en_read=1'b1;
next=read_data2;
end
read_data2:
begin

DQM=2'b00;
en_read=1'b1;
next=read_data3;
end
read_data3:
begin
DQM=2'b00;
en_read=1'b1;
next=read_data4;
end
read_data4:
begin
DQM=2'b00;
next=autoprecharge1;
end
autoprecharge1: //trp min is 30 , do autoprecharge
begin
DQM=2'b00;
next=idle;
end
aautorefresh1:
begin
CKE=1'b1;
CS=1'b0;
RAS=1'b0;
CAS=1'b0;
WE=1'b1;
A[11]=1'bx;
A[10]=1'bx;
A[9:0]=10'bxxxxx_xxxxx;
DQM=2'b11;
next=aautorefresh_nop1;
end
aautorefresh_nop1://trc min 90
begin
DQM=2'b11;
zero=1'b0;
begin
if(counter==14'd2)
next=aautorefresh2;
else
next=aautorefresh_nop1;
end
end
aautorefresh2:
begin
CKE=1'b1;
CS=1'b0;
RAS=1'b0;
CAS=1'b0;
WE=1'b1;
A[11]=1'bx;
A[10]=1'bx;

A[9:0]=10'bxxxxx_xxxxx;
DQM=2'b11;
next=aautorefresh_nop2;
end
aautorefresh_nop2://trc min 90
begin
DQM=2'b11;
zero=1'b0;
begin
if(counter==14'd2)
next=idle;
else
next=aautorefresh_nop2;
end
end
endcase
end

Das könnte Ihnen auch gefallen