FPGA笔记5:基于SRAM读写实验

标签:
fpgaveriloghdl |
分类: FPGA学习笔记 |
SRAM管脚分配:
A0-A14
地址输入
I/O0-I/O7
数据输入、输出口
CEn
芯片使能输入,低有效
OEn
芯片使能输出,低有效
WEn
写使能输入,低有效
VCC 电源
GND 数字地
为节约管脚资源,可以将使能输入CEn和使能输出OEn接地,直接控制写使能WEn 来操作SRAM的读写。
图2 SRAM读时序
图3 SRAM写时序
本实验功能:对SRAM进行遍历式读写,若读写数据一致,指示灯亮;若不一致,指示灯灭
module sram(clk,rst_n,led,
address,write_en,data);
input clk,rst_n;
output led;//指示灯,灯亮:读写正确;灯灭:读写数据不一致
output[14:0] address;//SRAM地址
output write_en;//写使能,低电平有效
inout[7:0] data;//SRAM数据
reg[25:0] delay; //完成一次读写操作为1.28s
always @ (posedge clk or negedge rst_n)
if(!rst_n) delay <= 26'd0;
else delay <= delay+1;
wire write;//产生写请求
wire read;//产生读请求
assign write=(delay==26'd9999);//0.2ms写数据
assign read=(delay==26'd19999);//再隔0.2ms读数据
reg [7:0]write_data;//写入数据
always @ (posedge clk or negedge rst_n)//更新下一次的数据
if(!rst_n) write_data <= 8'd0;
else if(delay == 26'd29999) write_data <=
write_data+1'b1;
reg [14:0]addr_r;//数据地址
always @ (posedge clk or negedge rst_n)
if(!rst_n) addr_r <= 15'd0;
else if(delay == 26'd29999) addr_r <= addr_r+1'b1;
//更新下一次数据地址
reg [7:0]read_data;//读取数据
reg led_r;
always @ (posedge clk or negedge rst_n)
if(!rst_n) led_r <= 1'b0;
else if(delay == 26'd29999) begin
else led_r <= 1'b0;//数据读写不一致,灭灯
end
assign led=led_r;
parameter IDLE = 4'd0;
parameter WRT0 = 4'd1;
parameter WRT1 = 4'd2;
parameter REA0 = 4'd3;
parameter REA1 = 4'd4;
reg[3:0] cstate,nstate;
reg[2:0] cnt; //延时计数器
always @ (posedge clk or negedge rst_n)
if(!rst_n) cnt <= 3'd0;
else if(cstate == IDLE) cnt <= 3'd0;
else cnt <= cnt+1'b1;//读写操作均不为零
`define DELAY_160 (cnt==3'd7)//延时20ns*8 完成一次读(写)数据
//两段式状态机写法
always @ (posedge clk or negedge rst_n)
if(!rst_n) cstate <= IDLE;
else cstate <= nstate;
always @ (cstate or write or read or cnt)
case (cstate)
WRT1:nstate<=IDLE;
REA0:if(`DELAY_160)nstate<=REA1;
REA1:nstate<=IDLE;
default:nstate<=IDLE;
endcase
assign address=addr_r; //SRAM 地址
always @ (posedge clk or negedge rst_n)
if(!rst_n) read_data <= 8'd0;
else if(cstate == REA1) read_data <=data;
reg link;//数据线data双向口控制寄存器,连接=1 ,断开=0,处于高阻状态;
always @ (posedge clk or negedge rst_n)
if(!rst_n) link <=1'b0;
else
case (cstate)
IDLE: if(write) link <= 1'b1; //
WRT0: link <= 1'b1;
default: link <= 1'b0;
endcase
assign data = link ? write_data : 8'bzz; // 向SRAM写入数据
assign write_en= ~link;
endmodule