无聊了,发个SRAM控制器的verilog代码吧,仿真通过。
`timescale 1ns / 1ns//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 02:18:56 11/20/2009
// Design Name:
// Module Name: sram_ctrl_top
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
/////性能很低的SRAM控制器,好在简单易懂,占用资源也小。6个周期完成一个读或者写操作......////
/////只能操作一片16位宽的异步SRAM,想控制更多可以自己修改..//////
/////以下信号名称顾名思义.../////
module sram_ctrl_top(
bus2ip_clk,
bus2ip_reset,
ip2bus_data,
ip2bus_wrack,
ip2bus_rdack,
bus2ip_addr,
bus2ip_data,
bus2ip_rnw,
bus2ip_cs,
mem_a,
mem_dout,
mem_din,
mem_cen,
mem_oen,
mem_wen
);
parameter IDLE = 'd0;
parameter RD_LATCH = 'd1;
parameter RD_ACTIVE = 'd2;
parameter RD_FINISH = 'd3;
parameter WR_LATCH = 'd4;
parameter WR_ACTIVE1 = 'd5;
parameter WR_ACTIVE2 = 'd6;
parameter WR_FINISH = 'd7;
input bus2ip_clk, bus2ip_reset, bus2ip_rnw, bus2ip_cs;
input bus2ip_addr;
input bus2ip_data;
input mem_din;
output ip2bus_wrack, ip2bus_rdack;
output ip2bus_data;
output mem_dout;
output mem_a;
output mem_cen, mem_oen, mem_wen;
reg NS, CS;
reg mem_dout, ip2bus_data;
reg mem_a;
reg mem_cen, mem_oen, mem_wen;
reg ip2bus_wrack, ip2bus_rdack;
always@(posedge bus2ip_clk)
if(bus2ip_reset == 1'b1)
CS <= IDLE;
else
CS <= NS;
always@(*)
begin
case(CS)
IDLE:begin //// CS信号有效后,根据RNW的高低,1进入读状态,0进入写状态.....////
if(bus2ip_cs)
if(bus2ip_rnw)
NS = RD_LATCH;
else
NS = WR_LATCH;
else
NS = IDLE;
end
RD_LATCH:begin ////在这个状态锁存读地址数据,CE和OE信号也拉低....////
NS = RD_ACTIVE;
end
RD_ACTIVE:begin////在这个状态保持,等待SRAM的输出稳定..../////
NS = RD_FINISH;
end
RD_FINISH:begin/////锁存SRAM输出的数据并给出RDACK信号...,然后回到初始状态.//////
NS = IDLE;
end
WR_LATCH:begin/////在这个状态锁存上层给的写地址和写数据.../////
NS = WR_ACTIVE1;
end
WR_ACTIVE1:begin/////拉低CE,OE,WE信号.../////
NS = WR_ACTIVE2;
end
WR_ACTIVE2:begin////继续拉低这些信号等待稳定...////
NS = WR_FINISH;
end
WR_FINISH:begin ////拉高WE信号,同时给出WRACK信号,注意此时ADDR和DOUT的数据继续给出,防止不稳定..../////
NS = IDLE;
end
default: NS = IDLE;
endcase
end
////下面是具体的操作,很容易看懂就不详细说了...///
always@(posedge bus2ip_clk)
if(CS == IDLE)
mem_a <= 1'b0;
else
if((CS == RD_LATCH)||(CS == WR_LATCH))
mem_a <= bus2ip_addr;
else
mem_a <= mem_a;
always@(posedge bus2ip_clk)
if(CS == IDLE)
mem_dout <= 1'b0;
else
if(CS == WR_LATCH)
mem_dout <= bus2ip_data;
else
mem_dout <= mem_dout;
always@(posedge bus2ip_clk)
if(CS == IDLE)
ip2bus_data <= 1'b0;
else
if(CS == RD_FINISH)
ip2bus_data <= mem_din;
else
ip2bus_data <= ip2bus_data;
always@(posedge bus2ip_clk)
if(CS == IDLE)
ip2bus_rdack <= 1'b0;
else
if(CS == RD_FINISH)
ip2bus_rdack <= 1'b1;
else
ip2bus_rdack <= 1'b0;
always@(posedge bus2ip_clk)
if(CS == IDLE)
ip2bus_wrack <= 1'b0;
else
if(CS == WR_FINISH)
ip2bus_wrack <= 1'b1;
else
ip2bus_wrack <= 1'b0;
always@(posedge bus2ip_clk)
if(CS == IDLE)
mem_cen <= 1'b1;
else
mem_cen <= 1'b0;
always@(posedge bus2ip_clk)
if(CS == IDLE)
mem_oen <= 1'b1;
else
mem_oen <= 1'b0;
always@(posedge bus2ip_clk)
if(CS == IDLE)
mem_wen <= 1'b1;
else
if((CS == WR_ACTIVE1)||(CS == WR_ACTIVE2))
mem_wen <= 1'b0;
else
mem_wen <= 1'b1;
endmodule 附上简易仿真代码。能看一下读写波形。
module sram_ctrl_top_tb;
// Inputs
reg bus2ip_clk;
reg bus2ip_reset;
reg bus2ip_addr;
reg bus2ip_data;
reg bus2ip_rnw;
reg bus2ip_cs;
reg mem_din;
// Outputs
wire ip2bus_data;
wire ip2bus_wrack;
wire ip2bus_rdack;
wire mem_a;
wire mem_dout;
wire mem_cen;
wire mem_oen;
wire mem_wen;
// Instantiate the Unit Under Test (UUT)
sram_ctrl_top uut (
.bus2ip_clk(bus2ip_clk),
.bus2ip_reset(bus2ip_reset),
.ip2bus_data(ip2bus_data),
.ip2bus_wrack(ip2bus_wrack),
.ip2bus_rdack(ip2bus_rdack),
.bus2ip_addr(bus2ip_addr),
.bus2ip_data(bus2ip_data),
.bus2ip_rnw(bus2ip_rnw),
.bus2ip_cs(bus2ip_cs),
.mem_a(mem_a),
.mem_dout(mem_dout),
.mem_din(mem_din),
.mem_cen(mem_cen),
.mem_oen(mem_oen),
.mem_wen(mem_wen)
);
initial begin
// Initialize Inputs
bus2ip_clk = 0;
bus2ip_reset = 0;
bus2ip_addr = 32'h12345678;
bus2ip_data = 16'hA0A0;
bus2ip_rnw = 0;
bus2ip_cs = 0;
mem_din = 16'hFAFA;
// Wait 100 ns for global reset to finish
#100;
bus2ip_reset = 1;
#100;
bus2ip_reset = 0;
#100;
bus2ip_cs = 1;
bus2ip_rnw = 1;
#20;
bus2ip_cs = 0;
bus2ip_rnw = 0;
#100;
bus2ip_cs = 1;
#20;
bus2ip_cs = 0;
#200;
$stop;
// Add stimulus here
end
always #10 bus2ip_clk = ~bus2ip_clk;
endmodule 还是打个包吧
顶!!!!!!! 嗯,发现了一个BUG,先不说。 mark. 过两天来看程序 找找你留下的bug回复【3楼】ngzhang 兽哥
-----------------------------------------------------------------------
过两天来看程序 找找你留下的bug if((CS == WR_ACTIVE1)||(CS == WR_ACTIVE2))
mem_wen <= 1'b0;
这个好像是bug吧?经波形仿真,有问题
改成:
if(CS == WR_ACTIVE1)
mem_wen <= 1'b0;
else if(CS == WR_ACTIVE2)
mem_wen <= 1'b0;
else
mem_wen <= 1'b1;
就OK啦!不过具体怎么回事我不清楚啊,菜鸟一个,请高手解答! mark. mark SRAM要用6周期这个咋想的啊 回复【9楼】uindex
-----------------------------------------------------------------------
简单稳定。 有没有操作双口RAM的程序啊? hehe 学习了 SRAM时序很简单,只需要在CE使能的时候,掌握好数据线、地址线、与写使能之间的建立和释放 就好。 不错的,但是这是针对那个芯片的啊 仿真过了,实际驱动芯片试过吗? mark
页:
[1]