您的位置:首页 > 其它

【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验十九:SDRAM模块② — 多字读写

2015-04-07 16:35 531 查看

实验十九:SDRAM模块② — 多字读写

表示19.1 Mode Register的内容。

Mode Register

A12

A11

A10

A9

A8

A7

A6

A5

A4

A3

A2

A1

A0

0

0

OP Code

0

0

CAS Latency

BT

Burst Length

A3

Burst Type

0

Sequential

1

Interleave

Burst Length

A2

A1

A0

A3 = 0

A3 = 1

0

0

0

1

1

0

0

1

2

2

0

1

0

4

4

0

1

1

8

8

1

1

1

Full Page

Reserved

A9

Write Mode

0

Burst Read and Burst Write

1

Burst Read and Single Write

A6

A5

A4

CAS Latency

0

1

0

2

0

1

1

3

实验十八我们实现单字读写,实验十九则要实现多字读写。表19.1告诉我们,A2~A0控制Burst Length的长度,为了实现长度为4的字读写,A2~A0的内容设置为3’b010。

7: // Send LMR Cmd. Burst Read & Write, 3'b011 mean CAS latecy = 3, Sequentia 4 burst length

begin rCMD <= _LMR; rBA <= 2'b11; rA <= { 3'd0, 1'b0, 2'd0, 3'b011, 1'b0, 3'b010 }; i <= i + 1'b1; end

代码19.2

如代码基本上,初始化的大致过程与实验十八没有什么两样,仅有更改 Mode Register 的内容,结果如代码19.2所示。对此,写操作还有读操作因为读写字节改变,所以时序也稍微改变了一下。

多字写操作:





图19.1 多字写操作的理想时序图。

图19.1是多字写操作的理想时序图。T1~T3基本上没有什么改变,反之接续的T4~T6会依据Burst Length设置的长度而有所改变。由于 Burst Length 设置为 4,结果T3写第一字数据,T4写第二字数据,T5写第三字数据,T6则写第四字,然而大致的过程如下所示:

l T1,发送ACT命令,BANK地址与行地址;

l T1半周期,SDRAM读取;

l T2,满足TRCD;

l T3,发送WR命令,BANK地址与列地址,还有写第一字数据;

l T3半周期,SDRAM读取;

l T4,写第二字数据;

l T4半周期,SDRAM读取;

l T5,写第三字数据;

l T5半周期,SDRAM读取;

l T6,写第四字数据;

l T6半周期,SDRAM读取;

l T7,满足TWR;

l T8,满足TRP。

Verilog则可以这样描述,结果如代码19.2所示:

1.          1: // Send Active Command with Bank and Row address

[code]2. begin rCMD <= _ACT; rBA <= iAddr[23:22]; rA <= iAddr[21:9]; i <= i + 1'b1; end

3.

4.         2: // wait TRCD 20ns

5.if( C1 == TRCD -1 ) begin C1 <= 14'd0; i <= i + 1'b1; end

6.          else begin rCMD <= _NOP; C1 <= C1 + 1'b1; end

7.

8.          3: // Send Write command with row address, pull up A10 to PR

9.           begin rCMD <= _WR; rBA <= iAddr[23:22]; rA <= {4'b0010,iAddr[8:0]}; D1 <= iData[63:48]; i <= i + 1'b1; end

10.

11. 4:

12.         begin rCMD <= _NOP; D1 <= iData[47:32]; i <= i + 1'b1; end

13.

14.         5:

15. begin rCMD <= _NOP; D1 <= iData[31:16]; i <= i + 1'b1; end

16.

17.         6:

18.         begin rCMD <= _NOP; D1 <= iData[15:0]; i <= i + 1'b1; end

19.

20.         7: // wait TWR 2 clock

21.         if( C1 == TWR -1 ) begin C1 <= 14'd0; i <= i + 1'b1; end

22.          else begin rCMD <= _NOP; C1 <= C1 + 1'b1; end

23.

24. 8: // wait TRP 20ns

25.if( C1 == TRP -1 ) begin C1 <= 14'd0; i <= i + 1'b1; end

26.          else begin rCMD <= _NOP; C1 <= C1 + 1'b1; end

[/code]

代码19.2

假设多字读写由高至低,那么步骤3写入iData[63:48],步骤4写入 iData[47:32],步骤5写入 iData[31:16],步骤6写 iData[15:0]。

多字读操作:





图19.2 多字读操作的理想时序图。

图19.2是多字读操作的理想时序图,大致过程如下:

l T1,发送ACT命令,BANK地址与行地址;

l T1半周期,SDRAM读取;

l T2,满足TRCD;

l T3,发送RD命令,BANK地址与列地址;

l T3半周期,SDRAM读取命令;

l T4,满足 CAS Latency;

l T5,读取第一字数据;

l T6,读取第二字数据;

l T7,读取第三字数据;

l T8,读取第四字数据。

多字读操作相较单字读操作稍微有一些不同,不同的地方除了读取数据的字变长以外,还有 TRP满足在最后两字之中。至于Verilog则可以这样描述,结果如代码19.3所示:

1.         1: // Send Active command with Bank and Row address

[code]2. begin rCMD <= _ACT; rBA <= iAddr[23:22]; rA <= iAddr[21:9]; i <= i + 1'b1; end

3.

4.         2: // wait TRCD 20ns

5.if( C1 == TRCD -1 ) begin C1 <= 14'd0; i <= i + 1'b1; end

6.         else begin rCMD <= _NOP; C1 <= C1 + 1'b1; end

7. 

8.         3: // Send Read command and column address, pull up A10 to PR

9.         begin rCMD <= _RD; rBA <= iAddr[23:22]; rA <= { 4'b0010, iAddr[8:0]}; i <= i + 1'b1; end

10.

11.4: // wait CL 3 clock

12.         if( C1 == CL -1 ) begin C1 <= 14'd0; i <= i + 1'b1; end

13.         else begin rCMD <= _NOP; C1 <= C1 + 1'b1; end

14.

15.5: // Read Data

16.         begin T[63:48] <= S_DQ; i <= i + 1'b1; end

17. 

18.         6: // Read Data

19.         begin T[47:32] <= S_DQ; i <= i + 1'b1; end

20.

21.         7: // Read Data

22.         begin T[31:16] <= S_DQ; i <= i + 1'b1; end

23.

24.8: // Read Data

25.begin T[15:0] <= S_DQ; i <= i + 1'b1; end

[/code]

代码19.3

代码19.3也没有什么好解释的,基本上完全根据图19.2描述。理解完毕以后,我们就可以开始建模了。





图19.3 SDRAM基础模块的建模图。

图19.3是SDRAM基础模块的建模图,这家伙比较实验十八,最大的区别就是iData与oData的位宽增大而已。

sdram_funcmod.v




图19.4 SDRAM功能模块的建模图。

图19.4是SDRAM功能模块的建模图,具体内容我们还是来看代码吧。

1.    module sdram_funcmod

[code]2. (

3.         input CLOCK,

4.         input RESET,

5.

6.         output S_CKE, S_NCS, S_NRAS, S_NCAS, S_NWE,

7.         output [1:0]S_BA,  //2

8.         output [12:0]S_A,  //12, CA0~CA8, RA0~RA12, BA0~BA1, 9+13+2 = 24;

9.         output [1:0]S_DQM,

10.     inout [15:0]S_DQ,

11.

12.         input [3:0]iCall,

13.         output oDone,

14.         input [23:0]iAddr,  // [23:22]BA,[21:9]Row,[8:0]Column

15.input [63:0]iData,

16.         output [63:0]oData

17.    );

[/code]

以上内容为相关的出入端声明,注意第15~16行的位宽增大至64位。

18.        parameter T100US = 14'd13300;

[code]19. // tRP 20ns, tRRC 63ns, tRCD 20ns, tMRD 2CLK, tWR/tDPL 2CLK, CAS Latency 3CLK

20.        parameter TRP = 14'd3, TRRC = 14'd9, TMRD = 14'd2, TRCD = 14'd3, TWR = 14'd2, CL = 14'd3;

21.        parameter  _INIT = 5'b01111, _NOP = 5'b10111, _ACT = 5'b10011, _RD = 5'b10101, _WR = 5'b10100,

22.                  _BSTP = 5'b10110, _PR = 5'b10010, _AR = 5'b10001, _LMR = 5'b10000;

23.

[/code]

以上内容为相关的常量声明。

24.        reg [4:0]i;

[code]25. reg [13:0]C1;

26.        reg [15:0]D1;

27.        reg [63:0]T;

28.        reg [4:0]rCMD;

29.        reg [1:0]rBA;

30.        reg [12:0]rA;

31.        reg [1:0]rDQM;

32.        reg isOut;

33.        reg isDone;

34.

35.        always @ ( posedge CLOCK or negedge RESET )

36.            if( !RESET )

37.                begin

38.                    i <= 4'd0;

39.                  C1 <= 14'd0;

40.                  D1 <= 16'd0;

41.                  T <= 64'd0;

42.                    rCMD <= _NOP;

43.                    rBA <= 2'b11;

44.         rA <= 13'h1fff;

45.           rDQM <= 2'b00;

46.                    isOut <= 1'b1;

47.                  isDone <= 1'b0;

48.                end

[/code]

以上内容为相关的寄存器声明与复位操作,注意寄存器T是用来暂存读取数据。

49.              else if( iCall[3] )

[code]50. case( i )

51.

52.                    0: // Set IO to output State

53.                    begin isOut <= 1'b1; i <= i + 1'b1; end

54.

55.           1: // Send Active Command with Bank and Row address

56.                    begin rCMD <= _ACT; rBA <= iAddr[23:22]; rA <= iAddr[21:9]; i <= i + 1'b1; end

57.      

58.                  2: // wait TRCD 20ns

59.                  if( C1 == TRCD -1 ) begin C1 <= 14'd0; i <= i + 1'b1; end

60.                    else begin rCMD <= _NOP; C1 <= C1 + 1'b1; end

61.

62.                    /*********************************************/

63.

64.                   3: // Send Write command with row address, pull up A10 to PR

65.        begin rCMD <= _WR; rBA <= iAddr[23:22]; rA <= { 4'b0010, iAddr[8:0] }; D1 <= iData[63:48]; i <= i + 1'b1; end

66.

67. 4:  

68.                  begin rCMD <= _NOP; D1 <= iData[47:32]; i <= i + 1'b1; end

69.

70.                  5:

71.                  begin rCMD <= _NOP; D1 <= iData[31:16]; i <= i + 1'b1; end

72.

73.                  6:

74.                  begin rCMD <= _NOP; D1 <= iData[15:0]; i <= i + 1'b1; end

75.            

76.                    /**********************************************/

77.      

78.                  7: // wait TWR 2 clock

79.                  if( C1 == TWR -1 ) begin C1 <= 14'd0; i <= i + 1'b1; end

80.                    else begin rCMD <= _NOP; C1 <= C1 + 1'b1; end

81.

82.                  8: // wait TRP 20ns

83.                  if( C1 == TRP -1 ) begin C1 <= 14'd0; i <= i + 1'b1; end

84.                    else begin rCMD <= _NOP; C1 <= C1 + 1'b1; end

85.                

86.                    /*******************/

87.      

88.                    9: // Generate done signal

89.                    begin isDone <= 1'b1; i <= i + 1'b1; end

90.

91.                  10:

92.                  begin isDone <= 1'b0; i <= 4'd0; end

93.

94.                endcase

[/code]

以上内容为部分核心操作。注意步骤3~6,D1用来驱动SD_Q,而iData赋值D1,次序由高至低。


95.   else if( iCall[2] )

[code]96. case( i )

97. 

98.                  0:

99.                  begin isOut <= 1'b0; D1 <= 16'd0; i <= i + 1'b1; end

100.

101.                    1: // Send Active command with Bank and Row address

102.                    begin rCMD <= _ACT; rBA <= iAddr[23:22]; rA <= iAddr[21:9]; i <= i + 1'b1; end

103.

104.                  2: // wait TRCD 20ns

105.         if( C1 == TRCD -1 ) begin C1 <= 14'd0; i <= i + 1'b1; end

106.                    else begin rCMD <= _NOP; C1 <= C1 + 1'b1; end

107.

108.                    /********************/

109.

110.                3: // Send Read command and column address, pull up A10 to PR

111.           begin rCMD <= _RD; rBA <= iAddr[23:22]; rA <= { 4'b0010, iAddr[8:0]}; i <= i + 1'b1; end

112.

113.                    4: // wait CL 3 clock

114.                    if( C1 == CL -1 ) begin C1 <= 14'd0; i <= i + 1'b1; end

115.           else begin rCMD <= _NOP; C1 <= C1 + 1'b1; end 

116.          

117. /********************/ 

118.

119.                5: // Read Data

120.                    begin T[63:48] <= S_DQ; i <= i + 1'b1; end

121.

122.                  6: // Read Data

123.            begin T[47:32] <= S_DQ; i <= i + 1'b1; end

124.

125.         7: // Read Data

126.                    begin T[31:16] <= S_DQ; i <= i + 1'b1; end

127.      

128.                  8: // Read Data

129.                    begin T[15:0] <= S_DQ; i <= i + 1'b1; end

130.

131.                    /********************/

132.

133.                    9: // Generate done signal

134.                begin rCMD <= _NOP; isDone <= 1'b1; i <= i + 1'b1; end

135.               

136.                  10:

137.                  begin isDone <= 1'b0; i <= 4'd0; end

138.

139.                endcase

[/code]

以上内容为部分核心操作。注意步骤5~8,寄存器T用来暂存读数据,次序由高至低。

140.              else if( iCall[1] )

[code]141. case( i )

142.

143.                  0: // Send Precharge Command

144.         begin rCMD <= _PR; i <= i + 1'b1; end

145.                

146.                  1: // wait TRP 20ns

147.                  if( C1 == TRP -1 ) begin C1 <= 14'd0; i <= i + 1'b1; end

148.                    else begin rCMD <= _NOP; C1 <= C1 + 1'b1; end

149.

150.                    2: // Send Auto Refresh Command

151.begin rCMD <= _AR; i <= i + 1'b1; end

152.

153.                    3: // wait TRRC 63ns

154.         if( C1 == TRRC -1 ) begin C1 <= 14'd0; i <= i + 1'b1; end

155.           else begin rCMD <= _NOP; C1 <= C1 + 1'b1; end

156.

157.                  4: // Send Auto Refresh Command

158.                    begin rCMD <= _AR; i <= i + 1'b1; end

159.

160.                    5: // wait TRRC 63ns

161.                  if( C1 == TRRC -1 ) begin C1 <= 14'd0; i <= i + 1'b1; end

162.                    else begin rCMD <= _NOP; C1 <= C1 + 1'b1; end

163.

164.                    /********************/

165.           

166.                    6: // Generate done signal

167. begin isDone <= 1'b1; i <= i + 1'b1; end

168.

169.                  7:

170.                  begin isDone <= 1'b0; i <= 4'd0; end

171.

172.                endcase

[/code]
以上内容为部分核心操作。刷新操作,基本上没有什么改变。

173.              else if( iCall[0] )

[code]174. case( i )

175.           

176.                   0:  // delay 100us

177.if( C1 == T100US -1 ) begin C1 <= 14'd0; i <= i + 1'b1; end

178.                   else begin C1 <= C1 + 1'b1; end

179.

180.                   /********************/

181.

182.                   1: // Send Precharge Command

183.                   begin rCMD <= _PR; { rBA, rA } <= 15'h3fff; i <= i + 1'b1; end

184.

185.          2: // wait TRP 20ns

186.                 if( C1 == TRP -1 ) begin C1 <= 14'd0; i <= i + 1'b1; end

187.else begin rCMD <= _NOP; C1 <= C1 + 1'b1; end

188.

189.                   3: // Send Auto Refresh Command

190.                   begin rCMD <= _AR; i <= i + 1'b1; end

191.

192.                   4: // wait TRRC 63ns

193.             if( C1 == TRRC -1 ) begin C1 <= 14'd0; i <= i + 1'b1; end

194.                   else begin rCMD <= _NOP; C1 <= C1 + 1'b1; end

195.               

196.                   5: // Send Auto Refresh Command

197.begin rCMD <= _AR; i <= i + 1'b1; end

198.

199.                   6: // wait TRRC 63ns

200.                 if( C1 == TRRC -1 ) begin C1 <= 14'd0; i <= i + 1'b1; end

201.                   else begin rCMD <= _NOP; C1 <= C1 + 1'b1; end

202.

203.                   /********************/

204.

205.          7: // Send LMR Cmd. Burst Read & Write,  3'b011 mean CAS latecy = 3, Sequentia 4 burst length

206.                   begin rCMD <= _LMR; rBA <= 2'b11; rA <= { 3'd0, 1'b0, 2'd0, 3'b011, 1'b0, 3'b010 }; i <= i + 1'b1; end

207.     

208.                 8: // Send 2 nop CLK for tMRD

209.                 if( C1 == TMRD -1 ) begin C1 <= 14'd0; i <= i + 1'b1; end

210.               else begin rCMD <= _NOP; C1 <= C1 + 1'b1; end

211.          

212.                   /********************/

213.

214.                   9: // Generate done signal

215.          begin isDone <= 1'b1; i <= i + 1'b1; end

216.

217.                 10:

218.                 begin isDone <= 1'b0; i <= 4'd0; end

219.

220.                endcase

221.

[/code]
以上内容为部分核心操作。初始化操作,注意步骤7,Burst Length 设置为 3’b010。

222.          assign { S_CKE, S_NCS, S_NRAS, S_NCAS, S_NWE } = rCMD;

[code]223. assign { S_BA, S_A } = { rBA, rA };

224.assign S_DQM = rDQM;

225.assign S_DQ  = isOut ? D1 : 16'hzzzz;

226.         assign oDone = isDone;

227.         assign oData = T;

228.

229.    endmodule

[/code]

以上内容为相关的输出驱动,D1驱动S_DQ,T驱动oData。

sdram_ctrlmod.v
该控制模块的内容基本上与实验十八一模一样,笔者就不重复粘贴了。

sdram_demo.v




图19.5 实验十九的建模图。

图19.5是实验十九的建模图,虽然外观上改变不大,最多只是Data的位宽改为64位而已 ... 话虽如此,核心操作则有点不同,具体的内容让我们来看代码吧。

1.    module sdram_demo

[code]2. (

3.        input CLOCK,

4.        input RESET,

5.        output S_CLK,

6.        output S_CKE, S_NCS, S_NRAS, S_NCAS, S_NWE,

7.        output [12:0]S_A,

8.        output [1:0]S_BA,

9.        output [1:0]S_DQM,

10.    inout [15:0]S_DQ,

11.        output TXD

12.    );

[/code]

以上内容为相关的出入端声明。

13.         wire CLOCK1,CLOCK2;

[code]14.

15.pll_module U1

16.         (

17.                 .inclk0 ( CLOCK ), // 50Mhz

18.                .c0 ( CLOCK1 ),  // 133Mhz -210 degree phase

19.                .c1 ( CLOCK2 )   // 133Mhz

20.         );

21.

[/code]

以上内容为PLL模块的实例化。

22.         wire [1:0]DoneU2;

[code]23. wire [63:0]DataU2;

24.

25.sdram_basemod U2

26.         (

27.              .CLOCK( CLOCK1 ),

28.              .RESET( RESET ),

29.              .S_CKE( S_CKE ),

30.              .S_NCS( S_NCS ),

31.              .S_NRAS( S_NRAS ),

32.              .S_NCAS( S_NCAS ),

33.              .S_NWE( S_NWE ),

34.          .S_A( S_A ),

35.     .S_BA( S_BA ),

36.              .S_DQM( S_DQM ),

37.              .S_DQ( S_DQ ),

38.              .iCall( isCall ),

39.              .oDone( DoneU2 ),

40.              .iAddr( {D1,2’b00} ),

41.               .iData( D2 ),

42.              .oData( DataU2 )

43.         );

44.

[/code]

以上内容为sdram基础模块的实例化。


45.parameter B115K2 = 11'd1157, TXFUNC = 6'd16;

[code]46.

47.         reg [5:0]i,Go;

48.         reg [10:0]C1;

49.         reg [21:0]D1;

50.         reg [63:0]D2,D3;

51.         reg [10:0]T;

52.         reg [1:0]isCall;

53.         reg rTXD;

54.

55.always @ ( posedge CLOCK1 or negedge RESET )

56.             if( !RESET )

57.                 begin

58.                           i <= 6'd0;

59.                          Go <= 6'd0;

60.                          C1 <= 11'd0;

61.       D1 <= 22'd0;

62.                          D2 <= 64'd0;

63. D3 <= 64'd0;

64.                          T <= 11'd0;

65.                 isCall <= 2'b00;

66. rTXD <= 1'b1;

67.                 end

[/code]

以上内容为相关的寄存器声明还有复位操作。第45行是波特率为115200的常量声明还有伪函数入口。

68.             else

[code]69. case( i )

70.

71.                         0:

72.if( DoneU2[1] ) begin isCall[1] <= 1'b0; i <= i + 1'b1; end

73.else begin isCall[1] <= 1'b1; D1 <= 22'd0; D2 <= 64'hAABBCCDDEEFF8899; end

74.

75.                1:

76.                         if( DoneU2[0] ) begin D3 <= DataU2; isCall[0] <= 1'b0; i <= i + 1'b1; end

77.      else begin isCall[0] <= 1'b1; D1 <= 22'd0; end

78.

79.                         2:

80.                         begin T <= { 2'b11, D3[63:56], 1'b0 }; i <= TXFUNC; Go <= i + 1'b1; end

81.

82.                         3:

83.begin T <= { 2'b11, D3[55:48], 1'b0 }; i <= TXFUNC; Go <= i + 1'b1; end

84.

85.                4:

86.                         begin T <= { 2'b11, D3[47:40], 1'b0 }; i <= TXFUNC; Go <= i + 1'b1; end

87.      

88.                         5:

89.                         begin T <= { 2'b11, D3[39:32], 1'b0 }; i <= TXFUNC; Go <= i + 1'b1; end

90. 

91.                         6:

92.                         begin T <= { 2'b11, D3[31:24], 1'b0 }; i <= TXFUNC; Go <= i + 1'b1; end

93.

94.                         7:

95.                begin T <= { 2'b11, D3[23:16], 1'b0 }; i <= TXFUNC; Go <= i + 1'b1; end

96.

97.      8:

98.                         begin T <= { 2'b11, D3[15:8], 1'b0 }; i <= TXFUNC; Go <= i + 1'b1; end

99.

100.                     9:

101.                         begin T <= { 2'b11, D3[7:0], 1'b0 }; i <= TXFUNC; Go <= i + 1'b1; end

102.

103. 10:

104.                         i <= i;

105.                

106.                        /******************************/

107.  

[/code]

以上内容为部分核心操作。步骤0将64位的数据写入地址0,步骤1则将数据从地址0读取。步骤2~9则是轮番将数据送出去。

108.                          16,17,18,19,20,21,22,23,24,25,26:

[code]109. if( C1 == B115K2 -1 ) begin C1 <= 11'd0; i <= i + 1'b1; end

110.else begin rTXD <= T[i - 16]; C1 <= C1 + 1'b1; end

111.                

112.                     27:

113.i <= Go;

114.

115.       endcase

116.

117.          assign S_CLK = CLOCK2;

118.          assign TXD = rTXD;

119.

120.    endmodule

[/code]

以上内容为部分核心操作。步骤16~27是发送一帧数据的伪函数。第117~118行则是相关的输出驱动。综合完毕并且下载程序,如果串口调试程序出现数据 AABBCCDDEEFF8899,结果表示实验成功。

细节一:完整的个体模块

本实验的SDRAM基础模块已经准备就绪。

细节二:读写地址的驱动方式

1.    sdram_basemod

[code]2. (

3.        ...

4.        iAddr( {D1,2’b00} ),

5.        ...

6.    );

7.    reg [21:0]D1;

8.    ...

9.    always @ ( posedge CLOCK1 )

10.     ...

11.case( i )

12.             0:

13.             if( ... ) ...

14.             else D1 <= 22'd0; ...

[/code]

代码19.4

代码19.4是sdram_demo的部分内容,其中iAddr由22位宽的D1与2’b00联合驱动,好奇的朋友一定会觉得疑惑“为什么”?其实这是经过深思以后的写法。实验十九是多字读写操作,其中长度为4,或者说地址的偏移量为4,所以iAddr[1:0] 所指定的范围基本作废。为了正式这点问题,代码19.4需要这样表达。

1.    sdram_basemod

[code]2. (

3.        ...

4.        iAddr( D1 ),

5.        ...

6.    );

7.    reg [23:0]D1;

8.    ...

9.    always @ ( posedge CLOCK1 )

10.     ...

11.case( i )

12.             0:

13.             if( ... ) ...

14.             else D1 <= 24'd1; ...

[/code]

代码19.5

如代码19.5所示,假设我们无视这个问题,直接使用24位宽的D1驱动iAddr,然后将数据写入地址24’d1。根据SDRAM的内部操作,数据会依序写入地址为1234,而不是 0123 或者 4567 之类 ... 如此一来,我们会不小心破坏地址的偏移量。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐