异步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
原文地址:https://www.cnblogs.com/loadomain/p/3278809.html