F1--DDR3的应用总结(二)-2021.11.29
DDR3应用总结(二)
接DDR3应用总结(一)
4.使用MIG IP核构建DDR3应用
截图取自Xilinx官方手册ug586,figure1-51,MIG IP核是一个逻辑模块,相当于是由它连接了DDR芯片,对内给用户封装了接口,便于用户使用。从图中可以看出,将用户侧和物理侧通过控制器进行了逻辑上的划分,由此也引出来用户侧的一系列问题。下面关于MIG IP核的接口和时序以及MIG IP的配置进行说明。
4.1MIG IP接口信号
init_calib_complete:output信号,板卡上电后,DDR3 IP核会对DDR初始化校正,完成之后IP核拉高此信号,因此用户只有监测到该信号为高电平后才能对DDR进行读写操作(PHY asserts init_calib_complete when calibration is finished)
app_addr:input信号,将DDR实际的行信号,列信号,bank信号转换为逻辑地址信号,这个信号应该等于30bit=1bit rank+3bit bank+16bit row address + 10bit row address(以MT41K512M16HA-125AIT为例),30bit中的最高位rank为是冗余位,并没有用到。
app_cmd:input信号,3bit的IP核操作码输入,000为写命令,001为读命令
app_en:input信号,IP核的命令使能输入:This is the active-High strobe for the app_addr[], app_cmd[2:0] inputs
app_rdy:output信号,IP核输出的,命令ready信号:This output indicates that the UI is ready to accept commands. If the signal is deasserted when app_en is enabled, the current app_cmd and app_addr must be retried until app_rdy is asserted
app_rd_data:output信号,当前读取到的数据,与app_rd_data_valid同步。
app_rd_data_end:output信号,此高电平有效输出指示当前时钟周期是app_rd_data []上输出数据的最后一个周期。 仅当app_rd_data_valid为active-High时有效。(这个信号在用户逻辑中没用)This active-High output indicates that the current clock cycle is the last cycle of output data on app_rd_data[]. This is valid only when app_rd_data_valid is active-High。实际应用过程中,通常不用这个信号。
app_rd_data_valid:output信号,高电平表示当前的 app_rd_data 数据有效。This active-High output indicates that app_rd_data[] is valid.
app_wdf_data:input信号,当前将要写入的数据,This provides the data for write commands.
app_wdf_end:input信号,此高电平有效输入指示当前时钟周期是 app_wdf_data 上输入数据的最后一个周期。This active-High input indicates that the current clock cycle is the last cycle of input data on app_wdf_data[]。应用中通常与app_wdf_wren同步,如下:
assign app_wdf_end = app_wdf_wren;
app_wdf_mask[APP_MASK_WIDTH – 1:0]:input信号,当前输入数据的掩码,mask为1的位对应的数据将被屏蔽掉。This provides the mask for app_wdf_data[]。
app_wdf_rdy:output信号,该输出表明写数据FIFO已准备好接收数据。 当app_wdf_rdy = 1’b1和app_wdf_wren = 1’b1时,接受写入数据。This output indicates that the write data FIFO is ready to receive data. Write data is accepted when app_wdf_rdy = 1’b1 and app_wdf_wren = 1’b1.
app_wdf_wren:input信号,高电平表示 app_wdf_data 数据有效。 This is the active-High strobe for app_wdf_data[].
ui_clk:output信号,MIG输出的用户端时钟(注意与2.3节的核心时钟与工作时钟区分),在4:1(这个比例可以在IP核中配置)模式下是DDR主频的1/4。这个时钟是由MIG生成的,与同频的其他时钟也要做时钟域的隔离。
ui_clk_sync_rst:output信号,MIG输出的用户端复位信号,高电平复位。
sys_clk_i:输入MIG的时钟(注意区分,此处可以在IP核配置)。
clk_ref_i:输入MIG的参考时钟,值固定为200MHz。
sys_rst:输入MIG的复位信号,低电平有效。
4.2MIG IP接口时序
写入addr与cmd:
如上图所示①,②,③情况,只有在③时刻app_en和app_rdy同时为高电平app_cmd(命令)和(app_addr)地址才有效,所以当需要app_cmd,app_addr有效时app_en必须保持到app_rdy为高电平才有效。
写时序:
如上图所示①,②,③种情况,写命令和写数据直接存在三种逻辑关系。
①表示写命令(app_cmd),写当前地址(app_addr)和写数据(app_wdf_data)以及写控制信号(app_en,app_rdy,app_wdf_rdy,app_wdf_wren,app_wdf_end)同时有效。推荐采用这种时序。
②表示写数据(app_wdf_data)和写控制信号(app_wdf_wren,app_wdf_end)先于写命令(app_cmd)和写当前地址(app_addr)以及其他写控制信号(app_en,app_rdy,app_wdf_rdy)一个用户时钟(ui_clk)。
③表示写数据(app_wdf_data)和写控制信号(app_wdf_wren,app_wdf_end)迟于写命令(app_cmd)和写当前地址(app_addr)以及其他写控制信号(app_en,app_rdy,app_wdf_rdy)。最多两个用户时钟(ui_clk)。
读时序:
如上图所示,当读命令(app_cmd)和当前读地址(app_addr)以及读控制信号(app_en,app_rdy)同时有效时,等待读数据有效信号(app_rd_data_valid)有效时读数据(app_rd_data)有效。
4.3MIG IP配置
1.在 IP Catalog 中搜索 Memory Interface Generator,双击打开出现以下页面,点击 Next ,出现 MIG Output Options 。
2.选择A创建设计以创建新的内存控制器设计;在B“Component Name field”一栏中输入IP核组件名称;在C选择要生成的控制器数量;D处,DDR2和DDR3 SDRAM设计支持内存映射的AXI4接口。 AXI4接口仅支持Verilog语言。 如果需要AXI4接口,请在调用MIG工具之前在Vivado Design Suite中将语言选择为“ Verilog”。 如果未选择AXI4界面,则用户界面(UI)是主要界面。
3.引脚兼容的FPGA页面列出了所选系列中具有相同封装的FPGA。 如果从MIG工具生成的引脚需要与其他任何FPGA兼容,则应使用此选项来选择必须与引脚兼容的FPGA。
4.此页面显示所选FPGA系列支持的所有存储器类型。选择DDR3 SDRAM控制器类型,单击下一步以显示“控制器选项”页面。
5.此页面显示了可以选择的各种控制器选项。
A.时钟周期,频率范围受所选FPGA和器件速度等级等因素的限制。这里配置为400MHz这个是DDR3物理引脚的工作频率,即IO缓冲器的工作频率,这里配置为400MHz。
B.PHY与控制器时钟比率–此功能确定物理层(存储器)时钟频率与用户界面时钟频率的比率,例如选择4:1,工作频率为400MHz,那么用户时钟ui_clk为100MHz。由于FPGA逻辑时序的限制,2:1的比率降低了最大存储器接口频率。2:1比例的用户界面数据总线宽度是物理内存接口宽度的四倍,而4:1比例的总线宽度是物理内存接口宽度的八倍(若设置工作频率为400MHz,因为DDR,所以等效于每一个800MHz周期需要16bit数据,此处设置为2:1,则用户时钟ui_clk为200MHz,那么一个200M周期在时间上等于4个800M周期,由此一个用户时钟周期应提供4倍的16bit数据才能做到匹配,同理,设置为4:1时,那么用户数据应该是8倍的16bit)。2:1的比例具有较低的延迟。4:1的比率对于获得最高数据速率是必要的。通常配做4:1。
C.此功能选择设计中使用的内存部分的类型。使用默认
D.选择器件具体型号数据宽度–可以根据之前选择的存储类型在此处选择数据宽度值。 该列表显示了所选part的所有支持的数据宽度。如果列表中并没有自己的芯片类型,可以选择相似的(指容量、位宽一致),也可以点击下面的creat custom port设置自定义的型号。注意,应在select base part中选择与实际芯片位宽大小一样的已有的型号作为基础,修改以下时序参数(DDR datasheet中提供)以及实际的行列线宽,以及bank位宽,生成自定义的型号。
E.数据宽度–可以根据之前选择的存储类型在此处选择数据宽度值。 该列表显示了所选part的所有支持的数据宽度。如果只有一颗DDR3,则此处的值应等于颗粒的物理位宽。不由的想,如果有两颗DDR3,如何做呢?后续将会给出答案。
F.Data mask 视需要而定。
G.Bank Machines数量–列表显示所选设计配置支持的Bank Machines数量。一般设置为4。
H.排序–正常模式允许内存控制器将命令重新排序到内存,以获得最高的效率。 严格模式强制控制器以接收到的确切顺序执行命令。一般设置为Normal。
若是自定义的DDR3型号,应关注Memory Details,是否与DDR3实际情况一致,若不一致则应修改一致继续使用。此处描述的是一片DDR3的情况。
6.除第一个设置输入IP的时钟为200MHz之外(此处设置的是sys_clk_i),其余保持默认。该功能允许选择各种有关存储模式的寄存器值。在初始化期间,将模式寄存器的值加载到加载模式寄存器中。内存地址映射的选择选择红色框中内容。
7.除了这两个选择无缓冲区外,其余保持默认。
A系统时钟–此选项为sys_clk信号对选择时钟类型(单端,差分或无缓冲区)。 选择“无缓冲区”选项时,不会在RTL代码中实例化IBUF原语,并且不会为系统时钟分配引脚。如果在没有执行更改的情况下实现了从MIG为No Buffer选项生成的设计,则设计可能会由于未针对sys_clk_i信号实例化的IBUF而无法实现。 因此,对于无缓冲区方案,需要将sys_clk_i信号连接到内部时钟。
B系统复位电平–可以选择系统复位的电平(sys_rst)。 如果将选项选择为active-Low,则参数RST_ACT_LOW设置为1;如果设置为active-High,则参数RST_ACT_LOW设置为0。
降低I/O功耗–该选项通过在控制器处于空闲状态时自动禁用DQ和DQS IBUF来降低平均I/O功耗。
8.HR Bank的内部终端匹配电阻–内部终端选项可以设置为40、50或60Ω或禁用。 此选择仅适用于HR Bank。通常设置为50即可。
9.引脚模式选择第二个,之后导入UCF文件,进行引脚约束配置。
10.开始一个个的输入DDR3信号对应的管脚,如果事先写好了管脚约束文件,也可以直接载入。填写完成后,点击“Validate”检查,看写的是否有误。
其余的点next即可。
注:MIG输入一个200MHz的时钟sys_clk_i,再输入一个200MHz的参考时钟clk_ref_i。倍频出来DDR3的工作时钟400MHz(工作时钟,IO驱动时钟),分频出来一个100MHz的用户时钟ui_clk。加之前面的工作时钟,核心时钟,都务必分清楚。
5.一个IP控制两颗DDR3
如下原理图,可以清楚的看到,两颗DDR3的相同的控制线连在了一个控制器的相同引脚,而数据线是各自连的。那么也就是说,对于FPGA而言,把外部的位宽为16bit的两颗DDR当成了一个位宽为32bit的DDR3来控制。这种往往是为了扩大容量;或者为了匹配rank位宽;或者为了提升带宽,将两片或者四片甚至更多片DDR3放在一起。
对于这种场景,MIG配置的时候有啥注意事项呢?只需要将4.3节IP配置第5步中的data width设置为实际芯片加起来的位宽即可。如两片16bit位宽颗粒相连,则设置位宽为32bit即可。配置生成的IP核的接口中app_addr仍会多出一位,这一位仍然是rank的冗余位,并无实际意义。其余的用户逻辑且把他当作一片位宽为32bit的DDR3即可。
实际上,用户存入的32bit数据在实际存放时,高位16bit和低位16bit的数据被放到不同的两片DDR3中,唯一的关联就是,这两个位置的物理值是相等的而已。
6.DDR3的乒乓应用
以采集摄像头数据为例,把DDR3当作缓存芯片,那么乒乓操作的思想是在DDR中开辟两块大小为1帧图像的缓冲区,如果读取速度大于写入速度的时候,需要采用乒乓操作的方式发挥DDR弹性缓冲的作用。往缓冲区写的时候,1号缓冲区写满之后,切换到2号缓冲区写,2号写满之后,在往1号去写,如此往复。由于读取速度大于写入速度,因此,读一定是在与当前写不同的另一块缓冲区去读,在底层,可能会对同一块缓冲区的数据读取很多次,但是这并不影响人在视觉上对于画面流畅的影响。这就是通过乒乓操作实现了数据缓冲,匹配了读写两端的速度。如下图所示,
说明:1.每一个bank存储一帧图像数据,bank中每一行为图像的一行数据(即每一次读写的突发长度是一行像素数据),读和写彼此独立进行;2.bank之间的切换由状态机实现,由于读速度大于写速度,则每写完一个bank切换另一个bank去写;每读完一个bank,判断当前写bank,选择不同于写bank的bank进行读。3.由于读速度大于写速度,因此永远不会发生冲突,只是可能某一帧会被重复播放,但在视频应用中,这对用户的视觉不产生任何影响。那么问题来了,如果是读的速度小于写的速度,该如何发挥DDR3的作用呢?留给大家思考,后续的制作中会提及。
7.DDR3测试用例
以四颗MT41K512M16HA-125AIT颗粒为例,介绍如何在一块新制板卡上做关于DDR3的测试。
测试内容:除基本的读写测试之外,应对速度(如400MHz、800MHz)、容量进行测试。
测试策略:一个测试工程,对上述三项全部测试;在MIG的平面地址接口中,按照地址顺序写入确定的已知值,然后在按照相同顺序读出这些已知值做比较,相同则常亮led表示测试通过,否则led闪烁表示测试失败。应注意,当MIG app时序不正确时可能会导致app_rd_valid始终为低电平从而导致led指示灯常亮,出现错误的判断,为了避免这一情况的发生,添加led2指示已经读取了。因此只有led1与led2都常亮的情况下才能得出测试通过的结论。
4片DDR3 MIG的配置,除下图中data width应该设置为64bit外,其余均无需特殊配置。当然相应的ucf文件应含有相应管脚约束。此外,速度测试时应调整IP核中的工作频率分别为400MHz和800MHz。
测试若出现异常,应按照DDR是否初始化成功、MIG app接口时序是否正确、MIG ip配置是否正确、状态机运行状态是否异常方面入手分析。
附verilog测试代码,程序步骤解读如下:
①例化clk ip产生200MMIG参考电压输入
②例化MIG ip通过app接口读写ddr数据
③写两段式状态机,为进行容量测试,写至满容量的90%即可。写完切换至读状态,若读写无误则一直读写。Wr_addr_cnt或者rd_addr_cnt每计数一次,app_addr_begin自增8,这是因为,当工作频率配置为800MHz且用户时钟ui_clk与工作频率的比值配置为4:1时,ui_clk为200MHz。四片DDR3的数据位宽为64bit,由于”“DDR(double data rate)”,所以在每一个800MHz周期应该提供128bit数据,因此每一个200MHz周期应该向MIG提供512bit数据。而在单一内核中,每一个平面地址存储位数为16bit,四片即64bit,那512bit/64bit=8,即一个200MHz周期的512bit数据写入了8个平面地址,因此此处一次突发(即Wr_addr_cnt或者rd_addr_cnt每计数一次),app_addr_begin自增8。
该颗粒平面地址空间有16+10+3=29bit,上一段的描述提到一次突发需要8个地址,那么满容量可以进行多少次突发?即2^29(满地址)/8=67108864,将TEST_LENGTH设置为32’d60000000,即写了60000000/67108864=90%的空间,这样可以满足容量测试的要求。
④结合状态机运行状态和MIG返回的指示信号为app接口信号赋值,此处应结合各信号含义和接口时序核准。
⑤用户判错逻辑,写入和读出的都是从0开始递增的数据,当出错时指示灯闪烁。
module ddr_top(input sys_clk, inout [63:0] ddr3_dq , inout [7:0] ddr3_dqs_n , inout [7:0] ddr3_dqs_p , output [15:0] ddr3_addr , output [2:0] ddr3_ba , output ddr3_ras_n , output ddr3_cas_n , output ddr3_we_n , output ddr3_reset_n , output [0:0] ddr3_ck_p , output [0:0] ddr3_ck_n , output [0:0] ddr3_cke , output [0:0] ddr3_cs_n , output [7:0] ddr3_dm , output [0:0] ddr3_odt , output reg led1, output reg led2 ); wire clk_rst; wire clk_200;reg [29:0] app_addr_begin=0;wire app_en; //写命令使能wire [2:0] app_cmd; //用户读写命令wire app_wdf_wren; //DDR3写使能wire app_wdf_end; //突发写最后一个数标识wire [29:0] app_addr; //用户平面地址wire app_rdy; //设备接收准备就绪 wire app_wdf_rdy; //写响应wire [511:0] app_rd_data; //用户读数据wire app_rd_data_end; //突发读当前时钟最后一个数据wire app_rd_data_valid; //读数据有效wire [511:0] app_wdf_data; //用户写数据wire app_sr_active; //保留wire app_ref_ack; //刷新请求wire app_zq_ack; //ZQ 校准请求wire init_calib_complete; //校准完成信号wire ui_clk ; //用户时钟wire ui_clk_sync_rst; clk_wiz_0 u_clk_wiz_0(.clk_out1(clk_200), .reset(1'b0), .locked(clk_rst), .clk_in1(sys_clk)); mig_7series_0 mig_JC (// Memory interface ports.ddr3_addr (ddr3_addr), // output [15:0] .ddr3_ba (ddr3_ba), // output [2:0].ddr3_cas_n (ddr3_cas_n), // output .ddr3_ck_n (ddr3_ck_n), // output [0:0] .ddr3_ck_p (ddr3_ck_p), // output [0:0] .ddr3_cke (ddr3_cke), // output [0:0] .ddr3_ras_n (ddr3_ras_n), // output .ddr3_reset_n (ddr3_reset_n), // output .ddr3_we_n (ddr3_we_n), // output .ddr3_dq (ddr3_dq), // inout [63:0] .ddr3_dqs_n (ddr3_dqs_n), // inout [7:0] .ddr3_dqs_p (ddr3_dqs_p), // inout [7:0] .init_calib_complete (init_calib_complete), // output .ddr3_cs_n (ddr3_cs_n), // output [0:0] .ddr3_dm (ddr3_dm), // output [7:0] .ddr3_odt (ddr3_odt), // output [0:0] // Application interface ports.app_addr (app_addr), // input [29:0] .app_cmd (app_cmd), // input [2:0] .app_en (app_en), // input .app_wdf_data (app_wdf_data), // input [511:0] .app_wdf_end (app_wdf_end), // input .app_wdf_wren (app_wdf_wren), // input .app_rd_data (app_rd_data), // output [511:0] .app_rd_data_end (app_rd_data_end), // output .app_rd_data_valid (app_rd_data_valid), // output .app_rdy (app_rdy), // output .app_wdf_rdy (app_wdf_rdy), // output .app_sr_req (1'b0), // input .app_ref_req (1'b0), // input .app_zq_req (1'b0), // input .app_sr_active (app_sr_active), // output .app_ref_ack (app_ref_ack), // output .app_zq_ack (app_zq_ack), // output .ui_clk (ui_clk), // output用户时钟输出,其实是通过IP配置自己配出来的 .ui_clk_sync_rst (ui_clk_sync_rst), // output .app_wdf_mask (64'b0), // input [63:0] //写数据屏蔽.sys_clk_i (clk_200),//输入IP的时钟// Reference Clock Ports.clk_ref_i (clk_200),//参考时钟 .sys_rst (clk_rst) // input sys_rst);parameter TEST_LENGTH = 32'd60000000;
//**************1.先写后读状态机state machine
parameter IDLE = 2'd0;
parameter WRITE = 2'd1;
parameter WAIT = 2'd2;
parameter READ = 2'd3;
reg [511:0]my_512_data;
reg [25:0] wr_addr_cnt;
reg [25:0] rd_addr_cnt;
reg [1:0] state;always @(posedge ui_clk or negedge rst_n) beginif((~rst_n)||(error_flag)) begin state <= IDLE; my_512_data <= 512'd0; wr_addr_cnt <= 26'd0; rd_addr_cnt <= 26'd0; app_addr_begin<= 30'd0; endelse if(init_calib_complete)begin //MIG IP核初始化完成case(state)IDLE:beginstate <= WRITE;my_512_data <= 512'd0; wr_addr_cnt <= 26'd0; rd_addr_cnt <= 26'd0; app_addr_begin <= 30'd0; endWRITE:beginif((wr_addr_cnt == TEST_LENGTH-1) &&(app_rdy && app_wdf_rdy))state <= WAIT; //写到设定的长度跳到等待状态else if(app_rdy && app_wdf_rdy)begin //写条件满足my_512_data <= my_512_data + 1; //写数据自增wr_addr_cnt <= wr_addr_cnt + 1; //写计数自增app_addr_begin<= app_addr_begin + 8; //DDR3 地址自增end else begin //写条件不满足,保持当前状态my_512_data <= my_512_data; wr_addr_cnt <= wr_addr_cnt;app_addr_begin<= app_addr_begin; endendWAIT:begin state <= READ; //下一个时钟,跳到读状态rd_addr_cnt <= 26'd0; //读地址复位app_addr_begin<= 30'd0; //DDR3读从地址0endREAD:begin //读到设定的地址长度 if((rd_addr_cnt == TEST_LENGTH -1 ) && app_rdy)state <= IDLE; //则跳到空闲状态 else if(app_rdy)begin //若MIG已经准备就绪,则开始读rd_addr_cnt <= rd_addr_cnt + 1'd1; //用户地址每次加一app_addr_begin <= app_addr_begin + 8; //DDR3地址加8end else begin //若MIG没准备好,则保持原rd_addr_cnt <= rd_addr_cnt;app_addr_begin <= app_addr_begin; endenddefault:beginstate <= IDLE;my_512_data <= 512'd0;wr_addr_cnt <= 26'd0;rd_addr_cnt <= 26'd0;app_addr_begin <= 30'd0;endendcaseendend
//**************2.根据状态机与MIG指示信号为app信号赋值assign app_en =((state == WRITE && (app_rdy && app_wdf_rdy))||(state == READ && app_rdy)) ? 1'b1:1'b0; assign app_cmd =(state == READ) ? 3'd1 :3'd0; assign app_wdf_wren=(state == WRITE && (app_rdy && app_wdf_rdy)) ? 1'b1:1'b0;assign app_wdf_end =app_wdf_wren; assign app_addr =app_addr_begin;assign app_wdf_data=my_512_data;
//*******************3.用户判错逻辑
reg [25:0] rd_cnt;
wire rst_n; //复位,低有效
reg error_flag;
parameter L_TIME = 28'd200_000_000;
reg [27:0] led_cnt; //led计数
wire error; //读写错误标记
assign rst_n = ~ui_clk_sync_rst;//&&myrst
always @(posedge ui_clk or negedge rst_n) beginif(~rst_n) rd_cnt <= 0; //若计数到读写长度,且读有效,地址计数器则�?0 else if(app_rd_data_valid&&(rd_cnt == TEST_LENGTH - 1))rd_cnt <= 0; //其他条件只要读有效,每个时钟自增1else if (app_rd_data_valid)rd_cnt <= rd_cnt + 1;end
//判断错误,读出数据应为计数递增数据
assign error = (app_rd_data_valid && (rd_cnt!=app_rd_data));
always @(posedge ui_clk or negedge rst_n) beginif(~rst_n)led2<=0;else if(rd_cnt==32'd50000000)led2<=1;
end
always @(posedge ui_clk or negedge rst_n) beginif(~rst_n) error_flag <= 0;else if(error)error_flag <= 1;end
//读写测试正确,指示灯led1常亮,反之则闪烁
always @(posedge ui_clk or negedge rst_n) beginif((~rst_n) || (~init_calib_complete )) beginled_cnt <= 28'd0;led1 <= 1'b0;endelse beginif(~error_flag) led1 <= 1'b1; else begin led_cnt <= led_cnt + 28'd1;if(led_cnt == L_TIME - 1'b1) beginled_cnt <= 25'd0;led1 <= ~led1; end endend
end
endmodule
F1--DDR3的应用总结(二)-2021.11.29相关推荐
- 史上最详细微信小程序授权登录与后端SprIngBoot交互操作说明,附源代码,有疑惑大家可以直接留言,蟹蟹 2021.11.29完善更新小程序代码,
2021.11.29 更新文章 你好,我是博主宁在春,一起学习吧!!! 写这篇文章的原因,主要是因为最近在写毕业设计,用到了小程序,这中间曲曲折折,一言难尽啊.毕业设计真的让人麻脑阔
- 2021中石油程序设计平台新生热身赛7-挨打记录2021/11/29
这期热身赛翘掉了,去看了院里的迎新晚会,得努力补啊...... 问题 A: 分组 时间限制: 1 Sec 内存限制: 128 MB 提交 状态 题目描述 一年一度的圣诞大联欢又要来临了.做为班长的小 ...
- Java学习日报—SQL基础—2021/11/29
今天效率很低,就看了以下内容... 目录 1.1关键词DISTINCT 1.2 连表查询 1.2.1 内连接 1.2.2 外连接 1.3 查询执行顺序 1.1关键词DISTINCT DISTINCT ...
- 叮~2021 CSDN年度报告已出炉;私信新增拉黑功能;创作助手支持错别字检测……【2021.12.29】
hello,大家好,这里是「CSDN产品周报」第23期.本次更新主要涉及博客.问答及私信,欢迎大家详细了解和使用. 一.博客使用体验优化 1.优化复制按钮,复制代码无压力 优化前 优化后 2.优化博客 ...
- 读论文——Pre-Training with Whole Word Masking for Chinese BERT(2021 11.25)
第一遍 标题以及作者(2021 11.25) 摘要 本文基于BERT,在RoBERTa上进行一系列改进,提出了用于中文的预训练模型MacBERT. 提出了一种新的掩码策略,MLM as correct ...
- 首页推荐流支持快捷修改兴趣标签,问答支持展示gif【2021.11.8】
hello,大家好,这里是「CSDN产品周报」第17期.本次更新主要涉及首页和问答两个产品模块,具体细节请往下看. 一.首页优化 1.「推荐」信息流新增「修改兴趣标签」按钮 从用户需求的角度考虑,对内 ...
- 2021.11.8-11.14 AI行业周刊(第71期):AI行业经验
篇章一:行业经验 不同的AI公司,对于AI产品的场景定位不同. 有的公司是面向C端产品.有的公司专门做B端用户. 当然大白所在的公司,也有具体的定位,主要面向智慧金融.智慧机场.智慧城市. 之前,一直 ...
- 第13期微生物组-宏基因组分析(线上/线下同时开课,2021.11)
福利公告:为了响应学员的学习需求,经过易生信培训团队的讨论筹备,现决定安排扩增子16S分析.宏基因组.Python课程和转录组的线上直播课.报名参加线上直播课的老师可在1年内选择参加同课程的一次线下课 ...
- 微生物组-宏基因组分析(线上/线下同时开课,2021.11)
福利公告:为了响应学员的学习需求,经过易生信培训团队的讨论筹备,现决定安排扩增子16S分析.宏基因组.Python课程和转录组的线上直播课.报名参加线上直播课的老师可在1年内选择参加同课程的一次线下课 ...
最新文章
- Java 内存查看与分析
- 离职后竟半夜偷溜回办公室写代码?一个为自由软件而战斗的程序员
- Thread concepts
- 5加载stm32 keil_KEIL 那些编辑技巧与方法
- vim+linux+ctags+taglist+winmanager+grep+cscope+supertab+visualmark--ctags
- HB-X打不开的解决办法
- 《Python Cookbook 3rd》笔记(5.15):打印不合法的文件名
- 如何dos中查看当前MySQL版本信息?
- 计算机二级mysql大题_2016年计算机二级MySQL练习题及答案
- C# Window Form解决播放amr格式音乐问题
- python词组语义相似度_语义相似度
- Leetcode刷题笔记 35.搜索插入位置(详细说明二分查找)
- nexus9刷机全记录
- 【mysql报错】Data truncation: Data too long for column ‘XXX‘ at row 1
- js实例之分解质因数
- Hotkeycontrol录制宏
- 如何解决flex:1撑开父元素问题
- codeforce_div3_round527_ABCDEF
- python--爬虫--爬虫学习路线指南
- Leek' music diary 1