SRAM的控制程序
虽然SRAM的时序比起SDRAM要简单的多,但我是耗了好几天的时间,更让人纠结的是
我竟然会把管脚分配错误,耽误了两天。希望大家给看看,指点一二也好。
//DATA_EN会有一个周期的高电平,如果DATA_EN为高电平说明:
//如果在SRAM的写过程已经写完了一位,数据和地址可以再次产生
//如果在SRAM的读过程可以再产生下一个地址;
//如果在
module SRAM_Ctrl(
SYS_CLK ,
SYS_RST_N ,
SD_CE_N ,
SD_WE_N ,
SD_OE_N ,
SD_ADDR ,//SRAM的地址
SD_DATA ,//SRAM的数据总线
SD_BHE_N ,
SD_BLE_N ,
OUT_DATA ,//SRAM为输出时,读出数据的输出
RD_REQ ,//读写的请求信号
WR_EN ,//向FIFO的写数据请求信号
DATA_EN ,//写地址和数据的指示信号
WR_DONE , //SRAM写满的标志信号
IN_DATA ,
GEN_ADDR ,
WR_REQ
);
input WR_REQ ;
input RD_REQ ;
input SYS_CLK ;
input SYS_RST_N;
input [15 : 0] IN_DATA ;
input [17 : 0] GEN_ADDR;
output DATA_EN ;
output SD_CE_N ;
output WR_EN ;
output SD_WE_N;
output SD_OE_N ;
output SD_BHE_N;
output SD_BLE_N;
input WR_DONE;
output [15 : 0] OUT_DATA;
output [17 : 0] SD_ADDR;
inout [15 : 0] SD_DATA ;
reg SD_WE_N;
reg [ 3 : 0] C_STATE ;
reg [15 : 0] OUT_DATA;
reg DATA_EN;
parameter IDLE = 4'd0,
WR_WAIT = 4'd1,
WRITE = 4'd2,
READ = 4'd3,
RD_WAIT = 4'd4;
assign SD_CE_N = 1'b0;
assign SD_OE_N = 1'b0;
assign SD_BHE_N = 1'b0;
assign SD_BLE_N = 1'b0;
always@( posedge SYS_CLK or negedge SYS_RST_N ) begin
if( !SYS_RST_N ) begin
C_STATE <= IDLE;
SD_WE_N <= 1'b1;
end
else
case( C_STATE )
IDLE : begin
if( WR_REQ ) begin
C_STATE <= WRITE;
SD_WE_N <= 1'b0;
end
else if( RD_REQ ) begin
C_STATE <= READ;
SD_WE_N <= 1'b1;
end
else begin
C_STATE <= IDLE;
SD_WE_N <= 1'b1;
end
end
WRITE : C_STATE <= WR_WAIT;
WR_WAIT : C_STATE <= IDLE ;
READ : C_STATE <= RD_WAIT;
RD_WAIT : C_STATE <= IDLE;
default : C_STATE <= IDLE;
endcase
end
always@( posedge SYS_CLK or negedge SYS_RST_N ) begin
if( !SYS_RST_N )
OUT_DATA <= 16'hzzzz;
else if( C_STATE == READ )
OUT_DATA <= SD_DATA ;
else OUT_DATA <= 16'hzzzz;
end
always@( posedge SYS_CLK or negedge SYS_RST_N ) begin
if( !SYS_RST_N )
DATA_EN <= 1'b0;
else if( (C_STATE == WR_WAIT) || ( C_STATE == RD_WAIT ))
DATA_EN <= 1'b1;
else DATA_EN <= 1'b0;
end
assign I_O_LINK = ( (C_STATE == WRITE ) || (C_STATE == WR_WAIT)) ? 1'b1 : 1'b0;
assign SD_DATA = I_O_LINK ? IN_DATA : 16'hzzzz;
assign WR_EN = ( C_STATE == RD_WAIT ) ? 1'b1 : 1'b0;
assign SD_ADDR = (C_STATE == WRITE || C_STATE == READ ||
C_STATE == WR_WAIT || C_STATE == RD_WAIT ) ? GEN_ADDR : 18'hz;
endmodule
///********************************修改后的SRAM控制程序***************************************
我是很想把SRAM的接口写好的,所以又做了一些改进,但是还是有不如意的地方,就在沿触发的设计上,现在还没有找到
更好的办法,只能先如此,说明一下各个输入输出的作用吧:
WR_REQ:写时钟,一个上升沿写进一位;
RD_REQ:读时钟,一个上升沿读走一位;
WR_EN:向FIFO的写有效信号,连接到FIFO写请求信号
module SRAM_Ctrl(
SYS_CLK ,
SYS_RST_N ,
SD_CE_N ,
SD_WE_N ,
SD_OE_N ,
SD_ADDR ,//SRAM的地址
SD_DATA ,//SRAM的数据总线
SD_BHE_N ,
SD_BLE_N ,
OUT_DATA ,//SRAM为输出时,读出数据的输出
RD_REQ ,
WR_EN ,//向FIFO的写数据请求信号
DATA_EN ,//写地址和数据的指示信号
WR_DONE , //SRAM写满的标志信号
IN_DATA ,
GEN_ADDR ,
WR_REQ
);
input WR_REQ ;
input RD_REQ ;
input SYS_CLK ;
input SYS_RST_N;
input [15 : 0] IN_DATA ;
input [17 : 0] GEN_ADDR;
output DATA_EN ;
output SD_CE_N ;
output WR_EN ;
output SD_WE_N;
output SD_OE_N ;
output SD_BHE_N;
output SD_BLE_N;
input WR_DONE;
output [15 : 0] OUT_DATA;
output [17 : 0] SD_ADDR;
inout [15 : 0] SD_DATA ;
reg [ 3 : 0] C_STATE ;
reg [15 : 0] OUT_DATA;
reg DATA_EN;
reg WR_REQ1;
reg RD_REQ1;
parameter IDLE = 4'd0,
WR_WAIT = 4'd1,
WRITE = 4'd2,
READ = 4'd3,
RD_WAIT = 4'd4;
assign SD_CE_N = 1'b0;
assign SD_OE_N = 1'b0;
assign SD_BHE_N = 1'b0;
assign SD_BLE_N = 1'b0;
always@( posedge SYS_CLK or negedge SYS_RST_N ) begin
if( !SYS_RST_N )
WR_REQ1 <= 1'b0;
else WR_REQ1 <= WR_REQ;
end
always@( posedge SYS_CLK or negedge SYS_RST_N ) begin
if( !SYS_RST_N )
RD_REQ1 <= 1'b0;
else RD_REQ1 <= RD_REQ;
end
wire Pos_WR_REQ = WR_REQ && (~WR_REQ1) ;
wire Pos_RD_REQ = RD_REQ && (~RD_REQ1);
always@( posedge SYS_CLK or negedge SYS_RST_N ) begin
if( !SYS_RST_N ) begin
C_STATE <= IDLE;
end
else
case( C_STATE )
IDLE :
if( Pos_WR_REQ && !WR_DONE)
C_STATE <= WRITE;
else if( Pos_RD_REQ && WR_DONE)
C_STATE <= READ;
else C_STATE <= IDLE;
WRITE : C_STATE <= WR_WAIT;
WR_WAIT : C_STATE <= IDLE ;
READ : C_STATE <= RD_WAIT;
RD_WAIT : C_STATE <= IDLE;
default : C_STATE <= IDLE;
endcase
end
always@( posedge SYS_CLK or negedge SYS_RST_N ) begin
if( !SYS_RST_N )
OUT_DATA <= 16'hzzzz;
else if( C_STATE == READ )
OUT_DATA <= SD_DATA ;
else OUT_DATA <= 16'hzzzz;
end
always@( posedge SYS_CLK or negedge SYS_RST_N ) begin
if( !SYS_RST_N )
DATA_EN <= 1'b0;
else if( (C_STATE == WR_WAIT) || ( C_STATE == RD_WAIT ))
DATA_EN <= 1'b1;
else DATA_EN <= 1'b0;
end
wire I_O_LINK = ( (C_STATE == WRITE ) || (C_STATE == WR_WAIT)) ? 1'b1 : 1'b0;
assign SD_DATA = I_O_LINK ? IN_DATA : 16'hzzzz;
assign WR_EN = ( C_STATE == RD_WAIT ) ? 1'b1 : 1'b0;
assign SD_ADDR = (C_STATE == WRITE || C_STATE == READ ||
C_STATE == WR_WAIT || C_STATE == RD_WAIT ) ? GEN_ADDR : 18'hz;
assign SD_WE_N = ( C_STATE == WRITE || C_STATE == WR_WAIT) ? 1'b0 : 1'b1;
endmodule