zoukankan      html  css  js  c++  java
  • 异步SRAM控制器的Verilog建模

      前言:sram顾名思义静态随机存储器,分为asram异步型和ssram同步型。这里驱动DE2上一块ISSI公司的512KB的asram。

      设计思路:因为实际应用中单字节读写效率不高,所以本设计中仿照sdram的页突发读写,提高sram的效率。因为sram不像sdram需要定期刷新以及行列地址复用,因此省却很多麻烦。拿到手册以后主要关注的就是其最快运行时钟以及数据稳定的建立时间和保持时间,以及控制线的时间参数,这些参数可以由datasheet的时序参数的min time和max time确定,通过这些参数可以简化后续的读写的时序图。

      注意事项:

          (a)在读操作中,读指令有效到数据有效输出有一个CLK的延迟,即latency;

          (b)为了避免读写操作过程中,数据与地址之间的时钟差,其中sys_data_o与sdram_data_r寄存器直接用latch建模,综合后出现的警告;

          (c)模块时钟工作在100MHz,移植过程中pll视情况而定,pll工作于normal模式即可l;

      总结:以上代码结果仿真和硬件测试,并未做超频测试。这里附出源码。

    源码1:sram控制器

      1 `timescale 1 ns / 100 ps
      2 `define SIM
      3 `define IS61LV25616AL_10TL
      4 `define SYS_CLK    100000000
      5 `define BURST    16
      6 `define BURST_WIDTH    8
      7 module sram_ctrl(
      8                             sys_clk,
      9                             sys_rst_n,
     10                             //read
     11                             sys_rd_addr_i,
     12                             rreq_i,
     13                             sys_data_o,
     14                             sram_rd_ack_o,
     15                             sram_rd_valid_o,
     16                             //write
     17                             wreq_i,
     18                             sys_wr_addr_i,
     19                             sys_data_i,
     20                             sram_wr_valid_o,
     21                             sram_wr_ack_o,
     22                             //sram
     23                             sram_ce_n,
     24                             sram_oe_n,
     25                             sram_we_n,
     26                             sram_lb_n,
     27                             sram_ub_n,
     28                             sram_addr,
     29                             sram_data
     30                             );
     31 `ifdef IS61LV25616AL_10TL
     32     `define DSIZE    16
     33     `define ASIZE     18
     34 `endif
     35 input sys_clk;
     36 input sys_rst_n;
     37 //read
     38 input [`ASIZE-1:0] sys_rd_addr_i;
     39 input rreq_i;
     40 output [`DSIZE-1:0] sys_data_o;
     41 output sram_rd_ack_o;
     42 output sram_rd_valid_o;
     43 //write
     44 input [`ASIZE-1:0] sys_wr_addr_i;
     45 input wreq_i;
     46 input [`DSIZE-1:0] sys_data_i;
     47 output sram_wr_ack_o;
     48 output sram_wr_valid_o;
     49 //sram
     50 output sram_ce_n;
     51 output sram_oe_n;
     52 output sram_we_n;
     53 output sram_lb_n;
     54 output sram_ub_n;
     55 output [`ASIZE-1:0] sram_addr;
     56 inout [`DSIZE-1:0] sram_data;
     57 //command
     58 parameter    CMD_NOP = 5'b01000, 
     59                 CMD_READ = 5'b10000,
     60                 CMD_WRITE = 5'b00100;
     61 reg [4:0] cmd_r = CMD_NOP;
     62 assign {sram_we_n,sram_ce_n,sram_oe_n,sram_lb_n,sram_ub_n} = cmd_r; 
     63 //FSM PARAMS
     64 `ifdef SIM
     65     parameter ST_WIDTH = 40;
     66     parameter IDLE = "IDLE.",
     67                     READ = "READ.",
     68                     RD = "RD...",
     69                     END = "END..",
     70                     WR = "WR...";
     71 `else
     72     `define FSM    5
     73     parameter ST_WIDTH = 5;
     74     parameter IDLE = `FSM'b0_0001,
     75                     READ = `FSM'b0_0010,
     76                     RD = `FSM'b0_0100,
     77                     END = `FSM'b0_1000,
     78                     WR = `FSM'b1_0000;
     79 `endif
     80 //capture the posedge of rreq
     81 reg rreq_r = 0;
     82 always @ (posedge sys_clk) begin
     83 if(sys_rst_n == 1'b0) rreq_r <= 0;
     84 else rreq_r <= rreq_i;
     85 end
     86 wire do_rreq = rreq_i & ~rreq_r;
     87 //generate the rd_start signal
     88 reg rd_start = 0;
     89 always @ (posedge sys_clk) begin
     90 if(sys_rst_n == 1'b0) rd_start <= 0;
     91 else if(sram_rd_ack_o == 1'b1) rd_start <= 0;
     92 else if(do_rreq) rd_start <= 1;
     93 else rd_start <= rd_start;
     94 end
     95 //capture the posedge of wreq
     96 reg wreq_r = 0;
     97 always @ (posedge sys_clk) begin
     98 if(sys_rst_n == 1'b0) wreq_r <= 0;
     99 else wreq_r <= wreq_i;
    100 end
    101 wire do_wreq = wreq_i & ~wreq_r;
    102 //generate the rd_start signal
    103 reg wr_start = 0;
    104 always @ (posedge sys_clk) begin
    105 if(sys_rst_n == 1'b0) wr_start <= 0;
    106 else if(sram_wr_ack_o == 1'b1) wr_start <= 0;
    107 else if(do_wreq) wr_start <= 1;
    108 else wr_start <= wr_start;
    109 end
    110 //FSM register
    111 reg [`BURST_WIDTH-1:0] bit_cnt = 0;
    112 reg [ST_WIDTH-1:0] c_st = IDLE;
    113 reg [ST_WIDTH-1:0] n_st = IDLE;
    114 reg link = 0;    //0:read while 1:write
    115 
    116 reg [`ASIZE-1:0] sram_addr = 0;
    117 //fsm-1
    118 always @ (posedge sys_clk) begin
    119 if(1'b0 == sys_rst_n) c_st <= IDLE;
    120 else c_st <= n_st;
    121 end
    122 //fsm-2
    123 always @ (*) begin
    124     case(c_st)
    125     IDLE:begin
    126                 if(rd_start == 1'b1) begin
    127                                             n_st = READ;end
    128                 else if(wr_start == 1'b1) begin
    129                                             n_st = WR;end
    130                 else begin
    131                         n_st = IDLE;end
    132             end
    133     READ:n_st = RD;
    134     RD:n_st = (bit_cnt == `BURST)?END:RD;
    135     END:n_st = IDLE;
    136     WR:n_st = (bit_cnt == `BURST)?END:WR;
    137     default:n_st = IDLE;
    138     endcase
    139 end
    140 //fsm-3
    141 always @ (posedge sys_clk) begin
    142 if(sys_rst_n == 1'b0) begin
    143                                 bit_cnt <= 0;
    144                                 link <= 0;
    145                                 sram_addr <= `ASIZE'h3FFFF;
    146                                 cmd_r <= CMD_NOP;
    147                                 end
    148 else begin
    149         case(n_st)
    150         IDLE:begin
    151                                 bit_cnt <= 0;
    152                                 link <= 0;
    153                                 sram_addr <= sram_addr;
    154                                 cmd_r <= CMD_NOP;
    155                                 end
    156         READ:begin
    157                     bit_cnt <= bit_cnt;
    158                     sram_addr <= sys_rd_addr_i;
    159                     link <=0;
    160                     cmd_r <= CMD_READ;
    161                     end
    162         RD:begin
    163                     bit_cnt <= (bit_cnt == `BURST)?`BURST_WIDTH'd0:bit_cnt + 1'd1;
    164                     link <= 0;
    165                     sram_addr <= (bit_cnt == `BURST-1)?sram_addr:sram_addr + 1'd1;
    166                     cmd_r <= CMD_READ;
    167                     end
    168         END:begin
    169                     bit_cnt <= 0;
    170                     link <= 0;
    171                     sram_addr <= sram_addr;
    172                     cmd_r <= CMD_NOP;
    173                     end
    174         WR:begin
    175                     bit_cnt <= (bit_cnt == `BURST)?`BURST_WIDTH'd0:bit_cnt + 1'd1;
    176                     sram_addr <= (bit_cnt == `BURST)?sram_addr:sram_addr + 1'd1;
    177                     link <=1;
    178                     cmd_r <= CMD_WRITE;
    179                     end
    180         default:begin
    181                                 bit_cnt <= 0;
    182                                 link <= 0;
    183                                 sram_addr <= `ASIZE'h3FFFF;
    184                                 cmd_r <= CMD_NOP;end
    185         endcase
    186         end
    187 end
    188 //generate sys_data_o
    189 reg [`DSIZE-1:0] sys_data_o = 0;
    190 always @ (*) begin
    191 if(c_st == RD) sys_data_o <= sram_data;
    192 else sys_data_o <= sys_data_o;
    193 end
    194 //generate sram_data_r
    195 reg [`DSIZE-1:0] sram_data_r = 0;
    196 always @ (*) begin
    197 if(c_st == WR) sram_data_r <= sys_data_i;
    198 else sram_data_r <= sram_data_r;
    199 end
    200 //assign
    201 assign sram_data = (link == 1'b1)?sram_data_r:16'hzzzz;
    202 assign sram_rd_ack_o = ((c_st == END)&&(rd_start == 1'b1))?1'b1:1'b0;
    203 assign sram_rd_valid_o = (c_st == RD)?1'b1:1'b0;
    204 assign sram_wr_ack_o = ((c_st == END)&&(wr_start == 1'b1))?1'b1:1'b0;
    205 assign sram_wr_valid_o = (c_st == WR)?1'b1:1'b0;
    206 
    207 endmodule

    源码2:读驱动

     1 `timescale 1 ns / 100 ps
     2 `define BURST 16
     3 `define BURST_WIDTH    8
     4 `define ASIZE    18
     5 module sram_rd_driver(
     6                                     sys_clk,
     7                                     sys_rst_n,
     8                                     key_n,
     9                                     sram_rd_valid_i,
    10                                     rreq_o,
    11                                     sys_rd_addr_o
    12                                     );
    13 input sys_clk;
    14 input sys_rst_n;
    15 input key_n;
    16 input sram_rd_valid_i;
    17 output rreq_o;
    18 output [`ASIZE-1:0] sys_rd_addr_o;
    19 //generate the rreq_o
    20 reg key_r = 1;
    21 reg rreq_o = 0;
    22 always @ (posedge sys_clk) begin
    23 if(1'b0 == sys_rst_n) key_r <= 1;
    24 else key_r <= key_n;
    25 end
    26 
    27 wire rd_trigger = ~key_n & key_r;
    28 always @ (posedge sys_clk) begin
    29 if(1'b0 == sys_rst_n) rreq_o <= 0;
    30 else if(rd_trigger) rreq_o <= 1;
    31 else rreq_o <= 0;
    32 end
    33 
    34 //generate the sys_rd_addr_o
    35 reg [`ASIZE-1:0] sys_rd_addr_o = 0;
    36 always @ (posedge sys_clk) begin
    37 if(1'b0 == sys_rst_n) sys_rd_addr_o <= 0;
    38 else if(sram_rd_valid_i) sys_rd_addr_o <= sys_rd_addr_o + 1'd1;
    39 else sys_rd_addr_o <= sys_rd_addr_o;
    40 end
    41 
    42 
    43 endmodule

    源码3:写驱动

     1 `timescale 1 ns / 100 ps
     2 `define BURST 16
     3 `define BURST_WIDTH    8
     4 `define ASIZE    18
     5 `define DSIZE 16
     6 module sram_wr_driver(
     7                                     sys_clk,
     8                                     sys_rst_n,
     9                                     wr_key_n,
    10                                     sram_wr_valid_i,
    11                                     wreq_o,
    12                                     sys_wr_addr_o,
    13                                     sys_data_o
    14                                     );
    15 input sys_clk;
    16 input sys_rst_n;
    17 input wr_key_n;
    18 input sram_wr_valid_i;
    19 output wreq_o;
    20 output [`ASIZE-1:0] sys_wr_addr_o;
    21 output [`DSIZE-1:0] sys_data_o;
    22 
    23 //capture negedge of wr_key_n
    24 reg wr_key_r = 1;
    25 always @ (posedge sys_clk) begin
    26 if(sys_rst_n == 1'b0) wr_key_r <= 1;
    27 else wr_key_r <= wr_key_n;
    28 end
    29 //generate wreq_o
    30 reg wreq_o = 0;
    31 wire wr_trigger = ~wr_key_n & wr_key_r;
    32 always @ (posedge sys_clk) begin
    33 if(1'b0 == sys_rst_n) wreq_o <= 0;
    34 else if(wr_trigger) wreq_o <= 1;
    35 else wreq_o <= 0;
    36 end
    37 //generate sys_data_o and sys_wr_addr_o
    38 reg [`ASIZE-1:0] sys_wr_addr_o = 0;
    39 reg [`DSIZE-1:0] sys_data_o = 0;
    40 
    41 always @ (posedge sys_clk) begin
    42 if(sys_rst_n == 1'b0) begin
    43                                 sys_wr_addr_o <= 0;
    44                                 sys_data_o <= 0;end
    45 else if(sram_wr_valid_i) begin
    46                                     sys_wr_addr_o <= sys_wr_addr_o + 1'd1;
    47                                     sys_data_o <= sys_data_o + 1'd1;end
    48 else begin
    49         sys_wr_addr_o <= sys_wr_addr_o;
    50         sys_data_o <= sys_data_o;end
    51 end
    52 
    53 endmodule

    源码4:顶层例化

     1 `timescale 1 ns / 100 ps
     2 `define ASIZE 18
     3 `define DSIZE    16
     4 module sram(
     5                     sys_clk,
     6                     sys_rst_n,
     7                     key_n,
     8                     wr_key_n,
     9                     //sram
    10                     sram_ce_n,
    11                     sram_oe_n,
    12                     sram_we_n,
    13                     sram_lb_n,
    14                     sram_ub_n,
    15                     sram_data,
    16                     sram_addr
    17                     );
    18 input sys_clk;
    19 input sys_rst_n;
    20 input key_n;
    21 input wr_key_n;
    22 //SRAM
    23 output sram_ce_n;
    24 output sram_oe_n;
    25 output sram_we_n;
    26 output sram_lb_n;
    27 output sram_ub_n;
    28 inout [`DSIZE-1:0] sram_data;
    29 output [`ASIZE-1:0] sram_addr;
    30 
    31 wire rreq;
    32 wire sram_rd_ack;
    33 wire sram_rd_valid;
    34 wire [`ASIZE-1:0] sys_rd_addr;            //from driver module 
    35 wire [`DSIZE-1:0] sys_data_o;
    36 
    37 wire wreq;
    38 wire sram_wr_ack;
    39 wire sram_wr_valid;
    40 wire [`ASIZE-1:0] sys_wr_addr;
    41 wire [`DSIZE-1:0] sys_data_i;
    42 
    43 //for hardware
    44 
    45 wire sys_clk100;
    46 pll100    pll100_inst (
    47                             .inclk0 ( sys_clk ),
    48                             .c0 ( sys_clk100 )
    49                             );
    50 
    51 sram_ctrl                inst_sram_ctrl(
    52                             .sys_clk(sys_clk100),
    53                             .sys_rst_n(sys_rst_n),
    54                             //read
    55                             .sys_rd_addr_i(sys_rd_addr),
    56                             .rreq_i(rreq),
    57                             .sys_data_o(sys_data_o),
    58                             .sram_rd_ack_o(sram_rd_ack),
    59                             .sram_rd_valid_o(sram_rd_valid),
    60                             ////write
    61                             .wreq_i(wreq),
    62                             .sys_wr_addr_i(sys_wr_addr),
    63                             .sys_data_i(sys_data_i),
    64                             .sram_wr_valid_o(sram_wr_valid),
    65                             .sram_wr_ack_o(sram_wr_ack),
    66                             //sram
    67                             .sram_ce_n(sram_ce_n),
    68                             .sram_oe_n(sram_oe_n),
    69                             .sram_we_n(sram_we_n),
    70                             .sram_lb_n(sram_lb_n),
    71                             .sram_ub_n(sram_ub_n),
    72                             .sram_addr(sram_addr),
    73                             .sram_data(sram_data)
    74                             );
    75 
    76 sram_wr_driver                inst_sram_wr_driver(
    77                                     .sys_clk(sys_clk100),
    78                                     .sys_rst_n(sys_rst_n),
    79                                     .wr_key_n(wr_key_n),
    80                                     .sram_wr_valid_i(sram_wr_valid),
    81                                     .wreq_o(wreq),
    82                                     .sys_wr_addr_o(sys_wr_addr),
    83                                     .sys_data_o(sys_data_i)
    84                                     );
    85 
    86 sram_rd_driver                inst_sram_rd_driver(
    87                                     .sys_clk(sys_clk100),
    88                                     .sys_rst_n(sys_rst_n),
    89                                     .key_n(key_n),
    90                                     .sram_rd_valid_i(sram_rd_valid),
    91                                     .rreq_o(rreq),
    92                                     .sys_rd_addr_o(sys_rd_addr)
    93                                     );
    94                                                                     
    95 endmodule
  • 相关阅读:
    jekyll+github搭建个人博客总结
    ES6-let命令
    Ajax-快速上手前后端交互
    第一次项目总结——校园博览会
    Python获取exe文件版本
    @JsonFormat与@DateTimeFormat注解的使用
    前后端时间转化
    左右flex布局
    fastjson将json字符串转化成map的五种方法
    RestTemplate 发送post请求
  • 原文地址:https://www.cnblogs.com/loadomain/p/3278809.html
Copyright © 2011-2022 走看看