ASIC-WORLD Verilog(1)一日Verilog

写在前面

        在自己准备写一些简单的verilog教程之前,参考了许多资料----asic-world网站的这套verilog教程即是其一。这套教程写得极好,奈何没有中文,在下只好斗胆翻译过来(加了自己的理解)分享给大家。

        这是网站原文:Verilog Tutorial

介绍

        Verilog 是一种硬件描述语言 (HARDWARE DESCRIPTION LANGUAGE ,HDL)。硬件描述语言是一种用于描述数字系统(例如网络交换机、微处理器或存储器或简单的触发器)的语言。这意味着你可以通过使用 HDL来描述任何级别的任何(数字)硬件。

//D触发器
module d_ff ( d, clk, q, q_bar);

input d ,clk;
output q, q_bar;
wire d ,clk;
reg q, q_bar;
       
always @(posedge clk) begin
  q <= d;
  q_bar <= ! d;
end

endmodule

        通过硬件描述语言,你可以描述一个如上图所示的简单D触发器,也可以描述一个超过100 万个逻辑门的复杂设计。Verilog 是业界可用于硬件设计的 HDL 语言之一。它允许我们在行为级(Behavior Level)、寄存器传输级 (Register Transfer Level,RTL)、门级(Gate level)和开关级(switch level)进行数字设计。Verilog 允许硬件设计人员使用行为结构来表达他们的设计,将实现细节推迟到最终设计的后期阶段。

        很多想学这门语言的工程师,经常会问这样一个问题:"学Verilog需要多少时间?" 对此我的答案是“如果你碰巧知道至少一种编程语言的话(比如C、Java等),那可能只需要一周的时间。”

设计风格

        Verilog 与任何其他硬件描述语言一样,允许采用自下而上(Bottom-up)或自上而下(Top-down)的方法进行设计。

自下而上的设计

        传统的电子设计方法是自下而上的,每个设计都是使用标准门电路在门级实现的。随着新设计变得越来越复杂,这种方法几乎无法维护。新系统由 ASIC 或微处理器组成,复杂性达到了数千个晶体管级别。这种传统的自下而上的方法必须让位于新的结构化、层次化的设计方法。没有这些新方法,就无法解决新设计的复杂性。

自上而下的设计

        所有设计师都期望的设计风格是自上而下的。真正的自上向下设计允许早期测试、不同技术的轻松更改、结构化系统设计并能提供许多其他优势。但是要实现纯粹的自上而下的设计是非常困难的,基于这个事实,大多数设计都是这两种方法(自下而上和自上而下)的混合,以结合两种方法的优点。

        下图展示了自上而下的设计方法。

Verilog的抽象层级

        Verilog 支持在不同的抽象层级上进行设计。其中三个非常重要:

  • 行为级(Behavioral level)
  • 寄存器转换级(Register-Transfer Level)
  • 门级(Gate Level)

行为级

        通过并行算法(行为)来描述系统。每个算法本身都是有顺序的,这意味着它由一组依次执行的指令组成。函数(Functions)、任务(Tasks)和 Always 块(Always blocks)是主要元素。行为级不考虑设计的结构实现。

寄存器转换级(RTL)

        使用寄存器传输级别的设计通过操作和寄存器之间的数据传输来指定电路的特性。这需要使用显式的时钟信号。RTL 设计包含精确的时序边界:操作被安排在特定的时间发生。现代 RTL 代码定义是“任何可综合的代码都称为 RTL 代码”。

门级

        在逻辑层内,系统的特性由逻辑链路及其时序属性描述。所有的信号都是离散信号,它们只能是明确的逻辑值('0'、'1'、'X'、'Z')。可用的操作是预定义的逻辑原语(AND、OR、NOT 等门)。对于任何级别的逻辑设计来说,使用门级建模可能都不是一个好主意。门级代码由综合工具等工具生成,此网表一般用于门级仿真和后端。

再介绍

        每一个初学者的梦想都是能在一天之内掌握Verilog,至少也要能使用它。为了帮助初学者实现这个梦想,我接下来将讲解一些理论、示例和练习。

        本教程不会教您如何编程(软件编程),因为它是为那些有一定编程(软件编程)经验的人设计的。Verilog 并发执行不同的代码块----尽管这与大多数软件编程语言的顺序执行所相反,但二者之间仍有许多相似之处。

        此外,一些数字电路的设计背景也对学习Verilog很有帮助。

        Verilog 出现之前的设计主要依赖原理图。每个设计,无论复杂程度如何,都是通过原理图设计的。它们难以验证且容易出错,这就很容易形成设计、验证、设计、验证……的漫长且乏味的开发迭代过程。

        当 Verilog 出现后,我们突然有了一种新的思考方式来认识逻辑电路。Verilog 设计周期更像是一个传统的编程周期,本教程将引导您完成它。

        使用Verilog进行设计的流程是这样的:

  • 规格 (Specifications,specs)
  • 高层级设计(High level design)
  • 低层级设计(Low level (micro) design)
  • RTL编码(RTL coding)
  • 验证(Verification)
  • 综合(Synthesis)

        列表中的第一个是规格----我们将对设计施加何种限制和要求?我们要构建什么?

        在本教程中,我们将构建一个2路仲裁器(2 agent arbiter):一种在2个源之间进行选择以争夺控制权(mastership)的设备。以下是我们可能会编写的一些规格。

  • 2路仲裁器
  • 高电平有效的异步复位
  • 源 0 优先于源1的固定优先级
  • 只要请求被断言,授权就会被断言(意思就是只要输入有效,输出就有效)

        一旦我们有了规格,就可以绘制框图了,它基本上算是系统内数据流的一种抽象(什么进入黑盒子?或什么从黑盒子出来?)。我们举的例子很简单,对应的框图如下所示。现在我们还不用担心神奇的黑盒子里有什么。

仲裁器框图

        如果现在我们不用Verilog来设计这个仲裁器,标准程序将要求我们绘制一个状态机,然后我们将为每个触发器制作一个包含状态转换的真值表,跟着我们会绘制卡诺图,根据卡诺图我们可以得到优化后的电路。此方法适用于小型设计,但对于大型设计,此流程将变得复杂且容易出错。这就是 Verilog 的用武之地,它向我们展示了另一种方式。

低层级设计

        要了解 Verilog 是如何帮助我们设计仲裁器的话,让我们继续聚焦在状态机----现在我们进入低级设计并剥开上一个框图中黑盒子的封面,来看看输入是如何影响仲裁器的。

        圆圈代表仲裁器可能处于的状态,每个状态都对应一个输出。状态之间的箭头是状态转换,由导致转换的事件标记。例如,最左边的橙色箭头表示如果仲裁器处于状态 GNT0(输出对应于 GNT0 的信号)并接收到输入 !req_0时,就会移动到状态 IDLE 并输出对应于该状态的信号。这个状态机描述了你所需要的系统的所有逻辑状态。下一步是将其全部放入 Verilog 中。

模块(Modules)

        我们需要回溯一下才能做到这一点。如果你观察第一张图片中的仲裁器,就会发现它有一个名称(“仲裁器”)和输入/输出端口(req_0、req_1、gnt_0 和 gnt_1)。

        由于Verilog是一种HDL(硬件描述语言,一种用于集成电路概念设计的语言),它也需要具备这些东西(名称和输入/输出端口)。在 Verilog 中,我们把“黑盒子”称为模块(Modules)。这是Verilog中的保留字,用于指代具有输入、输出和内部逻辑的事物。它们是其他编程语言中具有返回值的函数(Functions)的类似概念。

“仲裁器”模块的代码

        如果你仔细观察仲裁块,就会看到有许多的箭头标记(进入模块的是输入,从模块出去的则是输出)。在Verilog中,我们声明了模块名和端口名之后,就可以定义每个端口的方向了。其RTL代码如下所示。

module arbiter (
clock      , // clock
reset      , // Active high, syn reset
req_0      , // Request 0
req_1      , // Request 1
gnt_0      , // Grant 0
gnt_1        // Grant 1
);

//-------------Input Ports-----------------------------
input           clock               ;
input           reset               ;
input           req_0               ;
input           req_1               ;

//-------------Output Ports----------------------------
output        gnt_0                 ;
output        gnt_1                 ;

双向端口示例

        上面我们只使用了两种类型的端口,输入input和输出output,此外,还有一种双向端口也可以使用----inout。

inout read_enable;     // 名为 read_enable 的端口是双向的

向量(vector )信号示例

        应该如何定义向量信号(由多于一位的信号组成的序列)呢?Verilog 提供了一种简单的方法。

inout [7:0] address;    //端口“address”是双向的

        请注意 [7:0] 意味着我们使用的是little-endian(低字节序)约定----从最右边的 0 位开始依次向左递增。

        如果我们使用的是 [0:7],意味着我们使用的是big-endian(高字节序)约定----从最左边的 0 位开始依次向右递增。

        Endianness (字节序)是一种决定数据“读取”方式的排序方式,不同的系统之间确实存在差异,因此始终使用正确的 endianness 很重要。作为类比,想想一些从左到右(高字节序)书写的语言(英语)与从右到左(低字节序)书写的其他语言(阿拉伯语)。了解语言的书写方向对于能够阅读它至关重要,但方向本身是在几年前任意设置的。

概括

  • 我们了解了如何在 Verilog 中定义块/模块(block/module)
  • 我们学习了如何定义端口和端口方向(ports and port directions)
  • 我们学习了如何声明向量/标量端口(vector/scalar)

数据类型

        数据类型与硬件有什么关系?实际上,没什么关系。人们只是想再写一种包含数据类型的语言。但是等等……硬件确实有两种驱动(Drivers)。驱动?那是什么?

        驱动是一种可以驱动负载的数据类型。在物理电路中,驱动器基本上可以是电子可以穿过/进入的任何东西。

  • 可以存储数值的驱动(例如:触发器(flip-flop))
  • 不能存储值,但能连接两点的驱动(例如:线(wire))。

        第一种类型的驱动在 Verilog 中称为 reg(“register”的缩写)。第二种数据类型称为线(wire)。此外还有很多其他的数据类型,例如,寄存器可以是有符号的、无符号的、浮点数……作为新手,你现在暂时不要管这些。

示例:

wire and_gate_output; // "and_gate_output" 是只输出的线
reg d_flip_flop_output;// "d_flip_flop_output" 是一个寄存器;它存储并输出数值
reg [7:0] address_bus;// "address_bus" 是一个低字节序的 8 位寄存器

概括

  • Wire 数据类型用于连接两点
  • Reg 数据类型用于存储数值

运算符

        值得庆幸的是,verilog中的运算符与其他编程语言中的相同。他们取两个值并比较(或其他的运算方式)它们以产生第三个结果----常见的例子是加法、等于、逻辑与……为了让我们的生活更轻松,几乎所有的运算符(至少下面列表中的那些)与它们在 C 语言中的对应部分完全相同。

类型

符号

功能

算术运算符

*

乘法

/

除法

+

加法

-

减法

%

取余

+

一元加法(Unary plus)

-

一元减法(Unary minus)

逻辑运算符

!

逻辑非

&&

逻辑与

||

逻辑或

关系运算符

>

大于

<

小于

>=

大于等于

<=

小于等于

相等运算符

==

等于

!=

不等于

归约操作符

~

按位取反

~&

与非

|

~|

活飞

^

异或

^~

同或

~^

同或

移位运算符

>>

向右移位

<<

向左移位

拼接运算符

{ }

拼接

条件运算符

?

条件

示例

a = b + c ;     // 这很容易
a = 1 << 5;     // 嗯,让我想想,好吧,将 '1' 左移 5 个位置。
a = !b ;        // 它会反转 b 吗???
a = ~b ;        // 你还想给'a'赋值多少次?这可能会导致多驱动(multiple-drivers)问题。


控制语句

        等等,这是什么?if, else, repeat, while, for, case----Verilog 看起来和 C 语言一模一样(或者其他你会使用的编程语言)!尽管功能上verilog看起来与 C语言相同,但 Verilog 是一种 HDL,因此描述应被转化为硬件。这意味着您在使用控制语句时必须小心(否则您的设计可能无法在硬件中实现)。

If-else语句

If-else 语句通过检查条件来决定执行哪部分代码。如果满足条件,则执行该条件对应的代码。否则,它会运行代码的其他部分。

if (enable == 1'b1) begin
  data = 10;             //10进制赋值
  address = 16'hDEAD;     //16进制赋值
  wr_enable = 1'b1;     // 2进制赋值
end 
else begin
  data = 32'b0;
  wr_enable = 1'b0;
  address = address + 1;  
end

        你可以在条件检查中使用任何运算符,就像 C 语言的用法一样。如果需要,我们也可以嵌套 if-else 语句。没有 else 的语句也是合法的,但是它们可能会有其他问题----在实现组合逻辑时容易产生锁存器Latch。

Case语句

        当我们有一个变量需要检查多个值时,可以使用 Case 语句。就像地址解码器一样,输入是一个地址,且需要检查它的所有可能值。我们没有使用多个嵌套的 if-else 语句(一个对应于我们要查找的单个值),而是使用单个 case 语句----这类似于 C/C++ 等语言中的 Switch 语句。

        Case 语句以case开头,以endcase结束。在这两个分隔符之间列出你希望执行的所有语句(后跟冒号:)。

        写default语句是一个好主意,就像有限状态机 (FSM) 一样,如果进入了非定义状态,状态机就被挂起(“死机”)。带有返回功能的default语句可以保证我们的安全。

case(address)
  0 : $display ("It is 11:40PM");
  1 : $display ("I am feeling sleepy");
  2 : $display ("Let me skip this tutorial");
  default : $display  ("Need to complete");
endcase

注意: if-else 和 case 语句有一个共同点----如果您没有涵盖到所有可能的情况(If-else 中没有“else”或 Case 中没有“default”),并且你正在写一个组合逻辑语句的话,那么综合工具就会推断出锁存器Latch。

While语句

        如果它检查的条件为真,那么 while 语句就会重复执行其中的代码。While循环通常不用于现实电路中的模型,一般都用于测试脚本testbench。与其他语句块一样,它们由begin和end分隔。

while (free_time) begin
  $display ("Continue with webpage development");
end

        只要 free_time 变量为真,就会重复执行 begin 和 end 内的代码----即打印“Continue with webpage development”。

        让我们来看一个更奇怪的例子,它使用了大部分的 Verilog 结构。

module counter (clk,rst,enable,count);
input clk, rst, enable;
output [3:0] count;
reg [3:0] count;
                      
always @ (posedge clk or posedge rst)
    if (rst) begin
      count <= 0;
    end 
    else begin : COUNT
      while (enable) begin
        count <= count + 1;
        disable COUNT;
      end
end

endmodule

        您会注意到一个名为 always 的新块----这说明了 Verilog 的一个关键特性。正如我们之前提到的,大多数软件语言都是按顺序执行的。相反,Verilog 程序通常有许多并行执行的语句。当满足其中列出的一个或多个条件时,所有标记为always 的块都将同时运行。

        在上面的示例中,always 块将在 rst 或 clk 达到上升沿时运行----当它们的值从 0 上升到 1 时。您可以在程序中同时运行两个或多个always块(此处未显示,但常用)。

        我们可以通过无效化保留字的方式来无效化代码块。在上面的示例中,每次计数器递增后,COUNT 代码块(此处未显示)都会被无效化。

For语句

        Verilog 中的 for 循环几乎与 C/C++ 中的 for 循环完全相同。唯一的区别是 Verilog 不支持 ++ 和 -- 运算符,所以和在 C 中那样编写 i++ 不同,你需要写出完整的 i = i + 1。

for (i = 0; i < 16; i = i +1) begin
      $display ("Current value of i is %d", i);
end

        此代码将按顺序打印从 0 到 15 的数字。将 for 循环用于RTL时要小心,需要确保你的代码实际上可以在硬件中正常实现……并且循环不是无限的。

Repeat语句

        repeat 语句类似于我们刚刚介绍的 for 循环。与我们声明 for 循环时显式地指定一个变量并递增它不同,repeat语句是告诉程序应该运行代码多少次,且没有变量递增(除非我们希望它们如此,就像在这个例子中)。

repeat (16) begin
    $display ("Current value of i is %d", i);
    i = i + 1;
end

        输出与前面的 for 循环程序示例完全相同。在实际硬件实现中我们一般很少使用repeat语句(或 for 循环)。

概括

  • while、if-else、case(switch)语句和C语言中的一样
  • If-else 和 case 语句要求涵盖组合逻辑的所有情况
  • For 循环与 C 中的相同,但没有 ++ 和 -- 运算符
  • Repeat 与 for 循环相同,但没有递增变量

变量赋值

        在数字电路中有两种类型的电路,组合逻辑电路和时序逻辑电路。我们当然知道这一点,但问题是“我们应该如何在 Verilog 中对此建模?”。Verilog 提供了两种对组合逻辑进行建模的方法和一种对时序逻辑进行建模的方法。

  • 可以使用 assign 和 always 语句对组合逻辑电路建模
  • 只能使用 always 语句对时序逻辑电路建模
  • 还有第三个块,仅在testbench中(实际上也可以在RTL中进行初始化,但不常见)使用:称为Initial语句。

Initial块

        顾名思义,Initial块(出师快)仅在仿真开始时执行一次。这在编写testbench时很有用。如果我们有多个Initial块,那么它们都会在仿真开始时执行。

示例

initial begin
    clk = 0;
    reset = 0;
    req_0 = 0;
    req_1 = 0;
end

        在上面的示例中,在仿真开始时(即当仿真时间为0 时),begin-end内的所有变量都会被赋值为零。


Always块

        顾名思义,always 块总是在执行,这与仅执行一次(在仿真开始时)的Initial块不同。第二个区别是 always 块应该有一个敏感列表或与之关联的延迟。

        敏感列表告诉 always 块何时执行代码块,如下图所示。保留字alway后的@符号表示代码块将在符号@后括号中的条件“触发”。

        关于 always 块的一个重要说明:它不能驱动 wire 数据类型,但可以驱动 reg 和 integer 数据类型。

always  @ (a or b or sel)begin
  y = 0;
  if (sel == 0) begin
    y = a;
  end 
  else begin
    y = b;
  end
end

        上面的例子是一个 2选1的多路选择器, a 和 b是输入,sel 是选择,y 是输出。

        在任何组合逻辑电路中,只要输入发生变化,输出就会立即发生变化。当应用于 always 块时,该理论意味着只要输入变量(或输出控制变量)发生变化,就需要执行 always 块中的代码。这些变量是包含在敏感列表中的变量,即 a、b 和 sel。

        有两种类型的敏感列表:电平敏感(用于组合电路)和边沿敏感(用于触发器)。下面的代码是相同的 2:1 Mux,但输出 y 现在是触发器输出。

always  @ (posedge clk )begin
    if (reset == 0) begin
      y <= 0;
    end 
    else if (sel == 0) begin
      y <= a;
    end 
    else begin
      y <= b;
    end
end    

        通常情况下我们不得不复位触发器,因此每次时钟从 0 转换到 1 (posedge) 时,都要检查复位是否有效(同步复位),然后继续执行正常逻辑。

        如果我们仔细观察,就会发现在组合逻辑的情况下,我们使用了“=”进行赋值;而对于时序逻辑,我们则使用了“<=”运算符。“=”是阻塞赋值,“<=”是非阻塞赋值。“=”在begin-end内顺序执行代码,而非阻塞“<=”则并行执行代码。

        我们可以写一个没有敏感列表的 always 块,在这种情况下需要有一个延迟,如下面的代码所示。

always  begin
    #5  clk = ~clk;
end

        语句前面的 #5 将其延迟 5 个时间单位。

Assign块

        assign 语句仅用于建模组合逻辑,并且会连续执行。所以赋值语句被称为“连续赋值语句(continuous assignment statement')”,因为其没有敏感列表。

  assign out = (enable) ? data : 1'bz;

        上面的例子是一个三态buffer。当使能为 1 时,数据被驱动到 out,否则 out 被拉到高阻抗。我们可以使用嵌套的条件运算符来构造多路选择器、解码器和编码器。

  assign out = data;

        这个例子是一个简单的buffer。

任务和函数

        当一次又一次重复相同的旧事物时,Verilog 与任何其他编程语言一样,提供了解决重复使用代码的方法----任务和函数。

        下面的代码可用于计算奇偶校验。

function parity;
    input [31:0] data;
    integer i;
    begin
      parity = 0;
      for (i= 0; i < 32; i = i + 1) begin
        parity = parity ^ data[i];
      end
    end
endfunction

        函数和任务具有相同的语法,一个区别是任务可以有时间延迟,但函数不能。这意味着函数可用于建模组合逻辑。第二个区别是函数可以返回一个值,而任务不能。


Testbench(测试脚本)

        好的,我们已经根据设计文档编写了代码,接着呢?

        我们需要对其进行测试,看看它是否符合规格。大多数时候,这与我们在大学时代在数字实验室中所做的相同----驱动输入,将输出与预期值相匹配。

        这是仲裁器的RTL代码:

module arbiter (
clock, 
reset, 
req_0,
req_1, 
gnt_0,
gnt_1
);

input clock, reset, req_0, req_1;
output gnt_0, gnt_1;

reg gnt_0, gnt_1;

always @ (posedge clock or posedge reset)
if (reset) begin
  gnt_0 <= 0;
  gnt_1 <= 0;
end else if (req_0) begin
  gnt_0 <= 1;
  gnt_1 <= 0;
end else if (req_1) begin
  gnt_0 <= 0;
  gnt_1 <= 1;
end

endmodule

        这是仲裁器的Testbench:

module arbiter_tb;

reg clock, reset, req0,req1;
wire gnt0,gnt1;

initial begin
  $monitor ("req0=%b,req1=%b,gnt0=%b,gnt1=%b", req0,req1,gnt0,gnt1);
  clock = 0;
  reset = 0;
  req0 = 0;
  req1 = 0;
   #5  reset = 1;
   #15  reset = 0;
   #10  req0 = 1;
   #10  req0 = 0;
   #10  req1 = 1;
   #10  req1 = 0;
   #10  {req0,req1} = 2'b11;
   #10  {req0,req1} = 2'b00;
   #10  $finish;
end

always begin
  #5  clock =  ! clock;
end

arbiter U0 (
.clock (clock),
.reset (reset),
.req_0 (req0),
.req_1 (req1),
.gnt_0 (gnt0),
.gnt_1 (gnt1)
);

endmodule

        看起来我们已经将所有仲裁器的输入声明为 reg,将输出声明为 wire;我们这样做是因为测试平台需要驱动输入并需要监控输出。

        在声明了所有需要的变量之后,我们将所有输入初始化为已知状态----这是在initial块中实现的。初始化后,我们按照要测试仲裁器的顺序断言/取消断言复位、req0、req1。时钟是用 always 块生成的。完成测试后,我们需要停止仿真----使用了 $finish 来终止仿真。$monitor 则用于监空信号列表的变化,并以我们想要的格式打印出来。

        这是仿真运行后的结果:

req0=0,req1=0,gnt0=x,gnt1=x
req0=0,req1=0,gnt0=0,gnt1=0
req0=1,req1=0,gnt0=0,gnt1=0
req0=1,req1=0,gnt0=1,gnt1=0
req0=0,req1=0,gnt0=1,gnt1=0
req0=0,req1=1,gnt0=1,gnt1=0
req0=0,req1=1,gnt0=0,gnt1=1
req0=0,req1=0,gnt0=0,gnt1=1
req0=1,req1=1,gnt0=0,gnt1=1
req0=1,req1=1,gnt0=1,gnt1=0
req0=0,req1=0,gnt0=1,gnt1=0

  • 📣您有任何问题,都可以在评论区和我交流📃!
  • 📣本文由 孤独的单刀 原创,首发于CSDN平台🐵,博客主页:wuzhikai.blog.csdn.net
  • 📣您的支持是我持续创作的最大动力!如果本文对您有帮助,还请多多点赞👍、评论💬和收藏⭐!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/7235.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Helm学习笔记

文章目录概念定义helm组件helm的工作流程helm安装helm仓库helm部署应用helm应用的更新或回退或卸载概念 定义 学习helm首先得了解helm是什么&#xff0c;我们先来看一下helm的定义&#xff1a;helm是将kubernetes的各种资源对象打包&#xff0c;类似于Linux中的yum工具&#…

【HTML系列】第六章 · 框架标签、HTML实体、HTML全局属性和meta元信息

写在前面 Hello大家好&#xff0c; 我是【麟-小白】&#xff0c;一位软件工程专业的学生&#xff0c;喜好计算机知识。希望大家能够一起学习进步呀&#xff01;本人是一名在读大学生&#xff0c;专业水平有限&#xff0c;如发现错误或不足之处&#xff0c;请多多指正&#xff0…

【前端面试题——微信小程序】

目录1.请谈谈wxml与标准的html的异同&#xff1f;2.请谈谈WXSS和CSS的异同&#xff1f;3.请谈谈微信小程序主要目录和文件的作用&#xff1f;4.请谈谈小程序的双向绑定和vue的异同&#xff1f;5.简单描述下微信小程序的相关文件类型&#xff1f;6.微信小程序有哪些传值(传递数据…

jsp+javaEE+mysql校园物品租赁系统dzkf5294程序

1&#xff0e;物品信息管理&#xff1a;管理员发布物品信息后&#xff0c;普通用户便可以查询到该物品信息&#xff0c;用户选择某个物品信息&#xff0c;查询物品信息&#xff0c;管理员审核添加&#xff0c;或删除物品信息。 2&#xff0e;租赁管理&#xff1a;管理员发布租赁…

ChatGPT大解密:带您探讨机器学习背后的秘密、利用与发展

一、什么是机器学习&#xff1f;二、ChatGPT 的运作原理三、ChatGPT 生活利用1、自然语言处理2、翻译3、自动回复四、ChatGPT vs 其他相关技术五、ChatGPT 的未来1、未来发展2、职业取代3、客服人员4、翻译人员5、语言学家6、机遇与挑战六、结语这篇文章&#xff0c;将带着各位…

ThreeJS-投影、投影模糊(十七)

无投影&#xff1a; 完整的代码&#xff1a; <template> <div id"three_div"></div> </template> <script> import * as THREE from "three"; import { OrbitControls } from "three/examples/jsm/controls/Or…

再不转型为ChatGPT程序员,有遭受降维打击的危险

Open AI在演示GPT-4的时候&#xff0c;有这么一个场景&#xff1a;给一个界面草图&#xff0c;就可以生成网页代码。这个演示非常简单&#xff0c;如果界面原型比较复杂呢&#xff1f;像这样&#xff1a;ChatGPT能不能直接生成HTML, CSS,JavaScript代码&#xff0c;把这个网页给…

MongoDB副本集Command failed with error 10107 (NotMaster):on server

问题 通过DataGrip连接的MongoDB节点&#xff0c;之前可以新增或更新数据。某天突然不能新增或更新数据&#xff0c;报错信息如下&#xff1a; 具体的报错信息&#xff1a; Command failed with error 10107 (NotMaster): not master on server 10.19.21.11:30386. The full…

HNU-电路与电子学-实验3

实验三 模型机组合部件的实现&#xff08;二&#xff09;&#xff08;实验报告格式案例&#xff09; 班级 计XXXXX 姓名 wolf 学号 2021080XXXXX 一、实验目的 1&#xff0e;了解简易模型机的内部结构和工作原理。 2&#xff0e;分析模型机的功能&am…

【Linux】LVM与磁盘配额

文章目录1.LVM1.1 LVM概述1.2 LVM机制1.3 LVM管理命令1.4 LVM应用实例2. 磁盘配额2.1 磁盘配额概述2.2 磁盘配额管理2.3 启用磁盘配额支持2.4 磁盘配额应用实例1.LVM 1.1 LVM概述 Logical Volume Manager&#xff0c;逻辑卷管理 ● 能够在保持现有数据不变的情况下动态调整磁盘…

43掌握自动化运维工具 Puppet 的基本用法,包括模块编写、资源管理

Puppet是一种自动化配置管理工具&#xff0c;可以自动化地部署、配置和管理大规模服务器环境。本教程将介绍Puppet的基本用法&#xff0c;包括模块编写和资源管理。 模块编写 在Puppet中&#xff0c;模块是一组相关的类、文件和资源的集合。模块可以用于部署和配置应用程序、服…

图形编辑器:排列移动功能的实现

大家好&#xff0c;我是前端西瓜哥。这次来实现一下图形编辑器排列&#xff08;arrange&#xff09;功能的实现。 先看效果。 有四种移动方式&#xff1a; 置顶&#xff08;Front&#xff09;&#xff1a;将指定的图形移动到顶部&#xff1b;置底&#xff08;Back&#xff09…

嵌入式学深度学习:1、Pytorch框架搭建

嵌入式学深度学习&#xff1a;1、Pytorch框架搭建1、介绍2、Pytorch开发环境搭建2.1、查看GPU是否支持CUDA2.2、安装Miniconda2.3、使用Conda安装pytorch2.4、安装常用库3、简单使用验证1、介绍 深度学习是机器学习的一种&#xff0c;如下图&#xff1a; 目前深度学习应用场景…

MySQL-四大类日志

目录 &#x1f341;MySQL日志分为4大类 &#x1f341;错误日志 &#x1f343;修改系统配置 &#x1f341;二进制日志 &#x1f343;查看二进制日志 &#x1f343;删除二进制日志 &#x1f343;暂时停止二进制日志的功能 &#x1f341;事务日志(或称redo日志) &#x1f341;慢查…

chatgpt3中文辅助写作-gpt2中文文本生成

GPT-3是一种深度学习模型&#xff0c;具有潜在的巨大计算成本和训练麻烦。根据OpenAI公司的官方消息&#xff0c;训练GPT-3是一项昂贵的和耗时的过程&#xff0c;在OpenAI公司&#xff0c;训练GPT-3的成本已经超过了10亿美元。考虑到GPT-3的架构、规模和训练时间&#xff0c;这…

高分子PEG磷酸盐mPEG-phosphoric acid,Phosphate PEG,甲氧基聚乙二醇磷酸,可用于修饰金属氧化物表面

规格单位&#xff1a;g |货期&#xff1a;按照具体的库存进行提供 | 端基取代率&#xff1a;95% 中英文名&#xff1a;mPEG-phosphoric acid|Phosphate PEG|甲氧基聚乙二醇磷酸​ 一、Phosphate PEG化学结构式&#xff1a; 二、产品详情&#xff1a; 外观&#xff1a;灰白…

[oeasy]python0123_中文字符_文字编码_gb2312_激光照排技术_王选

中文编码GB2312 回忆上次内容 上次回顾了 日韩各有 编码格式 日本 有假名 五十音一字节 可以勉强放下 有日本汉字 字符数量超过20000 韩国 有谚文 数量超过500一个字节 放不下 有朝鲜汉字 字符数量超过20000 作为 汉字源头的中国 究竟应该 如何对汉字 进行编码 呢&#x…

操作系统-AOSOA

一、个人感受 1.1 权衡 在我写这份报告的时候&#xff0c;已经是 6 月 30 号了&#xff0c;经历了一个学期的“折磨”&#xff0c;我面对终点&#xff0c;已经没啥感觉了&#xff0c;就想着赶快呼噜完了就完事了。其实做这个项目最大的体会就是“人力有穷&#xff0c;一切皆权…

视频剪辑:教你如何调整视频画面的大小。

大家应该都会调整图片的大小吧&#xff0c;那你们会调整视频画面的大小吗&#xff1f;我想&#xff0c;应该会有人不还不知道要调整的吧&#xff0c;今天就让小编来教大家一个方法怎样去调整视频画面的大小尺寸。 首先&#xff0c;我们要有以下材料&#xff1a; 一台电脑 【…

列的类型定义——整形类型

文章目录 前言一、整数类型的附带属性 类型名称后面的小括号unsignedauto_increment总结前言 1&#xff09;采用26字母和0-9的自然数加上下互相 ‘_’ 组成&#xff0c;命名简洁明确&#xff0c;多个单词用下划线 ‘_’ 隔开 2&#xff09;全部小写命名&#xff0c;尽量避免…
最新文章