当前位置: 首页 > news >正文

Zynq开发实践(FPGA之ddr sdram读写)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        用fpga做图像的时候,如果图像的输入速度和显示速度不匹配,这个时候就需要把图像先放到ddr里面。因为fpga里面毕竟还是空间太小,把图像全部缓存到fpga里面是不现实的。但是提到ddr很多人都会担心学不会,一来ddr pin比较多,布局布线本身就很麻烦了,而且ddr还分成ddr1、ddr2等很多种类型,很担心自己学不会是正常的。但这也是没有必要的。

1、ddr类型多

        ddr的类型确实很多,从ddr1到ddr5,类型确实不少。但是除了ddr1可以用状态机的方法去进行读取之外,其他ddr2以上的类型,一般都是用fpga厂商提供的ip,直接数据读取。也就是说,我们只要会用这些ip就可以操作ddr了。

        此外,不管是哪一代的ddr,一般就是分成数据总线、地址总线和控制总线三部分。只不过由于速度越来越快,很多总线变成了差分结构,电压也是越来越低,电路上的布局布线也是越来越难,但对于使用者来说,最重要的还是怎么用起来,至于底层的原理,除了ddr1可以好好看看之外,其他的ddr只要会使用即可。

2、ddr1的读写

        目前市面上大部分fpga对ddr都是基于第一代ddr进行操作的。这一代的ddr sdram封装简单,速率不高,所以用状态机的方法对它进行操作是完全可以的。ddr1 sdram也是分成数据总线、地址总线、控制总线三部分。其中数据总线和地址总线是复用的。实际使用的时候一般先发行信号,再发列信号。

3、ddr最特殊的地方

        要说初始化、读、写,这些eeprom、nor flash、nand flash、tf卡都会涉及到。也就是说,我们要对数据进行读写,那么先要初始化,然后进行读写操作。但是ddr和它们不一致的地方,那就是需要对ddr进行定时刷新处理。这就意味着初始化之后处于idle状态的时候,还要定时进行ddr刷新的操作,并且刷洗的优先级是最高的,这是其他存储芯片所没有的。

4、zynq访问ddr的不同

        在zynq芯片里面访问ddr有两种方式。一种是类似于7010、7020这种。即ps侧访问ddr,pl侧这边没有ddr。pl这边如果需要访问ddr的数据,基本上只有通过dma的方式去实现。第二种,就是7035或者是更好的soc,这一类的soc里面,pl侧是可以有自己的ddr,也就是说ps和pl都有自己的ddr芯片,好处是两者都可以有自己的数据访问区域,缺点就是价格比较贵。

5、特殊的inout信号

        之前我们学习uart、pwm、vga和spi的时候,对于外部接口要么是输入,要么是输出,很少是有inout信号的。本质上inout就是wire,它是一种特殊接口,相当于我们可以通过这个接口发送数据,也可以通过这个接口接收数据。iic、sdio里面都有这样的信号。当然除了接口可以这么用之外,fpga内部是不允许inout信号存在的。使用的时候一般是这么用的,

module sdram_top(input clk,input rst,input oe, // 1-write, 0-readinput data,output in,inout io);assign io = (oe) ? data : 1'bz;
assign in = io;endmodule

6、先把ddr用起来

        ddr本身布局布线比较麻烦,有很多要求。所以我们学习fpga的时候,可以先学习别人的板子,学习别人的verilog思路,等到自己有需求的时候,再去自己进行硬件电路设计。当然ddr1还是比较简单的,很多ddr1还是sop封装,这种不是bga封装,用起来比其他ddr容易很多,布局布线稍加注意即可。毕竟很多的学习板也是ddr1。

7、ddr1 sdram的读写代码

        这部分代码很多,某火、某原子、某linx,都可以看到类似的verilog代码。除了代码,还可以在视频网站上看到对应的视频讲解。要说verilog最简单的,还是某linx,基本上不到400行就讲解清楚了。里面的实现主要就是状态机+延时操作,初始化好了之后,在idle状态下按需进入read、write、refresh的状态。状态机准备好了,就是进行输出、输入操作即可。原来的代码地址在这,

https://github.com/alinxalinx/AX301/blob/master/src/13_sdram_test/src/sdram/sdram_core.v

        这里方便大家学习,粘贴一下。不同的命令、不同的输出方式、不同的延时条件,基本也是照着芯片手册去写的。

`timescale 1ns / 1ps
module sdram_core
#
(parameter T_RP                    =  4,parameter T_RC                    =  6,parameter T_MRD                   =  6,parameter T_RCD                   =  2,parameter T_WR                    =  3,parameter CASn                    =  3,parameter SDR_BA_WIDTH            =  2,parameter SDR_ROW_WIDTH           =  13,parameter SDR_COL_WIDTH           =  9,parameter SDR_DQ_WIDTH            =  16,parameter SDR_DQM_WIDTH           =  SDR_DQ_WIDTH/8,parameter APP_ADDR_WIDTH          =  SDR_BA_WIDTH + SDR_ROW_WIDTH + SDR_COL_WIDTH,parameter APP_BURST_WIDTH         =  9
)
(input                             clk,input                             rst,                 //reset signal,high for reset//writeinput                             wr_burst_req,        //  write requestinput[SDR_DQ_WIDTH-1:0]           wr_burst_data,       //  write datainput[APP_BURST_WIDTH-1:0]        wr_burst_len,        //  write data length, ahead of wr_burst_reqinput[APP_ADDR_WIDTH-1:0]         wr_burst_addr,       //  write base address of sdram write bufferoutput                            wr_burst_data_req,   //  wrtie data request, 1 clock aheadoutput                            wr_burst_finish,     //  write data is end//readinput                             rd_burst_req,        //  read requestinput[APP_BURST_WIDTH-1:0]        rd_burst_len,        //  read data length, ahead of rd_burst_reqinput[APP_ADDR_WIDTH-1:0]         rd_burst_addr,       //  read base address of sdram read bufferoutput[SDR_DQ_WIDTH-1:0]          rd_burst_data,       //  read data to internaloutput                            rd_burst_data_valid, //  read data enable (valid)output                            rd_burst_finish,     //  read data is end//sdramoutput                            sdram_cke,           //clock enableoutput                            sdram_cs_n,          //chip selectoutput                            sdram_ras_n,         //row selectoutput                            sdram_cas_n,         //colum selectoutput                            sdram_we_n,          //write enableoutput[SDR_BA_WIDTH-1:0]          sdram_ba,            //bank addressoutput[SDR_ROW_WIDTH-1:0]         sdram_addr,          //addressoutput[SDR_DQM_WIDTH-1:0]         sdram_dqm,           //data maskinout[SDR_DQ_WIDTH-1: 0]          sdram_dq             //data
);// State machine code
localparam     S_INIT_NOP  = 5'd0;       //Wait for the power on stable 200us end
localparam     S_INIT_PRE  = 5'd1;       //Precharge state
localparam     S_INIT_TRP  = 5'd2;       //Wait for precharge to complete
localparam     S_INIT_AR1  = 5'd3;       //First self refresh
localparam     S_INIT_TRF1 = 5'd4;       //Wait for the first time since end refresh
localparam     S_INIT_AR2  = 5'd5;       //Second self refresh
localparam     S_INIT_TRF2 = 5'd6;       //Wait for the second time since end refresh
localparam     S_INIT_MRS  = 5'd7;       //Mode register set
localparam     S_INIT_TMRD = 5'd8;       //Wait for the mode register set complete
localparam     S_INIT_DONE = 5'd9;       //The initialization is done
localparam     S_IDLE      = 5'd10;      //Idle state
localparam     S_ACTIVE    = 5'd11;      //Row activation, read and write
localparam     S_TRCD      = 5'd12;      //Row activation wait
localparam     S_READ      = 5'd13;      //Read data state
localparam     S_CL        = 5'd14;      //Wait for latency
localparam     S_RD        = 5'd15;      //Read data
localparam     S_RWAIT     = 5'd16;      //Precharge wait state after read completion
localparam     S_WRITE     = 5'd17;      //Write data state
localparam     S_WD        = 5'd18;      //Write data
localparam     S_TDAL      = 5'd19;      //Wait for the write data and the self refresh end
localparam     S_AR        = 5'd20;      //Self-Refresh
localparam     S_TRFC      = 5'd21;      //Wait for the self refreshreg                         read_flag;
wire                        done_200us;        //After power on, the 200us input is stable at the end of the flag bit
reg                         sdram_ref_req;     // SDRAM self refresh request signal
wire                        sdram_ref_ack;     // SDRAM self refresh request response signal
reg[SDR_BA_WIDTH-1:0]       sdram_ba_r;
reg[SDR_ROW_WIDTH-1:0]      sdram_addr_r;
reg                         ras_n_r;
reg                         cas_n_r;
reg                         we_n_r;
wire[APP_ADDR_WIDTH-1:0]    sys_addr;
reg[14:0]                   cnt_200us;
reg[10:0]                   cnt_7p5us;
reg[SDR_DQ_WIDTH-1:0]       sdr_dq_out;
reg[SDR_DQ_WIDTH-1:0]       sdr_dq_in;
reg                         sdr_dq_oe;
reg[8:0]                    cnt_clk_r; //Clock count
reg                         cnt_rst_n; //Clock count reset signal
reg[4:0]                    state;
reg                         wr_burst_data_req_d0;
reg                         wr_burst_data_req_d1;
reg                         rd_burst_data_valid_d0;
reg                         rd_burst_data_valid_d1;wire end_trp       =  (cnt_clk_r   == T_RP) ? 1'b1 : 1'b0;
wire end_trfc      =  (cnt_clk_r   == T_RC) ? 1'b1 : 1'b0;
wire end_tmrd      =  (cnt_clk_r   == T_MRD) ? 1'b1 : 1'b0;
wire end_trcd      =  (cnt_clk_r   == T_RCD-1) ? 1'b1 : 1'b0;
wire end_tcl       =  (cnt_clk_r   == CASn-1) ? 1'b1 : 1'b0;
wire end_rdburst   =  (cnt_clk_r   == rd_burst_len-4) ? 1'b1 : 1'b0;
wire end_tread     =  (cnt_clk_r   == rd_burst_len+2) ? 1'b1 : 1'b0;
wire end_wrburst   =  (cnt_clk_r   == wr_burst_len-1) ? 1'b1 : 1'b0;
wire end_twrite    =  (cnt_clk_r   == wr_burst_len-1) ? 1'b1 : 1'b0;
wire end_tdal      =  (cnt_clk_r   == T_WR) ? 1'b1 : 1'b0;
wire end_trwait    =  (cnt_clk_r   == T_RP) ? 1'b1 : 1'b0;always@(posedge clk or posedge rst)
beginif(rst == 1'b1)beginwr_burst_data_req_d0 <= 1'b0;wr_burst_data_req_d1 <= 1'b0;rd_burst_data_valid_d0 <= 1'b0;rd_burst_data_valid_d1 <= 1'b0;endelsebeginwr_burst_data_req_d0 <= wr_burst_data_req;wr_burst_data_req_d1 <= wr_burst_data_req_d0;rd_burst_data_valid_d0 <= rd_burst_data_valid;rd_burst_data_valid_d1 <= rd_burst_data_valid_d0;end
endassign wr_burst_finish = ~wr_burst_data_req_d0 & wr_burst_data_req_d1;
assign rd_burst_finish = ~rd_burst_data_valid_d0 & rd_burst_data_valid_d1;
assign rd_burst_data = sdr_dq_in;assign sdram_dqm = {SDR_DQM_WIDTH{1'b0}};
assign sdram_dq = sdr_dq_oe ? sdr_dq_out : {SDR_DQ_WIDTH{1'bz}};
assign sdram_cke = 1'b1;
assign sdram_cs_n = 1'b0;
assign sdram_ba = sdram_ba_r;
assign sdram_addr = sdram_addr_r;
assign {sdram_ras_n,sdram_cas_n,sdram_we_n} = {ras_n_r,cas_n_r,we_n_r};
assign sys_addr = read_flag ? rd_burst_addr:wr_burst_addr;        //Read / write address bus switching control
// power on 200us time, done_200us=1
always@(posedge clk or posedge rst)
beginif(rst == 1'b1)cnt_200us <= 15'd0;else if(cnt_200us < 15'd20_000)cnt_200us <= cnt_200us + 1'b1; 
endassign done_200us = (cnt_200us == 15'd20_000);//------------------------------------------------------------------------------
//7.5uS timer, every 8192 rows of 64ms storage for a Auto refresh
//------------------------------------------------------------------------------
always@(posedge clk or posedge rst)
beginif(rst == 1'b1)cnt_7p5us <= 11'd0;else if(cnt_7p5us < 11'd750)cnt_7p5us <= cnt_7p5us+1'b1;elsecnt_7p5us <= 11'd0;
endalways@(posedge clk or posedge rst)
beginif(rst == 1'b1)sdram_ref_req <= 1'b0;else if(cnt_7p5us == 11'd749)sdram_ref_req <= 1'b1;   else if(sdram_ref_ack)sdram_ref_req <= 1'b0; 
end
//SDRAM state machine
always@(posedge clk or posedge rst)
beginif(rst == 1'b1)state <= S_INIT_NOP;elsebegincase (state)S_INIT_NOP:state <= done_200us ? S_INIT_PRE : S_INIT_NOP;     //After the end of the 200us / reset into the next stateS_INIT_PRE:state <= S_INIT_TRP;     //Precharge stateS_INIT_TRP:state <= (end_trp) ? S_INIT_AR1 : S_INIT_TRP;         //Precharge, waits for T_RP clock cyclesS_INIT_AR1:state <= S_INIT_TRF1;    //First self refreshS_INIT_TRF1:state <= (end_trfc) ? S_INIT_AR2 : S_INIT_TRF1;           //Wait for first self refresh end, T_RC clock cyclesS_INIT_AR2:state <= S_INIT_TRF2;    //Second self refreshS_INIT_TRF2:state <= (end_trfc) ?  S_INIT_MRS : S_INIT_TRF2;       //Wait for second self refresh end T_RC clock cyclesS_INIT_MRS:state <= S_INIT_TMRD;//Mode register set(MRS)S_INIT_TMRD:state <= (end_tmrd) ? S_INIT_DONE : S_INIT_TMRD;      //wait mode register setting is complete with T_MRD clock cyclesS_INIT_DONE:state <= S_IDLE;        // SDRAM initialization setting complete flagS_IDLE:if(sdram_ref_req)beginstate <= S_AR;      //The timing of self refresh requestread_flag <= 1'b1;endelse if(wr_burst_req)beginstate <= S_ACTIVE;  //write SDRAMread_flag <= 1'b0;endelse if(rd_burst_req)beginstate <= S_ACTIVE;  //read SDRAMread_flag <= 1'b1;endelsebeginstate <= S_IDLE;read_flag <= 1'b1;end//row activeS_ACTIVE:if(T_RCD == 0)if(read_flag) state <= S_READ;else state <= S_WRITE;else state <= S_TRCD;//row active waitS_TRCD:if(end_trcd)if(read_flag) state <= S_READ;else state <= S_WRITE;else state <= S_TRCD;//read data S_READ:state <= S_CL;//read data wait S_CL:state <= (end_tcl) ? S_RD : S_CL;//read dataS_RD:state <= (end_tread) ? S_IDLE : S_RD;//Precharge wait state after read completionS_RWAIT:state <= (end_trwait) ? S_IDLE : S_RWAIT;//Write data stateS_WRITE:state <= S_WD;//write dataS_WD:state <= (end_twrite) ? S_TDAL : S_WD;//Wait for writing data and ending with self refreshS_TDAL:state <= (end_tdal) ? S_IDLE : S_TDAL;//Self-RefreshS_AR:state <= S_TRFC;//Self-Refresh waitS_TRFC:state <= (end_trfc) ? S_IDLE : S_TRFC;default:state <= S_INIT_NOP;endcaseend
endassign sdram_ref_ack = (state == S_AR);// SDRAM self refresh response signal//1 clock to write ahead
assign wr_burst_data_req = ((state == S_TRCD) & ~read_flag) | (state == S_WRITE)|((state == S_WD) & (cnt_clk_r < wr_burst_len - 2'd2));
//Read the SDRAM response signal
assign rd_burst_data_valid = (state == S_RD) & (cnt_clk_r >= 9'd1) & (cnt_clk_r < rd_burst_len + 2'd1);//Time delay for generating SDRAM sequential operation
always@(posedge clk or posedge rst)
beginif(rst == 1'b1)cnt_clk_r <= 9'd0;         else if(!cnt_rst_n)cnt_clk_r <= 9'd0;  elsecnt_clk_r <= cnt_clk_r+1'b1;
end//Counter control logic
always@(*) 
begincase (state)S_INIT_NOP: cnt_rst_n <= 1'b0;S_INIT_PRE: cnt_rst_n <= 1'b1;                   //Precharge delay count startS_INIT_TRP: cnt_rst_n <= (end_trp) ? 1'b0:1'b1;  //Wait until the precharge delay count is over and the counter is clearedS_INIT_AR1,S_INIT_AR2:cnt_rst_n <= 1'b1;          //Self refresh count startS_INIT_TRF1,S_INIT_TRF2:cnt_rst_n <= (end_trfc) ? 1'b0:1'b1;   //Wait until the refresh count is finished, and the counter is clearedS_INIT_MRS: cnt_rst_n <= 1'b1;          //Mode register setting, time counting startS_INIT_TMRD: cnt_rst_n <= (end_tmrd) ? 1'b0:1'b1;   //Wait until the refresh count is finished, and the counter is clearedS_IDLE:    cnt_rst_n <= 1'b0;S_ACTIVE:  cnt_rst_n <= 1'b1;S_TRCD:    cnt_rst_n <= (end_trcd) ? 1'b0:1'b1;S_CL:      cnt_rst_n <= (end_tcl) ? 1'b0:1'b1;S_RD:      cnt_rst_n <= (end_tread) ? 1'b0:1'b1;S_RWAIT:   cnt_rst_n <= (end_trwait) ? 1'b0:1'b1;S_WD:      cnt_rst_n <= (end_twrite) ? 1'b0:1'b1;S_TDAL:    cnt_rst_n <= (end_tdal) ? 1'b0:1'b1;S_TRFC:    cnt_rst_n <= (end_trfc) ? 1'b0:1'b1;default: cnt_rst_n <= 1'b0;endcase
endalways@(posedge clk or posedge rst)
beginif(rst == 1'b1)sdr_dq_out <= 16'd0; else if((state == S_WRITE) | (state == S_WD))sdr_dq_out <= wr_burst_data; 
end
//Bidirectional data  directional control logic
always@(posedge clk or posedge rst)
beginif(rst == 1'b1)sdr_dq_oe <= 1'b0;else if((state == S_WRITE) | (state == S_WD))sdr_dq_oe <= 1'b1;elsesdr_dq_oe <= 1'b0;
end//Reads data from the SDRAM
always@(posedge clk or posedge rst)
beginif(rst == 1'b1)sdr_dq_in <= 16'd0;else if(state == S_RD)sdr_dq_in <= sdram_dq;
endalways@(posedge clk or posedge rst)
beginif(rst == 1'b1) begin{ras_n_r,cas_n_r,we_n_r} <= 3'b111;sdram_ba_r <= {SDR_BA_WIDTH{1'b1}};sdram_addr_r <= {SDR_ROW_WIDTH{1'b1}};endelsecase(state)S_INIT_NOP,S_INIT_TRP,S_INIT_TRF1,S_INIT_TRF2,S_INIT_TMRD: begin{ras_n_r,cas_n_r,we_n_r} <= 3'b111;sdram_ba_r <= {SDR_BA_WIDTH{1'b1}};sdram_addr_r <= {SDR_ROW_WIDTH{1'b1}};endS_INIT_PRE: begin{ras_n_r,cas_n_r,we_n_r} <= 3'b010;sdram_ba_r <= {SDR_BA_WIDTH{1'b1}};sdram_addr_r <= {SDR_ROW_WIDTH{1'b1}};endS_INIT_AR1,S_INIT_AR2: begin{ras_n_r,cas_n_r,we_n_r} <= 3'b001;sdram_ba_r <= {SDR_BA_WIDTH{1'b1}};sdram_addr_r <= {SDR_ROW_WIDTH{1'b1}};endS_INIT_MRS:begin   //Mode register setting, which can be set according to actual needs{ras_n_r,cas_n_r,we_n_r} <= 3'b000;sdram_ba_r <= {SDR_BA_WIDTH{1'b0}};  sdram_addr_r <= {3'b000,1'b0,           //Operation mode setting (set here to A9=0, ie burst read / burst write)2'b00,          //Operation mode setting ({A8, A7}=00), the current operation is set for mode register3'b011,         //CAS latency setting1'b0,           //Burst mode3'b111          //Burst length ,full page};endS_IDLE,S_TRCD,S_CL,S_TRFC,S_TDAL: begin{ras_n_r,cas_n_r,we_n_r} <= 3'b111;sdram_ba_r <= {SDR_BA_WIDTH{1'b1}};sdram_addr_r <= {SDR_ROW_WIDTH{1'b1}};endS_ACTIVE: begin{ras_n_r,cas_n_r,we_n_r} <= 3'b011;sdram_ba_r <= sys_addr[APP_ADDR_WIDTH - 1:APP_ADDR_WIDTH - SDR_BA_WIDTH];  sdram_addr_r <= sys_addr[SDR_COL_WIDTH + SDR_ROW_WIDTH - 1:SDR_COL_WIDTH]; endS_READ: begin{ras_n_r,cas_n_r,we_n_r} <= 3'b101;sdram_ba_r <= sys_addr[APP_ADDR_WIDTH - 1:APP_ADDR_WIDTH - SDR_BA_WIDTH];  sdram_addr_r <= {4'b0010,sys_addr[8:0]};//Column address A10=1, set write enable, allow prechargeendS_RD: beginif(end_rdburst){ras_n_r,cas_n_r,we_n_r} <= 3'b110;else begin{ras_n_r,cas_n_r,we_n_r} <= 3'b111;sdram_ba_r <= {SDR_BA_WIDTH{1'b1}};sdram_addr_r <= {SDR_ROW_WIDTH{1'b1}};endendS_WRITE: begin{ras_n_r,cas_n_r,we_n_r} <= 3'b100;sdram_ba_r <= sys_addr[APP_ADDR_WIDTH - 1:APP_ADDR_WIDTH - SDR_BA_WIDTH];  sdram_addr_r <= {4'b0010,sys_addr[8:0]};//Column address A10=1, set write enable, allow prechargeendS_WD: beginif(end_wrburst) {ras_n_r,cas_n_r,we_n_r} <= 3'b110;else begin{ras_n_r,cas_n_r,we_n_r} <= 3'b111;sdram_ba_r <= {SDR_BA_WIDTH{1'b1}};sdram_addr_r <= {SDR_ROW_WIDTH{1'b1}};endendS_AR: begin{ras_n_r,cas_n_r,we_n_r} <= 3'b001;sdram_ba_r <= {SDR_BA_WIDTH{1'b1}};sdram_addr_r <= {SDR_ROW_WIDTH{1'b1}};enddefault: begin{ras_n_r,cas_n_r,we_n_r} <= 3'b111;sdram_ba_r <= {SDR_BA_WIDTH{1'b1}};sdram_addr_r <= {SDR_ROW_WIDTH{1'b1}};endendcase
endendmodule

文章转载自:

http://Mkbflf7z.jwxnr.cn
http://rO0JNJXp.jwxnr.cn
http://keeqTGXf.jwxnr.cn
http://CGIXwM8D.jwxnr.cn
http://qpDG1mpl.jwxnr.cn
http://usekXyEY.jwxnr.cn
http://NNRasvja.jwxnr.cn
http://MROo5ik1.jwxnr.cn
http://LvouJJB9.jwxnr.cn
http://VrUxKeip.jwxnr.cn
http://ADPLcVnD.jwxnr.cn
http://OLEbxsSr.jwxnr.cn
http://v0zOWP69.jwxnr.cn
http://z0xAE0fS.jwxnr.cn
http://bfFh4Vl9.jwxnr.cn
http://sO4eKx54.jwxnr.cn
http://jPedks7e.jwxnr.cn
http://0bu99OHn.jwxnr.cn
http://UO653O6A.jwxnr.cn
http://ZH7ztvKU.jwxnr.cn
http://GBoODMdm.jwxnr.cn
http://s09t02Bj.jwxnr.cn
http://vxQARNSM.jwxnr.cn
http://OPqpk4lN.jwxnr.cn
http://QAyLekWf.jwxnr.cn
http://QZyFzyH1.jwxnr.cn
http://DVsCwJ3o.jwxnr.cn
http://jrLAlLJc.jwxnr.cn
http://80cLUdrH.jwxnr.cn
http://VDmVpxm1.jwxnr.cn
http://www.dtcms.com/a/377888.html

相关文章:

  • LeetCode 热题 160.相交链表(双指针)
  • 西门子 S7-200 SMART PLC 编程:转换 / 定时器 / 计数器指令详解 + 实战案例(案例篇)
  • SAM-Med3D:面向三维医疗体数据的通用分割模型(文献精读)
  • 考研复习-计算机网络-第五章-传输层
  • win11安装jdk8-u211-windows
  • 从传统到智能:3D 建模流程的演进与 AI 趋势 —— 以 Blender 为例
  • 开发避坑指南(46):Java Stream 对List的BigDecimal字段进行求和
  • 在OpenHarmony上适配图形显示【3】——添加显示接口类型
  • Node.js 模块化规范详解
  • Neo4j--登录及简单操作
  • 使用nvm安装Node.js18以下报错解决方案——The system cannot find the file specified.
  • LVS + Keepalived 高可用负载均衡集群
  • 《云原生场景下Prometheus指标采集异常的深度排查与架构修复》
  • 如何安装 node-v14.16.1-x64.msi?Node.js 14.16.1 64位MSI安装详细步骤
  • React 基础
  • 自动化SSL证书管理:应对域名SSL证书更新焦虑
  • 跨平台快速上手:Couchbase 安装与使用指南
  • 【译】Visual Studio 八月更新已发布 —— 更智能的人工智能、更出色的调试功能以及更多控制权
  • python+selenium+PO模式
  • Excel表格如何制作?【图文详解】表格Excel制作教程?电脑Excel表格制作?
  • 【基于CNN的57类交通标志识别系统】
  • 【深度学习新浪潮】Nano Banana(Gemini 2.5 Flash Image)技术解析与开发者实操指南
  • 【Qt开发】显示类控件(二)-> QLCDNumber
  • 三角孔径衍射误差难分析?OAS 软件深度仿真解难题
  • 鸿蒙Next Web组件生命周期详解:从加载到销毁的全流程掌控
  • 【从0开始学习Java | 第17篇】集合(中-Set部分)
  • 【AI指导】Python实现prophet模型的业绩预测
  • RPA-4.0.0.0_SAAS新版本已上线,Edge扩展自动安装,快速实现RPA流程自动化
  • Server 13 ,CentOS 上使用 Nginx 部署多个前端项目完整指南( 支持多端口与脚本自动化 )
  • Java后端测试