基于verilog语言的SPI协议实现

2023-11-15

前言

关于SPI协议的基础知识这里就不在叙述了,感兴趣的小伙伴可以自行百度。本文基于verilog语言,实现SPI的四种通信模式,封装成通用模块。
更新时间:2023年7月11日
更新原因:之前的版本存在bug,通用性不够。

模块端口如下:

spi_comm #(
   .CPOL       (0), //时钟极性
   .CPHA       (0), //时钟相位
   .SPI_4P     (0), //1:四线制 0:三线制
   .CMD_BYTE   (3), //指令长度,单位字节
   .DATA_BYTE  (1)  //数据长度,单位字节
)your_instance_name(
   .clk     (clk     ), // input  wire [0            :0] |模块时钟
   .reset   (reset   ), // input  wire [0            :0] |模块复位

   .stert   (stert   ), // input  wire [0            :0] |开始信号
   .cmd     (cmd     ), // input  wire [CMD_BYTE*8-1 :0] |发送命令
   .valid   (valid   ), // output wire [0            :0] |读回数据有效
   .data    (data    ), // output wire [DATA_BYTE*8-1:0] |读回数据
   .done    (done    ), // output wire [0            :0] |结束标志

   .scs_n   (scs_n   ), // output wire [0            :0] |SPI|片选
   .sclk    (sclk    ), // output wire [0            :0] |SPI|时钟
   .sdio    (sdio    ), // output wire [0            :0] |SPI|三线制|数据线
   .mosi    (mosi    ), // output wire [0            :0] |SPI|四线制|主机发送
   .miso    (miso    )  // input  wire [0            :0] |SPI|四线制|主机接收
);

参数说明:

CPOL:配置模块时钟极性
CPHA:配置模块时钟相位
SPI_4P:配置模块的通信接口的引脚数量
CMD_BYTE:配置通信中指令的长度
DATA_BYTE:配置通信中数据的长度
关于CPOL和CPHA的相关说明在这里不做详细的描述,本模块在设计时采用了CPHA模糊化设计,即使CPHA配置错误也能与从机正常通信,但是CPOL必须配置正确。

功能介绍

特点:本模块是一个通用型SPI主机模块,实现SPI的四种通信模式可配置,指令长度可配置,数据长度可配置。

用户端口描述如下

stert :开始通信端口      |上升沿触发
cmd   :本次通信的CMD指令 |该数据会在stert的上升沿被模块锁存直至本次通信结束
valid :返回数据有效标志  |仅在读CMD指令时有效
data  :返回的数据        |仅在读CMD指令时有效
done  :本次通信结束标志

通信端口描述如下

scs_n :片选信号     |低电平有效
sclk  :通信时钟     |和本模块时钟之间的比例为1:8
sdio  :数据线       |当SPI_4P=0时有效,当SPI_4P=1时端口为高阻态
mosi  :主机发送端口 |当SPI_4P=1时有效,当SPI_4P=0时端口为高阻态
miso  :主机接收端口 |当SPI_4P=1时有效

CMD指令构成说明

指令长度是由读写位、地址位和数据位构成的。
CMD={R/W,ADDR,DATA}
CMD命令的最高位为读写位,CMD[CMD_BYTE*8-2 :DATA_BYTE*8]为地址位,CMD[DATA_BYTE*8-1:0]为数据位。
当CMD命令的最高位,即CMD[CMD_BYTE*8-1] = 1 时该指令为读指令,
此时CMD命令的数据位,即CMD[DATA_BYTE*8-1:0]无效,并且该CMD指令会通过valid和data端口返回一个数据。

模块源码

风格1

//
// Company: 
// Engineer: Zheng LiGuo
// Create Date: 2023/6/28
// Design Name: common_module
// Module Name: spi_comm
// Project Name: 
// Target Devices: spi_slave
// Tool Versions: vivado 2018.3
// Description: 通用SPI主机模块
//                支持配置项:
//                1.时钟极性
//                2.时钟相位
//                3.几线制
//                4.指令长度 |单位:字节
//                5.数据长度 |单位:字节
// Dependencies: CMD下发模块
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
/*===============================================
//----------- Begin Cut here for spi_comm Template ---//
//===============================================
// 通用SPI主机模块 
//===============================================
spi_comm #(
   .CPOL       (0), //时钟极性
   .CPHA       (0), //时钟相位
   .SPI_4P     (0), //1:四线制 0:三线制
   .CMD_BYTE   (3), //指令长度,单位字节
   .DATA_BYTE  (1)  //数据长度,单位字节
)your_instance_name(
   .clk     (clk     ), // input  wire [0            :0] |模块时钟
   .reset   (reset   ), // input  wire [0            :0] |模块复位

   .stert   (stert   ), // input  wire [0            :0] |开始信号
   .cmd     (cmd     ), // input  wire [CMD_BYTE*8-1 :0] |发送命令
   .valid   (valid   ), // output wire [0            :0] |读回数据有效
   .data    (data    ), // output wire [DATA_BYTE*8-1:0] |读回数据
   .done    (done    ), // output wire [0            :0] |结束标志

   .scs_n   (scs_n   ), // output wire [0            :0] |SPI|片选
   .sclk    (sclk    ), // output wire [0            :0] |SPI|时钟
   .sdio    (sdio    ), // output wire [0            :0] |SPI|三线制|数据线
   .mosi    (mosi    ), // output wire [0            :0] |SPI|四线制|主机发送
   .miso    (miso    )  // input  wire [0            :0] |SPI|四线制|主机接收
);
// INST_TAG_END ------ End spi_comm Template ---------
===============================================*/
`resetall
`timescale 1ns / 1ps
module spi_comm #(
   parameter   [0:0]    CPOL      = 0, //时钟极性
   parameter   [0:0]    CPHA      = 0, //时钟相位
   parameter   [0:0]    SPI_4P    = 0, //1:四线制 0:三线制
   parameter   [3:0]    CMD_BYTE  = 3, //指令长度,单位字节
   parameter   [3:0]    DATA_BYTE = 1  //数据长度,单位字节
)(
   input  wire                      clk   ,  // input  wire [0            :0] |模块时钟
   input  wire                      reset ,  // input  wire [0            :0] |模块复位

   input  wire                      stert ,  // input  wire [0            :0] |开始信号
   input  wire [CMD_BYTE*8-1 :0]    cmd   ,  // input  wire [CMD_BYTE*8-1 :0] |发送命令
   output wire                      valid ,  // output wire [0            :0] |读回数据有效
   output wire [DATA_BYTE*8-1:0]    data  ,  // output wire [DATA_BYTE*8-1:0] |读回数据
   output wire                      done  ,  // output wire [0            :0] |结束标志

   output wire                      scs_n ,  // output wire [0            :0] |SPI|片选
   output wire                      sclk  ,  // output wire [0            :0] |SPI|时钟
   inout  wire                      sdio  ,  // inout  wire [0            :0] |SPI|三线制|数据线
   output wire                      mosi  ,  // output wire [0            :0] |SPI|四线制|主机发送
   input  wire                      miso     // input  wire [0            :0] |SPI|四线制|主机接收
);
//=================================================
// 寄存器&网线定义
//=================================================
   reg                     resv_r;                    //接收引脚缓存器
   reg                     flag_rd   = 'd0;           //读操作标志寄存器
   reg  [2           :0]   stert_r3  = 'd0;           //开始信号缓存器
   reg  [CMD_BYTE*8-1:0]   cmd_r     = 'd0;           //CMD命令缓存器
   reg  [3:0]              NOW_S     = 'd1;           //状态机当前状态
   reg  [3:0]              NEX_S     = 'd1;           //状态机下一状态
   reg  [7:0]              time_cnt  = 'd0;           //时钟计数器
   reg  [5:0]              send_cnt  = CMD_BYTE*8-1;  //bit计数器
   reg                     flag_cnt1 = 'd0;           //bit交换完成标志寄存器
   reg  [DATA_BYTE*8-1:0]  data_r    = 'd0;           //读模式下接收数据寄存器
   wire                    stert_u;                   //开始信号上升沿标志
//=================================================
// 状态机状态定义
//=================================================
   localparam  [3:0]    S0_0 = 4'b0001;   //空闲状态
   localparam  [3:0]    S0_1 = 4'b0010;   //跳转至发送
   localparam  [3:0]    S0_2 = 4'b0100;   //发送命令
   localparam  [3:0]    S0_3 = 4'b1000;   //跳转回空闲
//=================================================
// 时钟计数器标志定义
//=================================================
   localparam  [7:0]    flag_time1 = 'd2;   //跳出跳转态时刻(跳转至发送)
   localparam  [7:0]    flag_time2 = 'd8;   //交换一个bit时间宽度
   localparam  [7:0]    flag_time3 = 'd3   //CPHA=0时接收bit时刻
   localparam  [7:0]    flag_time4 = 'd6;   //CPHA=1时接收bit时刻
   localparam  [7:0]    flag_time5 = 'd5;   //SPI时钟脉宽
//===============================================
// 同步端口信号到本地时钟
//===============================================
   always @(posedge clk) begin 
      if(SPI_4P) resv_r <= miso;
      else       resv_r <= sdio;
   end 
//===============================================
// 进程状态机
//===============================================
   always @(posedge clk) begin 
      if(reset) NOW_S <= S0_0 ;
      else      NOW_S <= NEX_S;
   end 
   always @(*) begin 
      case(NOW_S)
         S0_0    : begin if(stert_r3[2:1] == 2'b01) NEX_S = S0_1; else NEX_S = S0_0; end 
         S0_1    : begin if(time_cnt == flag_time1) NEX_S = S0_2; else NEX_S = S0_1; end 
         S0_2    : begin if(flag_cnt1             ) NEX_S = S0_3; else NEX_S = S0_2; end 
         S0_3    : begin if(time_cnt == flag_time1) NEX_S = S0_0; else NEX_S = S0_3; end 
         default : begin                            NEX_S = S0_0;                    end 
      endcase 
   end 
   always @(posedge clk) begin 
      case(NOW_S)
         S0_0    : begin 
            stert_r3  <= {stert_r3[1:0],stert}; 
            time_cnt  <= 'd0;
            send_cnt  <= CMD_BYTE*8-1;
            flag_cnt1 <= 'd0;
            data_r    <= 'd0;
            if(stert_r3[1:0] == 2'b01) cmd_r   <= cmd;
            else                       cmd_r   <= cmd_r;
            if(cmd_r[CMD_BYTE*8-1])    flag_rd <= 'd1;
            else                       flag_rd <= 'd0;
         end 
         S0_1    : begin 
            if(time_cnt == flag_time1) time_cnt <= 'd0;
            else                       time_cnt <= time_cnt+1;
         end 
         S0_2    : begin 
            if(time_cnt == flag_time2)                      time_cnt  <= 'd0;
            else                                            time_cnt  <= time_cnt+1;
            if(time_cnt == flag_time2)                      send_cnt  <= send_cnt-1;
            else                                            send_cnt  <= send_cnt;
            if(send_cnt == 'd0 && time_cnt == flag_time2-1) flag_cnt1 <= 'd1;
            else                                            flag_cnt1 <= 'd0;
            if(flag_rd && send_cnt<(DATA_BYTE*8)) begin 
               if(CPHA) begin 
                  if(time_cnt==flag_time4)   data_r[send_cnt] <= resv_r;
                  else                       data_r <= data_r;
               end else begin 
                  if(time_cnt==flag_time3)   data_r[send_cnt] <= resv_r;
                  else                       data_r <= data_r;
               end 
            end else 
               data_r <= data_r;
         end 
         S0_3    : begin 
            if(time_cnt == flag_time1)                   time_cnt <= 'd0;
            else                                         time_cnt <= time_cnt+1;
            if(NOW_S == S0_3 && time_cnt == flag_time1)  flag_rd  <= 'd0;
            else                                         flag_rd  <= flag_rd;
            if(NOW_S == S0_3 && time_cnt == flag_time1)  cmd_r    <= 'd0;
            else                                         cmd_r    <= cmd_r;
         end 
         default : begin 
            flag_rd   <= 'd0;
            time_cnt  <= 'd0;
            send_cnt  <= CMD_BYTE*8-1;
            flag_cnt1 <= 'd0;
            data_r    <= 'd0;
         end 
      endcase 
   end 

//===============================================
// 输入输出端口
//===============================================
   assign   valid = flag_rd ? ((NOW_S == S0_3) ? 1'b1 : 1'b0) : 1'b0;
   assign   data  = data_r;
   assign   done  = (NOW_S == S0_3 && time_cnt==flag_time1) ? 'd1 : 'd0;
   assign   scs_n = (NOW_S != S0_0) ? 'd0 : 'd1;
   assign   sclk  = (CPOL  == 'd0 ) ? (NOW_S == S0_2 ? ((time_cnt>=flag_time3 && time_cnt<=flag_time5) ? 'd1 : 'd0) : 'd0) :
                                      (NOW_S == S0_2 ? ((time_cnt>=flag_time3 && time_cnt<=flag_time5) ? 'd0 : 'd1) : 'd1) ;
   assign   sdio  = (SPI_4P) ? 'dz : ((NOW_S == S0_2) ? (flag_rd ? (send_cnt >= (DATA_BYTE*8) ? cmd_r[send_cnt] : 'dz) : cmd_r[send_cnt] ) : 'dz);
   assign   mosi  = (SPI_4P) ? ((NOW_S == S0_2) ? (flag_rd ? (send_cnt >= (DATA_BYTE*8) ? cmd_r[send_cnt] : 'dz) : cmd_r[send_cnt] ) : 'dz) : 'dz;

endmodule

风格2

//
// Company: 
// Engineer: Zheng LiGuo
// Create Date: 2023/6/28
// Design Name: common_module
// Module Name: spi_comm
// Project Name: 
// Target Devices: spi_slave
// Tool Versions: vivado 2018.3
// Description: 通用SPI主机模块
//                支持配置项:
//                1.时钟极性
//                2.时钟相位
//                3.几线制
//                4.指令长度 |单位:字节
//                5.数据长度 |单位:字节
// Dependencies: CMD下发模块
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
/*===============================================
//----------- Begin Cut here for spi_comm Template ---//
//===============================================
// 通用SPI主机模块 
//===============================================
spi_comm #(
   .CPOL       (0), //时钟极性
   .CPHA       (0), //时钟相位
   .SPI_4P     (0), //1:四线制 0:三线制
   .CMD_BYTE   (3), //指令长度,单位字节
   .DATA_BYTE  (1)  //数据长度,单位字节
)your_instance_name(
   .clk     (clk     ), // input  wire [0            :0] |模块时钟
   .reset   (reset   ), // input  wire [0            :0] |模块复位

   .stert   (stert   ), // input  wire [0            :0] |开始信号
   .cmd     (cmd     ), // input  wire [CMD_BYTE*8-1 :0] |发送命令
   .valid   (valid   ), // output wire [0            :0] |读回数据有效
   .data    (data    ), // output wire [DATA_BYTE*8-1:0] |读回数据
   .done    (done    ), // output wire [0            :0] |结束标志

   .scs_n   (scs_n   ), // output wire [0            :0] |SPI|片选
   .sclk    (sclk    ), // output wire [0            :0] |SPI|时钟
   .sdio    (sdio    ), // output wire [0            :0] |SPI|三线制|数据线
   .mosi    (mosi    ), // output wire [0            :0] |SPI|四线制|主机发送
   .miso    (miso    )  // input  wire [0            :0] |SPI|四线制|主机接收
);
// INST_TAG_END ------ End spi_comm Template ---------
===============================================*/
`resetall
`timescale 1ns / 1ps
module spi_comm #(
   parameter   [0:0]    CPOL      = 0, //时钟极性
   parameter   [0:0]    CPHA      = 0, //时钟相位
   parameter   [0:0]    SPI_4P    = 0, //1:四线制 0:三线制
   parameter   [3:0]    CMD_BYTE  = 3, //指令长度,单位字节
   parameter   [3:0]    DATA_BYTE = 1  //数据长度,单位字节
)(
   input  wire                      clk   ,  // input  wire [0            :0] |模块时钟
   input  wire                      reset ,  // input  wire [0            :0] |模块复位

   input  wire                      stert ,  // input  wire [0            :0] |开始信号
   input  wire [CMD_BYTE*8-1 :0]    cmd   ,  // input  wire [CMD_BYTE*8-1 :0] |发送命令
   output wire                      valid ,  // output wire [0            :0] |读回数据有效
   output wire [DATA_BYTE*8-1:0]    data  ,  // output wire [DATA_BYTE*8-1:0] |读回数据
   output wire                      done  ,  // output wire [0            :0] |结束标志

   output wire                      scs_n ,  // output wire [0            :0] |SPI|片选
   output wire                      sclk  ,  // output wire [0            :0] |SPI|时钟
   inout  wire                      sdio  ,  // inout  wire [0            :0] |SPI|三线制|数据线
   output wire                      mosi  ,  // output wire [0            :0] |SPI|四线制|主机发送
   input  wire                      miso     // input  wire [0            :0] |SPI|四线制|主机接收
);
//=================================================
// 寄存器&网线定义
//=================================================
   reg                     resv_r;                    //接收引脚缓存器
   reg                     flag_rd   = 'd0;           //读操作标志寄存器
   reg  [2           :0]   stert_r3  = 'd0;           //开始信号缓存器
   reg  [CMD_BYTE*8-1:0]   cmd_r     = 'd0;           //CMD命令缓存器
   reg  [3:0]              NOW_S     = 'd1;           //状态机当前状态
   reg  [3:0]              NEX_S     = 'd1;           //状态机下一状态
   reg  [7:0]              time_cnt  = 'd0;           //时钟计数器
   reg  [5:0]              send_cnt  = CMD_BYTE*8-1;  //bit计数器
   reg                     flag_cnt1 = 'd0;           //bit交换完成标志寄存器
   reg  [DATA_BYTE*8-1:0]  data_r    = 'd0;           //读模式下接收数据寄存器
   wire                    stert_u;                   //开始信号上升沿标志
//=================================================
// 状态机状态定义
//=================================================
   localparam  [3:0]    S0_0 = 4'b0001;   //空闲状态
   localparam  [3:0]    S0_1 = 4'b0010;   //跳转至发送
   localparam  [3:0]    S0_2 = 4'b0100;   //发送命令
   localparam  [3:0]    S0_3 = 4'b1000;   //跳转回空闲
//=================================================
// 时钟计数器标志定义
//=================================================
   localparam  [7:0]    flag_time1 = 'd2;   //跳出跳转态时刻(跳转至发送)
   localparam  [7:0]    flag_time2 = 'd8;   //交换一个bit时间宽度
   localparam  [7:0]    flag_time3 = 'd5;   //跳出跳转态时刻(跳转回空闲)
   localparam  [7:0]    flag_time4 = 'd3;   //CPHA=0时接收bit时刻
   localparam  [7:0]    flag_time5 = 'd6;   //CPHA=1时接收bit时刻
//===============================================
// 同步端口信号到本地时钟
//===============================================
   always @(posedge clk) begin 
      if(SPI_4P) resv_r <= miso;
      else       resv_r <= sdio;
   end 
//===============================================
// 获取开始信号上升沿 |缓存CMD |产生本地开始信号
//===============================================
   always @(posedge clk) stert_r3 <= {stert_r3[1:0],stert}; 
   always @(posedge clk) begin 
      if(stert_r3[1:0] == 2'b01)
         cmd_r <= cmd;
      else 
         cmd_r <= cmd_r;
   end 
   assign stert_u = (stert_r3[2:1] == 2'b01) ? 1'b1 : 1'b0;
   always @(posedge clk) begin 
      if(stert_r3[1:0] == 2'b01) begin 
         if(cmd[CMD_BYTE*8-1])
            flag_rd <= 'd1;
         else 
            flag_rd <= 'd0;
      end else if(NOW_S == S0_3 && time_cnt == flag_time3)
         flag_rd <= 'd0;
      else 
         flag_rd <= flag_rd;
   end 
//===============================================
// 进程状态机
//===============================================
   always @(posedge clk) begin 
      if(reset) NOW_S <= S0_0 ;
      else      NOW_S <= NEX_S;
   end 
   always @(*) begin 
      case(NOW_S)
         S0_0    : begin if(stert_u               ) NEX_S = S0_1; else NEX_S = S0_0; end 
         S0_1    : begin if(time_cnt == flag_time1) NEX_S = S0_2; else NEX_S = S0_1; end 
         S0_2    : begin if(flag_cnt1             ) NEX_S = S0_3; else NEX_S = S0_2; end 
         S0_3    : begin if(time_cnt == flag_time3) NEX_S = S0_0; else NEX_S = S0_3; end 
         default : begin                            NEX_S = S0_0;                    end 
      endcase 
   end 
//===============================================
// 时钟计数器
//===============================================
   always @(posedge clk) begin 
      case(NOW_S)
         S0_0    : begin                            time_cnt <= 'd0;                              end 
         S0_1    : begin if(time_cnt == flag_time1) time_cnt <= 'd0; else time_cnt <= time_cnt+1; end 
         S0_2    : begin if(time_cnt == flag_time2) time_cnt <= 'd0; else time_cnt <= time_cnt+1; end  
         S0_3    : begin if(time_cnt == flag_time3) time_cnt <= 'd0; else time_cnt <= time_cnt+1; end  
         default : begin                            time_cnt <= 'd0;                              end 
      endcase 
   end 
//===============================================
// 比特计数
//===============================================
   always @(posedge clk) begin 
      if(NOW_S == S0_2) begin 
         if(time_cnt == flag_time2)
            send_cnt <= send_cnt-1;
         else 
            send_cnt <= send_cnt;
      end else 
         send_cnt <= CMD_BYTE*8-1;
   end 
   //============================================
   // bit交换完成标志
   //============================================
   always @(posedge clk) begin 
      if(NOW_S == S0_2) begin 
         if(send_cnt == 'd0 && time_cnt == flag_time2-1)
            flag_cnt1 <= 'd1;
         else 
            flag_cnt1 <= 'd0;
      end else 
         flag_cnt1 <= 'd0;
   end 
//===============================================
// 读命令下接收bit
//===============================================
   always @(posedge clk) begin 
      if(flag_rd) begin 
         if(send_cnt<(DATA_BYTE*8)) begin 
            if(CPHA) begin 
               if(time_cnt==flag_time5)
                  data_r[send_cnt] <= resv_r;
               else 
                  data_r <= data_r;
            end else begin 
               if(time_cnt==flag_time4)
                  data_r[send_cnt] <= resv_r;
               else 
                  data_r <= data_r;
            end 
         end else 
            data_r <= data_r;
      end else 
         data_r <= 'd0;
   end 
//===============================================
// 输入输出端口
//===============================================
   assign   valid = flag_rd ? ((NOW_S == S0_3) ? 1'b1 : 1'b0) : 1'b0;
   assign   data  = data_r;
   assign   done  = (NOW_S == S0_3 && time_cnt==flag_time3) ? 'd1 : 'd0;
   assign   scs_n = (NOW_S != S0_0) ? 'd0 : 'd1;
   assign   sclk  = (CPOL  == 'd0 ) ? (NOW_S == S0_2 ? ((time_cnt>=flag_time4 && time_cnt<=flag_time3) ? 'd1 : 'd0) : 'd0) :
                                      (NOW_S == S0_2 ? ((time_cnt>=flag_time4 && time_cnt<=flag_time3) ? 'd0 : 'd1) : 'd1) ;
   assign   sdio  = (SPI_4P) ? 'dz : ((NOW_S == S0_2) ? (flag_rd ? (send_cnt >= (DATA_BYTE*8) ? cmd_r[send_cnt] : 'dz) : cmd_r[send_cnt] ) : 'dz);
   assign   mosi  = (SPI_4P) ? ((NOW_S == S0_2) ? (flag_rd ? (send_cnt >= (DATA_BYTE*8) ? cmd_r[send_cnt] : 'dz) : cmd_r[send_cnt] ) : 'dz) : 'dz;

endmodule

结束语

由于模块的通用性,这次更新删除了仿真部分
很抱歉之前的版本存在bug。也是我最近的项目需要用到SPI通信时才发现的。希望读者能给我反馈使用和阅读时发现的错误。也欢迎各位读者和我交流verilog知识。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于verilog语言的SPI协议实现 的相关文章

  • FPGA提示产生latch的报错

    在fpga的设计中有时会遇到 latch 的报错 1 latch是什么 Latch 就是锁存器 是一种在异步电路系统中 对输入信号电平敏感的单元 用来存储信息 锁存器在数据锁存使能时 数据被锁存 输入信号不起作用 这违背了组合逻辑中输出随输
  • 常用小工具使用记录整理

    简单记录方便后续使用 1 截图软件 FSCapture exe FSCapture最新版是款适合电脑屏幕中使用的抓屏工具 FSCapture官方版集成了图像捕捉 图像浏览以及图像编辑等功能为一体 帮助用户对截取的图形进行处理操作 并且FSC
  • Vim中多行删除

    在操作虚拟机的时候 都会出错 当在vim中出现问题的时候 可以在dw普通模式下删除对应的单词 如果在vim中使用多行删除 可以使用dd vim 命令 将行数添加到该命令中 如10dd将从光标底部删除10行 包含光标行在内 删除单行 1 按
  • Markdown基础语法介绍

    何为Markdown Markdown是一种轻量级标记语言 它允许用户以纯文本格式编写文档 然后转换成有效的XHTML或HTML文档 Markdown具备轻量化 跨平台 易读易写等特性 且支持文本 图片 图表等多种展示样式 Markdown
  • 编码GBK不可映射字符的三种解决方法

    当我们需要输出中文时 在DOS等运行和调试代码时会出现 study01 java 3 错误 编码GBK的不可映射字符 System out println 浠婂 鐨勬棩鏈熸槸锛 day 锛 或者中文编码错误 原因 Windows CMD和P
  • 【Xilinx Vivado时序分析/约束系列4】FPGA开发时序分析/约束-实验工程上手实操

    目录 建立工程 添加顶层 模块1 模块2 添加约束文件 编辑时钟约束 打开布线设计 代码代表的含义 时序报告 进行时序分析 Summary 包含了汇总的信息量 Source Clock Path 这部分是表示Tclk1的延时细节 Data
  • FPG—VGA显示器字符显示(附代码)

    目录 1 实操 1 1 字符取模 1 2 顶层模块 1 3 图像数据生成模块 1 3 1 模块框图 1 3 2 波形图绘制 1 3 3 代码编写 1 3 4 仿真验证 2 总结 本例程大部分与VGA显示驱动内容相同 只是显示部分改变了 故此
  • [从零开始学习FPGA编程-28]:进阶篇 - 基本组合电路-奇偶校验生成器(Verilog语言版本)

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 目录 第1章 奇偶校验生成器 1 1 什么是奇校验 1 2 Verilog语言描述
  • quill编辑器使用

    官方git https github com quilljs quill 官方文档 https quilljs com 中文文档 https kang bing kui gitbook io quill 编辑器是个正经编辑器 就是文档太不正
  • CSDN创作说明

    这里写自定义目录标题 欢迎使用Markdown编辑器 新的改变 功能快捷键 合理的创建标题 有助于目录的生成 如何改变文本的样式 插入链接与图片 如何插入一段漂亮的代码片 生成一个适合你的列表 创建一个表格 设定内容居中 居左 居右 Sma
  • Toad常用快捷键和缩写替换

    Toad常用快捷键 F8 调出以前执行的sql命令 F9 执行全部sql Ctrl T 补全table name 或者显示字段 alt 箭头上下 看sql history Ctrl Enter 直接执行当前选中的sql Ctrl Shift
  • VSCode中配置命令行参数

    VSCode中配置命令行参数 在跑程序调试的时候 可以直接使用脚本运行程序 这个时候调试代码只能用pdb 我觉得不太习惯 而且感觉不是很好 所以想这能不能将运行程序的脚本中的命令直接配置到vscode上 就有了这篇记录 正常vscode D
  • vscode配置clangd和clang-format

    vscode安装和配置 如何安装和配置vscode以搭建c 开发环境 可以查看我的另一篇博客 Windows上最轻量的vscode C 开发环境搭建 在这篇博客中 详细介绍了如何安装vscode以及应该安装哪些插件 这里不再赘述 vscod
  • 【FMC141】基于VITA57.4标准的4通道2.8GSPS 16位DA播放子卡(2片DAC39J84)

    FMC141是一款基于VITA57 4标准的4通道2 8GSPS 2 5GSPS 1 6GSPS采样率16位DA播放FMC子卡 该板卡为FMC 标准 符合VITA57 4与VITA57 1规范 16通道的JESD204B接口通过FMC 连接
  • vim常见操作

    vim常见操作 文章目录 vim常见操作 1 回退 前进 2 搜索 3 删除 4 定位到50行 5 显示行号 6 复制粘贴 7 剪贴
  • vscode 内置(自带)功能使用

    vscode 搜索 功能 使用正则表达式 参考文章 Justice23 参考文章 熟悉的新风景 转义字符 匹配内容 t tab r 回车符号 r n 换行符号 n 特殊符号转义 如
  • 基于FPGA的简易BPSK和QPSK

    1 框图 2 顶层 3 m generator M序列的生成 输出速率为500Kbps 4 S2P是串并转换模块 将1bit的m序列转换到50M时钟下的2bit M序列数据 就有4个象限 5 my pll是生成256M的时钟作为载波 因为s
  • Vivado ILA的debug信息保存与读取

    保存 write hw ila data D Project FPGA ILA Debug Data 202401041115 ila upload hw ila data hw ila 1 读取 display hw ila data r
  • TRICONEX MA2211-100 芯片上相互连接

    TRICONEX MA2211 100 芯片上相互连接 TRICONEX MA2211 100 所有相同的组件 io的电源 处理器 和内存将需要 但是 你可以看到所有这些带存储器和处理器的OO板 针不能嵌入到一个小的单片机上 现在是 普拉克
  • DSCA190V 57310001-PK

    DSCA190V 57310001 PK DSCA190V 57310001 PK 具有两个可编程继电器功能 并安装在坚固的 XP 外壳中 DSCA190V 57310001 PK 即可使用 只需最少的最终用户校准 DSCA190V 573

随机推荐

  • webpack output.library的16 种取值方法示例

    前置准备 在项目开发中使用 webpack 打包前端代码 对 output library 配置项总是不求甚解 只知道将代码打包成 npm 库的时候要配置它 这段时间又要开发组件库 借助这次机会对 output library 求甚解 配置
  • gimp中文版教程_GIMP中详细教程.pdf

    GIMP中详细教程 GIMP 实用系列教程 1文件的打开和存储 概述 打开GIMP软件其初始界面如下 左边是工具 工具箱中每选择一种工具后 通常在其下部会出 现一个与其相配的选项栏一起使用的 因此每选好一种工具 首先要 把选项栏中的有关选项
  • 蓝桥杯python青少年_让孩子参加蓝桥杯大赛好吗

    让孩子参加蓝桥杯大赛好吗 1 小学升初中备简历 该赛能帮孩子锦上添花 近年来 小学升初中的竞争越来越激烈 政策也年年在改变 许多地区的小学升初中甚至开始采取摇号和面试选拔学生 但不管政策怎么变 这其中的竞争力只会越来越大 优质生源决定学校核
  • 前端购物车,创建订单和支付流程

    前端购物车流程 用户在页面上将商品添加到购物车中 用户可以通过购物车页面查看添加的商品列表及其数量 并对其进行修改和删除 用户确认购物车中的商品无误后 点击 结算 按钮 用户填写收货地址 付款方式等相关信息 确认订单信息 系统生成订单并显示
  • flutter_blue + MethodChannel.invokeMethod + java.lang.NullPointerException

    友盟崩溃日志报了这样一个问题 说是扫描蓝牙设备回调时 MethodChannel 为空 java lang NullPointerException Attempt to invoke virtual method void io flut
  • Logrotate日志切分

    logrotate 程序是一个日志文件管理工具 用来把旧的日志文件更名或删除 并创建新的日志文件 我们把它叫做 转储 是个使日志轮替的程序 有了它就不用看着自己的日志体积一天天的变大 而可以根据你自己的需求来设定日志转储 这个工具对于像ng
  • discuz设置伪静态

    discuz设置伪静态 环境为 centos Apache mysql php 操作后台 点击提交 点击右上角的查看规则 复制一段到新建文件 htaccess中 注 WIN主机就另存为httpd ini Linux主机就另存为 htacce
  • python遍历文件夹下的所有子文件夹,并将指定的文件复制到指定目录

    python遍历文件夹下的所有子文件夹 并将指定的文件复制到指定目录 需求 复制单个文件夹 遍历所有子文件夹中的文件 并复制 代码封装 需求 在1文件夹中有1 2两个文件夹 将这两个文件夹中的文件复制到 after copy中 复制单个文件
  • Deathnote

    Deathnote 1 主机发现 arp scan l 2 扫描端口 nmap Pn sV P A 192 168 80 132 开放了80 22端口 3 访问80端口 修改host文件访问80端口时进行了跳转到deathnote vuln
  • Allegro 17.4设置中文界面

    一 Allegro 17 4 中文界面效果 二 Allegro 17 4 中文界面设置方法 2 1 需要打上此时 20210820 最新的S019的升级补丁 2 2 设置环境变量 变量名 intl enabled 变量值 1 要去除中文显示
  • LeetCode刷题-1

    数组 1 两数之和 题目描述 题目样例 Java方法 暴力枚举 思路及算法 代码 执行结果 复杂度 Java方法 哈希表 思路及算法 代码 执行结果 复杂度 题目描述 给定一个整数数组 nums 和一个整数目标值 target 请你在该数组
  • StarCraft开发:用肮脏的技巧解决难题

    http www csdn net article 2013 02 28 2814299 the starcraft path finding hack 摘要 在之前的文章中 Warcraft之父讲述了自己是如何以及为何重启StarCraf
  • Linux中的fork()函数

    Linux中的fork 函数 在Linux中 fork 函数是创建进程的基础 它是一个系统调用 用于创建一个新的进程作为当前进程的副本 新进程将拥有与原进程相同的代码 数据和堆栈 但是拥有不同的进程ID PID 并且它是原进程的子进程 函数
  • 【debug】(0, slice(None, None, None))‘ is an invalid key

    简单介绍 我获取了一个dataframe里的符合条件的多个index 想通过index对dataframe进行筛选 在筛选的时候反馈错误 原始代码为 input index df select df select item input in
  • 【word】如何设置交叉引用标注参考文献

    文章目录 1 定义参考文献编号格式 2 设置交叉引用 插入正文位置 3 修改连续多个参考文献的格式 4 更新正文标注 1 定义参考文献编号格式 开始 gt 编号 gt 定义新编号格式 2 设置交叉引用 插入正文位置 设置好固定的参考文献格式
  • 【vscode,python】pip成功的包却不能导入(import)问题

    第一次遇到这个问题 在网上找了些资料 网上的教程大致上都是需要去修改settings json这个文件 我问了我朋友 然后轻松地解决了这个问题 方法一 关掉编译软件重新打开即可解决问题 方法二 我认为造成这个问题的原因是在另一个新的路径上新
  • 真实GPS转腾讯/高德地图坐标系,百度地图与腾讯/高德地图坐标系转换

    1 获取真实坐标GPS wgs84转为gcj编码方式 positiontransform array manual 定义常量 var GPS PI 3 14159265358979324 x pi 3 14159265358979324 3
  • 对称矩阵的压缩存储、基于压缩矩阵的矩阵乘法

    def disp A 输出方阵A n len A for i in range n for j in range n print d A i j end print def compression A a 压缩矩阵A到a中 A是一个对称矩阵
  • 面试总结(五):搜索引擎

    问题导读 1 搜索引擎有哪些特点 优势 2 搜索引擎使用到哪些场景中 3 如何将原文档传给分次组件 4 如何将得到的词 Term 传给索引组件 Indexer 搜索引擎概述全文搜索就是对文本数据的一种搜索方式 文本数据的都多 可以分为顺序搜
  • 基于verilog语言的SPI协议实现

    前言 关于SPI协议的基础知识这里就不在叙述了 感兴趣的小伙伴可以自行百度 本文基于verilog语言 实现SPI的四种通信模式 封装成通用模块 更新时间 2023年7月11日 更新原因 之前的版本存在bug 通用性不够 模块端口如下 sp