ngzhang 发表于 2009-11-20 04:22:04

无聊了,发个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

ngzhang 发表于 2009-11-20 04:23:11

附上简易仿真代码。能看一下读写波形。

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

wc8841484 发表于 2009-11-20 08:28:52

还是打个包吧
顶!!!!!!!

ngzhang 发表于 2009-11-20 18:36:43

嗯,发现了一个BUG,先不说。

WXing 发表于 2010-4-20 14:32:52

mark.

zrx737 发表于 2010-6-16 16:37:13

过两天来看程序 找找你留下的bug回复【3楼】ngzhang 兽哥
-----------------------------------------------------------------------

过两天来看程序 找找你留下的bug

wjf0509 发表于 2011-7-7 17:20:50

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啦!不过具体怎么回事我不清楚啊,菜鸟一个,请高手解答!

tlong_1919 发表于 2011-7-23 17:01:01

mark.

SDbeijixing 发表于 2011-10-10 16:45:55

mark

uindex 发表于 2011-10-10 20:36:00

SRAM要用6周期这个咋想的啊

ngzhang 发表于 2011-10-11 13:16:47

回复【9楼】uindex
-----------------------------------------------------------------------

简单稳定。

wjcusney 发表于 2011-10-11 14:09:55

有没有操作双口RAM的程序啊?

caozhu 发表于 2011-10-12 00:02:53

hehe 学习了

hebeizhangyj 发表于 2011-10-14 09:53:31

SRAM时序很简单,只需要在CE使能的时候,掌握好数据线、地址线、与写使能之间的建立和释放 就好。

lb693294195 发表于 2012-6-14 10:55:47

不错的,但是这是针对那个芯片的啊

source.ant 发表于 2012-6-14 13:36:09

仿真过了,实际驱动芯片试过吗?

moxiaoxiong 发表于 2012-6-15 14:48:07

          mark
页: [1]
查看完整版本: 无聊了,发个SRAM控制器的verilog代码吧,仿真通过。