Verilog基础(三):过程

过程(Procedures)

- Always块 – 组合逻辑 (Always blocks – Combinational)

由于数字电路是由电线相连的逻辑门组成的,所以任何电路都可以表示为模块和赋值语句的某种组合.

然而,有时这不是描述电路最方便的方法.

两种always block是十分有用的:

  • 组合逻辑: always @(*)
  • 时序逻辑: always @(posedge clk)

always @(*)就相当于赋值语句–assign,因此选择哪一种语法仅仅取决与方便程度.

block内还有更丰富的语句集,比如if-else,case等等.但不能包含连续赋值即不可包含assign,因为他与always @(*)冲突.

以下语句是等价的

assign out1 = a & b | c ^ d;
always @(*) out2 = a & b | c ^ d;

  • Module Declaraction
module top_module(
    input a, 
    input b,
    output wire out_assign,
    output reg out_alwaysblock
);
  • Solution
// synthesis verilog_input_version verilog_2001
module top_module(
    input a, 
    input b,
    output wire out_assign,
    output reg out_alwaysblock
);
	assign out_assign = a&b;
    
    always @(*) out_alwaysblock = a&b;
endmodule
- Always块 – 时序逻辑 (Always blocks – Clocked)

verilog中有三种赋值方式:

  • 连续赋值: assign x = y; 不能在always-block内使用
  • 阻塞赋值: x = y;, 只能在always-block内使用
  • 非阻塞赋值: x <= y,只能在always-block内使用

请在组合逻辑中使用阻塞赋值,在时序逻辑中使用非阻塞赋值
否则将产生难以发现的错误

请实现如下电路:

  • Module Declaraction
module top_module(
    input clk,
    input a,
    input b,
    output wire out_assign,
    output reg out_always_comb,
    output reg out_always_ff   );
  • Solution
// synthesis verilog_input_version verilog_2001
module top_module(
    input clk,
    input a,
    input b,
    output wire out_assign,
    output reg out_always_comb,
    output reg out_always_ff   );
assign out_assign = a^b;
    
    always @(*) out_always_comb = a^b;
    
    always @(posedge clk) out_always_ff <= a^b;
endmodule
- If语句

if语句通常创建一个2对1的多路选择器,如果条件为真,则选择一个输入,如果条件为假,则选择另一个输入.

以下两种写法是等价的:

always @(*) begin
    if (condition) begin
        out = x;
    end
    else begin
        out = y;
    end
end

assign out = (condition) ? x : y;

建立一个在a和b之间选择的2对1多路选择器.如果sel_b1和sel_b2都为真,则选择b.否则,选择a.

执行相同的操作两次,一次使用assign语句,一次使用if语句.

  • Module Declaraction
module top_module(
    input a,
    input b,
    input sel_b1,
    input sel_b2,
    output wire out_assign,
    output reg out_always   ); 
  • Solution
// synthesis verilog_input_version verilog_2001
module top_module(
    input a,
    input b,
    input sel_b1,
    input sel_b2,
    output wire out_assign,
    output reg out_always   ); 
    assign out_assign = (sel_b1&sel_b2)?b:a;
    
    always @(*) begin
        if(sel_b1&sel_b2) begin
            out_always = b;
        end
        else begin
            out_always = a;
        end
    end
endmodule
- If语句引发的锁存(latches)

以下代码包含锁存的错误行为.

  • Module Declaraction
always @(*) begin
    if (cpu_overheated)
       shut_off_computer = 1;
end

always @(*) begin
    if (~arrived)
       keep_driving = ~gas_tank_empty;
end
  • Solution
// synthesis verilog_input_version verilog_2001
module top_module (
    input      cpu_overheated,
    output reg shut_off_computer,
    input      arrived,
    input      gas_tank_empty,
    output reg keep_driving  ); //

    always @(*) begin
        if (cpu_overheated) begin
            shut_off_computer = 1;
        end
        else begin
            shut_off_computer = 0;
        end
    end
    
    always @(*) begin
        if (~arrived&~gas_tank_empty) begin
            keep_driving = ~gas_tank_empty&(~arrived);
       end
       else begin
           keep_driving = ~(gas_tank_empty|arrived);
       end
    end

endmodule

If语句在硬件描述语言(如Verilog)中用于描述受条件控制的电路。然而,不当的If语句使用可能会引发锁存器(latches)的产生,这在FPGA或ASIC设计中通常是不希望看到的。以下是对If语句引发锁存器的详细分析:

  • 一、锁存器的基本概念

锁存器是一种在异步电路系统中对输入信号电平敏感的单元,用来存储信息。当锁存信号有效时,数据被锁存,输入信号不再起作用。锁存器也被称为透明锁存器,因为不锁存时输出对于输入是透明的。

  • 二、If语句引发锁存器的情况

    在Verilog中,If语句引发锁存器的情况主要包括以下几种:

    1. 组合逻辑中If语句缺少Else分支

      • 在组合逻辑电路中,如果If语句没有覆盖所有可能的条件,并且没有提供Else分支来指定其他条件下的输出,那么综合工具可能会推断出一个锁存器行为来保持上一个状态。
      • 例如,if (enable) reg <= data;enable为假时,reg的值将保持不变,这可能导致锁存器的产生。
    2. 敏感信号列表不完整

      • always块中使用非阻塞赋值(<=)时,如果没有显式的敏感信号列表或者敏感信号列表不完整,也可能导致锁存器的产生。
      • 这是因为综合器可能无法正确判断何时应更新信号,从而推断出锁存器行为来保持信号状态。
    3. 输出变量赋值给自己

      • 在If语句或组合逻辑中,如果输出变量被赋值给自己(即赋值表达式中包含输出变量自身),也可能导致锁存器的产生。
      • 这是因为输出变量需要具有存储功能来保持其上一个状态。
  • 三、避免If语句引发锁存器的策略

    为了避免If语句引发锁存器,可以采取以下策略:

    1. 确保If语句结构完整

      • 在组合逻辑中,确保If语句覆盖所有可能的条件,并提供Else分支来指定其他条件下的输出。
      • 这有助于确保输出在所有条件下都有一个已知的状态,从而避免锁存器的产生。
    2. 使用阻塞赋值明确表达组合逻辑

      • 在组合逻辑中,使用阻塞赋值(=)来明确表达逻辑关系,而不是使用非阻塞赋值。
      • 这有助于综合工具正确识别组合逻辑并避免推断出锁存器。
    3. 完善敏感信号列表

      • 在使用非阻塞赋值时,确保always块有完整的敏感信号列表。
      • 这有助于综合工具正确判断何时应更新信号并避免锁存器的产生。
    4. 避免输出变量赋值给自己

      • 在组合逻辑中,避免将输出变量赋值给自己。
      • 如果需要保持上一个状态,可以考虑使用触发器(Flip-Flop)而不是锁存器。
  • 四、锁存器的危害与替代方案

锁存器在FPGA或ASIC设计中可能带来以下危害:

  1. 不可预测的时序行为:锁存器的输出取决于输入信号的持续电平,而不是特定的时钟边沿,这使得时序分析和预测更加困难。
  2. 系统不稳定:由于锁存器的输出直接由输入决定,任何输入上的噪声或毛刺都会立即反映到输出上,可能导致系统不稳定或误操作。
  3. 资源利用率降低:FPGA内部的锁存器实现通常不如寄存器高效,可能降低资源利用率并增加功耗。

因此,在FPGA设计中,通常推荐使用寄存器(触发器)来代替锁存器,除非有特殊的应用场景要求锁存器的使用。寄存器在时钟边沿更新,提供了更可预测和稳定的行为,便于时序分析和设计验证。

综上所述,If语句在硬件描述语言中的使用需要谨慎,以避免引发不必要的锁存器。通过确保If语句结构完整、使用阻塞赋值明确表达组合逻辑、完善敏感信号列表以及避免输出变量赋值给自己等策略,可以有效避免锁存器的产生。


- Case语句

verilog中的case语句几乎等同于if elseif else的序列,该序列将一个表达式与其他表达式列表进行比较.它的语法和功能与C语言中的switch语句不同.

always @(*) begin     // This is a combinational circuit
    case (in)
      1'b1: begin 
               out = 1'b1;  // begin-end if >1 statement
            end
      1'b0: out = 1'b0;
      default: out = 1'bx;
    endcase
end
  • case语句以case开头,每个"case item"以冒号结尾,没有switch
  • 每个case项只能执行一条语句.这使得C中使用的“break”不必要.但这意味着如果需要多个语句,必须使用begin…end

如果有大量选项的情况,case语句比if语句更方便.因此,在本练习中,创建一个6对1的多路选择器.当sel介于0和5之间时,选择相应的数据输入,否则,输出0.数据输入和输出均为4位宽.小心锁存.

  • Module Declaraction
module top_module ( 
    input [2:0] sel, 
    input [3:0] data0,
    input [3:0] data1,
    input [3:0] data2,
    input [3:0] data3,
    input [3:0] data4,
    input [3:0] data5,
    output reg [3:0] out   );
  • Solution
// synthesis verilog_input_version verilog_2001
module top_module ( 
    input [2:0] sel, 
    input [3:0] data0,
    input [3:0] data1,
    input [3:0] data2,
    input [3:0] data3,
    input [3:0] data4,
    input [3:0] data5,
    output reg [3:0] out   );//

    always@(*) begin  // This is a combinational circuit
        case(sel)
            3'b0: begin
                out = data0;
            end
            3'b001: begin
                out = data1;
            end
            3'b010: begin
                out = data2;
            end
            3'b011: begin
                out = data3;
            end
            3'b100: begin
                out = data4;
            end
            3'b101: begin
                out = data5;
            end
            default: begin
                out[3:0] = 0;
            end
        endcase
    end

endmodule
- 简单编码器1

priority encoder是一种组合电路,当输入一个vector时,输出第一个’1’出现的位置.例如:输入8’b10010000,输出3’d4,因为[4]是第一个高位.
构建一个4位encoder,若全是低位则输出0.

  • Module Declaraction
module top_module (
    input [3:0] in,
    output reg [1:0] pos  );
  • Solution
// synthesis verilog_input_version verilog_2001
module top_module (
    input [3:0] in,
    output reg [1:0] pos  );
    always @(*) begin
        if (in[0] == 1'b1) begin
                pos = 2'd0;
        end
        else begin
            if(in[1] == 1'b1) begin
                pos = 2'd1;
            end
            else begin
                if(in[2] == 1'b1) begin
                    pos = 2'd2;
                end
                else begin
                    if(in[3] == 1'b1) begin
                        pos = 2'd3;
                    end
                    else begin
                        pos = 0;
                    end
                end
            end
        end
    end
endmodule
- 简单编码器2

假如现在输入是8位,那么就会有256种情况,我们可以使用casez来将item减少到9种.
例如:

always @(*) begin
    casez (in[3:0])
        4'bzzz1: out = 0;   // in[3:1] can be anything
        4'bzz1z: out = 1;
        4'bz1zz: out = 2;
        4'b1zzz: out = 3;
        default: out = 0;
    endcase
end
  • Module Declaraction
module top_module (
    input [7:0] in,
    output reg [2:0] pos  );
  • Solution
// synthesis verilog_input_version verilog_2001
module top_module (
    input [7:0] in,
    output reg [2:0] pos  );
always @(*) begin
    casez (in[7:0])
        8'bzzzzzzz1: begin
            pos = 3'd0;
        end
        8'bzzzzzz1z: begin
            pos = 3'd1;
        end
        8'bzzzzz1zz: begin
            pos = 3'd2;
        end
        8'bzzzz1zzz: begin
            pos = 3'd3;
        end
        8'bzzz1zzzz: begin
            pos = 3'd4;
        end
        8'bzz1zzzzz: begin
            pos = 3'd5;
        end
        8'bz1zzzzzz: begin
            pos = 3'd6;
        end
        8'b1zzzzzzz: begin
            pos = 3'd7;
        end
        default: begin
            pos = 0;
        end
    endcase
end
endmodule
- 避免锁存

假设您正在构建一个电路来处理游戏中PS/2键盘的扫描代码.

接收到的最后两个字节的扫描代码,您需要判断是否已按下键盘上的一个箭头键.这涉及到一个相当简单的映射,它可以使用一个case语句(或者如果elseif)实现,有四个case.

Scancode [15:0]Arrow key
16’he06bleft arrow
16’he072down arrow
16’he074right arrow
16’he075up arrow
Anythingelse none

为了避免创建锁存,必须在所有可能的条件下为所有输出分配一个值

  • Module Declaraction
module top_module (
    input [15:0] scancode,
    output reg left,
    output reg down,
    output reg right,
    output reg up  ); 
  • Solution
// synthesis verilog_input_version verilog_2001
module top_module (
    input [15:0] scancode,
    output reg left,
    output reg down,
    output reg right,
    output reg up  ); 
    always @(*) begin
        left = 0;
        down = 0;
        left = 0;
        right = 0;
        case (scancode)
            16'he06b: begin
                left = 1;
            end
            16'he072: begin
                down = 1;
            end
            16'he074: begin
                right = 1;
            end
            16'he075: begin
                up = 1;
            end
            default: begin
                up = 0;
                down = 0;
                left = 0;
                right = 0;
            end
        endcase
    end
endmodule

更多语法特点

verilog也有像C一样的三目算符:

- 三目算符

verilog也有像C一样的三目算符:

condition ? true : false;

给定四个无符号数,求其最小值.

  • Module Declaraction
module top_module (
    input [7:0] a, b, c, d,
    output [7:0] min);
  • Solution
module top_module (
    input [7:0] a, b, c, d,
    output [7:0] min);//

    // assign intermediate_result1 = compare? true: false;
	
    wire [7:0]min1,min2;
    assign min1=(a<b?a:b);
    
    assign min2 = (min1<c?min1:c);
    
    assign min = (min2<d?min2:d);
endmodule

- 优化运算1

奇偶校验经常被用来作为一种简单的方法检测错误.

创建一个电路,该电路将为一个8位字节计算一个奇偶校验位.

即计算输入8个位的异或

  • Module Declaraction
module top_module (
    input [7:0] in,
    output parity); 
  • Solution
module top_module (
    input [7:0] in,
    output parity); 
    assign parity = ^in[7:0];
endmodule
- 优化运算2

建立如下电路:

  • out_and: 对输入数据求与

  • out_or: 对输入数据求或

  • out_xor:对输入数据求异或

  • Module Declaraction

module top_module( 
    input [99:0] in,
    output out_and,
    output out_or,
    output out_xor 
);
  • Solution
module top_module( 
    input [99:0] in,
    output out_and,
    output out_or,
    output out_xor 
);
    assign out_and = &in[99:0];
    assign out_or = |in[99:0];
    assign out_xor = ^in[99:0];
endmodule
- 循环 – 组合逻辑:实现Vector反转

反转vector顺序

  • Module Declaraction
module top_module( 
    input [99:0] in,
    output [99:0] out
);
  • Solution
module top_module( 
    input [99:0] in,
    output [99:0] out
);
    integer i;
    always @(*) begin
        for(i=0;i<=99;i=i+1)
            out[7'd99-i] <= in[i];
    end
endmodule
- 循环 – 组合逻辑:实现255位计数器

计算vector中1的个数

  • Module Declaraction
module top_module( 
    input [254:0] in,
    output [7:0] out );
  • Solution
module top_module( 
    input [254:0] in,
    output [7:0] out );
    integer i;
    reg [7:0]count;
    always @(*) begin
        
	count=0;
        for(i=0;i<=254;i=i+1) begin
            if(in[i] == 1) begin
                count = count + 7'b1;
            end
        end
    end
    assign out = count;
endmodule
- 循环:实现100位加法器

通过实例化100个全加器构建一个100位加法器.

  • Module Declaraction
module top_module( 
    input [99:0] a, b,
    input cin,
    output [99:0] cout,
    output [99:0] sum );
  • Solution
module top_module( 
    input [99:0] a, b,
    input cin,
    output [99:0] cout,
    output [99:0] sum );
    reg [100:0]cin1;

    generate
    genvar i;
    for(i=0;i<100;i=i+1) begin:adds
        
        if(i==0) begin        
		    add ins(a[i],b[i],cin,sum[i],cout[i]);            
            assign cin1[i+1]=cout[i];
        end            
        else begin
            add ins(a[i],b[i],cin1[i],sum[i],cout[i]);
            assign cin1[i+1]=cout[i];            
        end
    end
    endgenerate
endmodule

module add(input a, input b, input cin, output sum, output cout);
    assign {cout,sum}=a+b+cin;
endmodule

- 循环:实现100位BCD加法器

在Verilog中实现一个100位的BCD(Binary-Coded Decimal)加法器相对复杂,因为BCD编码的每个数字占用4位二进制数,所以100位的BCD数实际上表示的是25位的十进制数(100位 / 4位/十进制数字 = 25个十进制数字)。

BCD加法的一个关键问题是进位处理。在普通的二进制加法中,进位是逐位传递的,但在BCD加法中,每四位(一个BCD数字)之间可能需要额外的调整来处理从低位到高位的进位,以确保结果仍然是有效的BCD数。这通常涉及到将非BCD的中间结果转换为BCD格式。

以下是一个简化的Verilog代码示例,用于实现两个4位BCD数的加法,并调整结果以确保它是有效的BCD数。请注意,这个示例并没有直接扩展到100位,但它提供了一个基础,你可以在这个基础上构建更复杂的100位BCD加法器。

module bcd_adder_4bit(
    input [3:0] a, // 4-bit BCD input
    input [3:0] b, // 4-bit BCD input
    input cin,     // Carry-in
    output [3:0] sum, // 4-bit BCD output
    output cout    // Carry-out
);
    wire [4:0] temp_sum; // 5-bit temporary sum to handle carry
    wire [3:0] adjusted_sum; // 4-bit adjusted BCD sum
    wire temp_cout; // Temporary carry-out

    // Perform binary addition of the BCD digits and the carry-in
    assign temp_sum = a + b + cin;
    assign temp_cout = (temp_sum[4] == 1'b1); // Carry-out if the sum is 5-bits wide

    // BCD adjustment: if the result is greater than or equal to 10 (0xA in BCD), adjust it
    // to be in the range 0-9 by subtracting 6 (0x6 in BCD) and setting the carry-out for the next BCD digit
    assign adjusted_sum = (temp_sum >= 4'd10) ? (temp_sum - 4'd6) : temp_sum[3:0];

    // Carry-out for the next BCD digit is set if the original sum was 10 or more, or if there was a carry-in and the sum was exactly 9
    wire carry_adjustment = (temp_sum == 4'd10) | (cin && temp_sum == 4'd9);
    assign cout = temp_cout | carry_adjustment;

    // Output the adjusted sum
    assign sum = adjusted_sum;

endmodule

要构建一个100位的BCD加法器,你需要将上述4位BCD加法器模块级联25次(因为100位/4位/数字=25个数字)。每个模块的输出cout将作为下一个模块的cin。同时,你需要一个额外的机制来处理最高位可能产生的进位(如果两个加数的和超过最大的25位BCD数)。

请注意,这个示例代码没有考虑所有可能的边界情况和优化。在实际应用中,你可能需要更复杂的逻辑来处理溢出、零检测、符号扩展等问题。此外,对于大规模设计,使用高级综合工具或手动优化可能有助于提高性能和资源利用率。

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

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

相关文章

[mmdetection]fast-rcnn模型训练自己的数据集的详细教程

本篇博客是由本人亲自调试成功后的学习笔记。使用了mmdetection项目包进行fast-rcnn模型的训练&#xff0c;数据集是自制图像数据。废话不多说&#xff0c;下面进入训练步骤教程。 注&#xff1a;本人使用linux服务器进行展示&#xff0c;Windows环境大差不差。另外&#xff0…

计算机网络——三种交换技术

目录 电路交换——用于电话网络 电路交换的优点&#xff1a; 电路交换的缺点&#xff1a; 报文交换——用于电报网络 报文交换的优点&#xff1a; 报文交换的缺点&#xff1a; 分组交换——用于现代计算机网络 分组交换的优点&#xff1a; 分组交换的缺点 电路交换——…

Java项目: 基于SpringBoot+mybatis+maven+mysql实现的图书管理系统(含源码+数据库+答辩PPT+毕业论文)

一、项目简介 本项目是一套基于SpringBootmybatismavenmysql实现的图书管理系统 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;eclipse或者idea 确保可以运行&#xff01; 该系统功能完善、界面美观…

Spring PropertyPlaceholderConfigurer多配置问题

本文重点是通过例子代码的debug了解PropertyPlaceholderConfigurer的原理 更多可阅读&#xff1a;placeholderconfigurer文档 了解 目录 测试程序如下PropertyPlaceholderConfigurerplaceholderConfigurer1 & placeholderConfigurer2的执行userbean的BeanDefinition应用Pr…

利用Vue编写一个“计数器”

目录 一、利用Vue编写一个“计数器”的操作方法&#xff1a;二、html文件相关源代码三、CSS文件相关源代码四、代码执行效果展示如下 一、利用Vue编写一个“计数器”的操作方法&#xff1a; 1、data中定义计数器的相关数据&#xff0c;如num、min、max。 2、methods中添加计数…

aws(学习笔记第二十七课) 使用aws API Gateway+lambda体验REST API

aws(学习笔记第二十七课) 使用aws API Gatewaylambda体验REST API 学习内容&#xff1a; 使用aws API Gatewaylambda 1. 使用aws API Gatewaylambda 作成概要 使用api gateway定义REST API&#xff0c;之后再接收到了http request之后&#xff0c;redirect到lambda进行执行。…

自研有限元软件与ANSYS精度对比-Bar3D2Node三维杆单元模型-央视大裤衩实例

目录 1、“央视大裤衩”自研有限元软件求解 1.1、选择单元类型 1.2、导入“央视大裤衩”工程 1.3、节点坐标定义 1.4、单元连接关系、材料定义 1.5、约束定义 1.6、外载定义 1.7、矩阵求解 1.8、变形云图展示 1.9、节点位移 1.10、单元应力 1.11、节点支反力 2、“…

家政预约小程序12服务详情

目录 1 修改数据源2 创建页面3 搭建轮播图4 搭建基本信息5 显示服务规格6 搭建服务描述7 设置过滤条件总结 我们已经在首页、分类页面显示了服务的列表信息&#xff0c;当点击服务的内容时候需要显示服务的详情信息&#xff0c;本篇介绍一下详情页功能的搭建。 1 修改数据源 在…

Multi-Scale Heterogeneous Text-Attributed Graph Datasets From Diverse Domains

Multi-Scale Heterogeneous Text-Attributed Graph Datasets From Diverse Domains WWW25 推荐指数&#xff1a;#paper/⭐⭐⭐#​ 代码地址&#xff1a;https://github.com/Cloudy1225/HTAG 作者主页&#xff1a;Yunhui Lius Homepage 一句话总结&#xff1a;提出了涵盖多…

day31-综合架构开篇(中)

轻松理解网站架构 运维内网维护架构

使用 SpringBoot+Thymeleaf 模板引擎进行 Web 开发

目录 一、什么是 Thymeleaf 模板引擎 二、Thymeleaf 模板引擎的 Maven 坐标 三、配置 Thymeleaf 四、访问页面 五、访问静态资源 六、Thymeleaf 使用示例 七、Thymeleaf 常用属性 前言 在现代 Web 开发中&#xff0c;模板引擎被广泛用于将动态内容渲染到静态页面中。Thy…

Verilog基础(一):基础元素

verilog基础 我先说&#xff0c;看了肯定会忘&#xff0c;但是重要的是这个过程&#xff0c;我们知道了概念&#xff0c;知道了以后在哪里查询。语法都是术&#xff0c;通用的概念是术。所以如果你有相关的软件编程经验&#xff0c;那么其实开启这个学习之旅&#xff0c;你会感…

保姆级教程Docker部署Kafka官方镜像

目录 一、安装Docker及可视化工具 二、单节点部署 1、创建挂载目录 2、运行Kafka容器 3、Compose运行Kafka容器 4、查看Kafka运行状态 三、集群部署 在Kafka2.8版本之前&#xff0c;Kafka是强依赖于Zookeeper中间件的&#xff0c;这本身就很不合理&#xff0c;中间件依赖…

yes镜像站群/PHP驱动的镜像站群架构实践

▍当前站群运维的三大技术困局 在近期与多个IDC服务商的交流中发现&#xff0c;传统站群系统普遍面临&#xff1a; 同步效率瓶颈&#xff1a;跨服务器内容同步耗时超过行业标准的42%SEO权重稀释&#xff1a;镜像站点重复率导致70%的站点无法进入百度前3页运维成本失控&#x…

知识库管理系统提升知识利用效率与企业创新能力的全面方案分析

内容概要 知识库管理系统作为现代企业信息化建设的重要组成部分&#xff0c;承担着整合、存储与分发知识资源的重任。其核心功能包括信息的分类与索引、知识的共享与协作&#xff0c;以及数据分析与挖掘等。这些功能不仅提高了企业内部信息流动的速度和效果&#xff0c;还为员…

STM32F103ZET6完整技术点(持续更新~)

①STM32②F③103④Z⑤E⑥T⑦6简介&#xff1a; ①基于ARM核心的32位微控制器&#xff0c;②通用类型&#xff0c;③增强型&#xff0c;④引脚数目144个 ⑤闪存存储器容量&#xff1a;512K字节&#xff0c;⑥封装:LQFP&#xff0c;⑦温度范围&#xff1a;工业级温度范围&#xf…

html基本结构和常见元素

html5文档基本结构 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><title>文档标题</title> </head> <body>文档正文部分 </body> </html> html文档可分为文档头和文档体…

Markdown转换器中间件

目录 需求 文本编码检测 Markdown→HTML 注意 实现 需求 Markdown是一种文本格式&#xff1b;不被浏览器支持&#xff1b;编写一个在服务器端把Markdown转换为HTML的中间件。我们开发的中间件是构建在ASP.NET Core内置的StaticFiles中间件之上&#xff0c;并且在它之前运…

数据降维技术研究:Karhunen-Loève展开与快速傅里叶变换的理论基础及应用

在现代科学计算和数据分析领域&#xff0c;数据降维与压缩技术对于处理高维数据具有重要意义。本文主要探讨两种基础而重要的数学工具&#xff1a;Karhunen-Love展开&#xff08;KLE&#xff09;和快速傅里叶变换&#xff08;FFT&#xff09;。通过分析这两种方法的理论基础和应…

使用LightGlue进行图像配准并提取图像重叠区域

发表日期&#xff1a;2023年6月23日 项目地址&#xff1a;https://github.com/cvg/LightGlue https://github.com/cvg/glue-factory/ LightGlue是一个在精度上媲美Superglue&#xff0c;但在速度上比Superglue快一倍的模型。通过博主实测&#xff0c;LightGlue的配准效果比Su…