用AI生成rtl设计(a simple synchronous FIFO)的一个实验

目录

1. 前言

2. RTL  and testbench generation

2.1 RTL generation

Explanation:

Assumptions:

2.2 Testbench generation

Explanation:

2.3 Add fsdb dump to testbench

3. 仿真与调试

3.1 RTL中的语法问题

3.2 testbench的问题        

3.3 RTL中empty/full状态标志逻辑问题

3.3.1 full generation logic

3.3.2 read empty and write full protection

4. 小结


1. 前言

        本实验用一个国内某大厂的AI大模型试着生成了一个同步FIFO的RTL模型,然后相应生成了一个简易的test-bench。目的是想看看现在大模型在数字逻辑设计领域能够对工程师有多少帮助。

2. RTL  and testbench generation

2.1 RTL generation

首先,请求大模型生成一个同步FIFO的RTL设计:

Prompt:

Can you generate one synchronous FIFO RTL implementation?

Response:

 Certainly! Below is a basic synchronous FIFO (First-In-First-Out) implementation in Verilog RTL (Register-Transfer Level). This FIFO uses a fixed-size array to store data and simple counters to manage the read and write pointers. It assumes a synchronous clock domain and includes basic functionality for writing, reading, checking if the FIFO is empty, and checking if it is full.

module SFIFO #(  
    parameter DATA_WIDTH = 8,    // Width of each data element  
    parameter FIFO_DEPTH = 16    // Depth of the FIFO  
)(  
    input wire clk,              // Clock signal  
    input wire rst_n,            // Active-low reset signal  
    input wire wr_en,            // Write enable  
    input wire rd_en,            // Read enable  
    input wire [DATA_WIDTH-1:0] din, // Data input  
    output reg [DATA_WIDTH-1:0] dout, // Data output  
    output wire full,            // FIFO full flag  
    output wire empty           // FIFO empty flag  
);  
  
    // Internal memory array to store FIFO data  
    reg [DATA_WIDTH-1:0] fifo_mem [0:FIFO_DEPTH-1];  
  
    // Pointers for write and read operations  
    reg [3:0] wr_ptr = 0;  // Write pointer (assuming FIFO_DEPTH <= 16)  
    reg [3:0] rd_ptr = 0;  // Read pointer (assuming FIFO_DEPTH <= 16)  
  
    // Count of valid entries in the FIFO  
    reg [3:0] count = 0;  
  
    // Write operation  
    always @(posedge clk or negedge rst_n) begin  
        if (!rst_n) begin  
            wr_ptr <= 0;  
        end else if (wr_en && !full) begin  
            fifo_mem[wr_ptr] <= din;  
            wr_ptr <= wr_ptr + 1;  
        end  
    end  
  
    // Read operation  
    always @(posedge clk or negedge rst_n) begin  
        if (!rst_n) begin  
            rd_ptr <= 0;  
            dout <= 0;  
        end else if (rd_en && !empty) begin  
            dout <= fifo_mem[rd_ptr];  
            rd_ptr <= rd_ptr + 1;  
        end  
    end  
  
    // Count of valid entries  
    always @(posedge clk or negedge rst_n) begin  
        if (!rst_n) begin  
            count <= 0;  
        end else begin  
            The originally generated code segment.
            case ({wr_en, rd_en, full, empty})  
                // Write without read when not full  
                {1'b1, 1'b0, 1'b0, _}: count <= count + 1;  // change "_" to "1'bx"
                // Write without read when already full (should not happen due to wr_en condition)  
                {1'b1, 1'b0, 1'b1, _}: count <= count;  
                // Read without write when not empty  
                {1'b0, 1'b1, _, 1'b0}: count <= count - 1;  
                // Read without write when already empty (should not happen due to rd_en condition)  
                {1'b0, 1'b1, _, 1'b1}: count <= count;  
                // Both read and write (balance)  
                {1'b1, 1'b1, _, _}: count <= count;  
                // No operation  
                default: count <= count;  
        end  
    end  
  
    // FIFO full flag  
    assign full = (count == FIFO_DEPTH);  
  
    // FIFO empty flag  
    assign empty = (count == 0);  
  
endmodule

除了代码外,大模型还给出了简要的设计描述,如下所示:

Explanation:

  1. Parameters:
    • DATA_WIDTH: Width of each data element in the FIFO.
    • FIFO_DEPTH: Depth (number of elements) of the FIFO.
  2. Inputs and Outputs:
    • clk: Clock signal.
    • rst_n: Active-low reset signal.
    • wr_en: Write enable signal.
    • rd_en: Read enable signal.
    • din: Data input.
    • dout: Data output.
    • full: FIFO full flag.
    • empty: FIFO empty flag.
  3. Internal Registers:
    • fifo_mem: Array to store FIFO data.
    • wr_ptr and rd_ptr: Write and read pointers.
    • count: Number of valid entries in the FIFO.
  4. Logic:
    • The write pointer increments on a write enable and the read pointer increments on a read enable.
    • The count register tracks the number of valid entries.
    • The full and empty flags are derived from the count register.

Assumptions:

  • FIFO_DEPTH is less than or equal to 16, so a 4-bit pointer is sufficient.
  • rst_n is an active-low reset.
  • This FIFO does not handle overflow or underflow conditions; it assumes that wr_en will not be asserted when the FIFO is full, and rd_en will not be asserted when the FIFO is empty.

You can adjust the DATA_WIDTH and FIFO_DEPTH parameters as needed for your application.

2.2 Testbench generation

接着,让大模型生成了一个简易的testbench:

Prompt:

Please create one testbench for the above synchronous FIFO design 

Response:

Certainly! Below is a testbench for the synchronous FIFO design provided earlier. This testbench will simulate the FIFO's behavior by applying various write and read operations and observing the FIFO's state, output, and flags. 

module tb_top;  
  
    // Parameters for the FIFO  
    parameter DATA_WIDTH = 8;  
    parameter FIFO_DEPTH = 16;  
  
    // Signals for the FIFO instance  
    reg clk;  
    reg rst_n;  
    reg wr_en;  
    reg rd_en;  
    reg [DATA_WIDTH-1:0] din;  
    wire [DATA_WIDTH-1:0] dout;  
    wire full;  
    wire empty;  
  
    // Instantiate the FIFO  
    fifo #(  
        .DATA_WIDTH(DATA_WIDTH),  
        .FIFO_DEPTH(FIFO_DEPTH)  
    ) fifo_inst (  
        .clk(clk),  
        .rst_n(rst_n),  
        .wr_en(wr_en),  
        .rd_en(rd_en),  
        .din(din),  
        .dout(dout),  
        .full(full),  
        .empty(empty)  
    );  
  
    // Clock generation  
    initial begin  
        clk = 0;  
        forever #5 clk = ~clk; // 10 time units clock period (5 up, 5 down)  
    end  
  
    // Test sequence  
    initial begin  
        // Initialize signals  
        rst_n = 0;  
        wr_en = 0;  
        rd_en = 0;  
        din = 0;  
  
        // Apply reset  
        #10 rst_n = 1;  
  
        // Write data to FIFO  
        #10 wr_en = 1; din = 8'hAA;  
        #10 wr_en = 1; din = 8'hBB;  
        #10 wr_en = 1; din = 8'hCC;  
        #10 wr_en = 0;  
  
        // Check FIFO state  
        #10 if (full) $display("Error: FIFO should not be full yet.");  
        #10 if (!empty) $display("FIFO is not empty (expected).");  
        #10 if (dout != 0) $display("Error: dout should be 0.");  
  
        // Read data from FIFO  
        #10 rd_en = 1;  
        #10 if (dout != 8'hAA) $display("Error: dout should be 8'hAA.");  
        #10 rd_en = 0;  
  
        #10 rd_en = 1;  
        #10 if (dout != 8'hBB) $display("Error: dout should be 8'hBB.");  
        #10 rd_en = 0;  
  
        // Write and read simultaneously  
        #10 wr_en = 1; din = 8'hDD;  
        #10 rd_en = 1;  
        #10 if (dout != 8'hCC) $display("Error: dout should be 8'hCC.");  
        #10 wr_en = 0; rd_en = 0;  
  
        #10 rd_en = 1;  
        #10 if (dout != 8'hDD) $display("Error: dout should be 8'hDD.");  
        #10 rd_en = 0;  
  
        // Fill FIFO to capacity  
        #10 wr_en = 1; din = 8'hEE;  
        #10 wr_en = 1; din = 8'hFF;  
        #10 wr_en = 1; din = 8'h00;  
        #10 wr_en = 1; din = 8'h01;  
        #10 wr_en = 0;  
  
        #10 if (!full) $display("Error: FIFO should be full.");  
  
        // Read until FIFO is empty  
        #10 rd_en = 1;  
        #10 if (dout != 8'hEE) $display("Error: dout should be 8'hEE.");  
        #10 rd_en = 0;  
  
        #10 rd_en = 1;  
        #10 if (dout != 8'hFF) $display("Error: dout should be 8'hFF.");  
        #10 rd_en = 0;  
  
        #10 rd_en = 1;  
        #10 if (dout != 8'h00) $display("Error: dout should be 8'h00.");  
        #10 rd_en = 0;  
  
        #10 rd_en = 1;  
        #10 if (dout != 8'h01) $display("Error: dout should be 8'h01.");  
        #10 rd_en = 0;  
  
        #10 if (!empty) $display("Error: FIFO should be empty.");  
  
        // End simulation  
        #10 $finish;  
    end  
  
endmodule

同样,也给出了概要性的说明:

Explanation:

  1. Parameters:
    • The DATA_WIDTH and FIFO_DEPTH parameters are set to match the FIFO instance.
  2. Signals:
    • The testbench includes all the signals required by the FIFO instance: clkrst_nwr_enrd_endindoutfull, and empty.
  3. Clock Generation:
    • A simple clock generator is created using an initial block that toggles the clk signal every 10 time units.
  4. Test Sequence:
    • The test sequence is defined in another initial block.
    • The FIFO is reset by setting rst_n to 0 and then to 1 after a delay.
    • Various write and read operations are performed, and the FIFO's state, output, and flags are checked using if statements.
    • If any check fails, an error message is displayed using $display.
    • The simulation ends after all the test operations are completed using the $finish system task.

To run this testbench, you would need to compile and simulate it using a Verilog simulator like ModelSim, Quartus, Vivado, or any other Verilog-compatible tool. The testbench will apply the specified sequences of write and read operations and verify that the FIFO behaves as expected.

2.3 Add fsdb dump to testbench

在以上生成的testbench中,没有波形dump语句,这个后续仿真调试肯定是需要的,所以:

Prompt:

I think you'd better add fsdb waveform dump statements to the testbench

Response:

Understanding your suggestion, it seems you are proposing to incorporate fsdb waveform dump statements into a testbench for better signal tracing and debugging in a hardware design or verification environment. Fsdb (Fast Signal Database) is commonly used in EDA (Electronic Design Automation) tools for capturing and visualizing signal behavior during simulation.

Here’s how you might approach adding fsdb waveform dump statements to a testbench:

  1. Identify Key Signals: First, determine which signals in your design are critical for debugging. This could include input signals, internal states, and output signals.

  2. Incorporate Dump Statements: In your testbench code, you will need to add specific commands or function calls to dump these signals to an fsdb file. The exact syntax depends on the simulation tool you are using (e.g., ModelSim, Questasim, VCS, etc.).

    For example, if you are using a tool that supports SystemVerilog and fsdb dumping through a specific library or API, your code might look something like the code segment shown below.
    Alternatively, some tools may require you to configure the simulation environment or use specific directives in your testbench to enable fsdb dumping.

  3. Configure Simulation Tool: Ensure that your simulation tool is configured to generate fsdb files. This may involve setting environment variables, command-line options, or modifying simulation scripts.

  4. Run Simulation: Execute your testbench with the added fsdb dump statements. The simulation tool should now capture the specified signals and store them in an fsdb file.

  5. Analyze Fsdb File: Use a compatible waveform viewer or debugger to load and analyze the fsdb file. This will allow you to visualize the signal behavior and debug your design.

Keep in mind that the specific implementation details will vary depending on the simulation tool and language you are using. Therefore, it is essential to consult the documentation for your specific EDA tool to understand how to properly incorporate fsdb waveform dump statements into your testbench.

// Assuming 'fsdb_dump' is a predefined function or task for dumping signals  
initial begin  
    fsdb_dump("signal_dump.fsdb"); // Start dumping signals to fsdb file  
    // Add dump commands for specific signals here  
    // For instance: fsdb_dump_signal(signal_name);  
    // (Note: The exact function name and usage may differ based on the tool)  
    // Wait for the simulation to end  
    wait(forever);  
end

大模型balabala说了一大堆,看上去对fsdb波形及其dump是有一定了解的,但是似乎并不知道verilog中用于fsdb waveform dump的语句,所以比较保守地只给出了以上几行示意性的伪代码。。。这个就没啥意义了,好在也比较简单,自己手动添加了以下代码:

    initial
    begin
        if($test$plusargs("fsdb")) 
        begin
            $fsdbDumpfile("./tb_top.fsdb");
            $fsdbDumpSVA(0,tb_top);
            $fsdbDumpvars(0,tb_top);
        end
    end

3. 仿真与调试

        写了个脚本对以上设计和testbench进行仿真和调试。

3.1 RTL中的语法问题

        一上来编译报告rtl中有错误:

        说的是case语句用的“_”,这个的本意是应该是用于表示通配符,即对应输入数据不管是什么都可以。其实我也不知道(System)verilog中这种意图应该怎么描述,也懒得去查了,所以就请大模型来回答这个问题:

但是,这个问题似乎并不容易表述(或许只是我的表述方式),反正,来回交互了好几轮,大模型始终没有理解我的意思。最后,我问:

Not what I expected. I mean codes segement like below, is it correct?

always @(*) begin

        case (sel)

        4'b110x: result = 1'b1; // Matches 1100 or 1101

        4'b1110: result = 1'b1; // Matches 1110

        4'b1111: result = 1'b1; // Matches 1111

        default: result = 1'b0; // Matches any other value endcase end

这回大模型终于搞明白了,给了我一个比较像样的回复:

In Verilog, the case statement does not support the use of wildcards like x in the way you might be used to in regular expressions or some other programming languages. The case statement in Verilog requires exact binary, octal, decimal, or hexadecimal matches for its branches.

However, you can achieve a similar effect using a combination of logical operations within the case statement or by using the casez (case with don't cares) or casex (case with don't cares and hexadecimal) statements, which do support the use of z (high-impedance state, treated as a don't care) and x (unknown value, also treated as a don't care) respectively.

Here's how you could rewrite your code using the casez statement to allow for the wildcard behavior you're looking for:

always @(*) begin  
    casez (sel)  
        4'b110z: result = 1'b1; // Matches 1100 or 1101 (z is a don't care)  
        4'b1110: result = 1'b1; // Matches 1110  
        4'b1111: result = 1'b1; // Matches 1111  
        default: result = 1'b0; // Matches any other value  
    endcase  
end

In this code:

  • The casez statement allows the use of z to represent a don't care bit. This means that any value (0 or 1) in the position of z will match the pattern.
  • The pattern 4'b110z will match both 4'b1100 and 4'b1101 because the least significant bit is a don't care.
  • The other patterns (4'b1110 and 4'b1111) match exactly as specified.
  • The default case handles any other value of sel.

This should achieve the behavior you're looking for in your code.

看上去好像说得通,就用这个代码段替换掉了原始代码段,这次编译通过了。

3.2 testbench的问题        

以上rtl中的语法问题解决了后,仿真倒是能够跑起来了(当然仿真脚本还是折腾了一会儿),但是报告错误如下:

FIFO is not empty (expected).
Error: dout should be 8'hBB.
Error: dout should be 8'hCC.
Error: FIFO should be full.
Error: dout should be 8'hFF.
Error: dout should be 8'h00.
$finish called from file "tb_top.sv", line 108.
$finish at simulation time                  410

 把波形打开看了看:

好像看起来也挺正常啊。。。至少没有出现什么X态之类的东西。 

琢磨了一会儿,好像看出点名堂来了,testbench中所有的驱动信号至少有两个问题:

(1) 都是异步产生的。这个问题不致命,但是没有必要。同步设计的验证时用同步信号驱动更简单明了。

(2) wr_en和rd_en的脉冲宽度控制不对。第一次连续写三个数据的操作只是恰好正确,然后接下来两次读操作,

        // Read data from FIFO  
        #10 rd_en = 1;  
        #10 if (dout != 8'hAA) $display("Error: dout should be 8'hAA.");  
        #10 rd_en = 0;  
  
        #10 rd_en = 1;  
        #10 if (dout != 8'hBB) $display("Error: dout should be 8'hBB.");  
        #10 rd_en = 0;  

以上写法所得到的第一个rd_en的宽度其实是20ns,而工作时钟周期是10ns,因为该脉冲覆盖了两个时钟上升沿,所以实际上发生了两次读操作。这样的话,后面的动作序列就完全错位了。。。

搞清楚出错原因后,解决就比较简单了。最好是全部激励信号改为时钟同步驱动,但是如上所述这个不是致命的,为了节约时间暂时就不改了。以上语句的根本问题在于rd_en deassert与rd_en assert之间还插入了一条判断语句,而该判断语句前面也有一个延时操作。直接的解决方案是将判断语句前面的延时操作删除,或者将rd_en de-assert语句放到前面去,or both。比如说如下修改后,这个问题就解决了。

// Read data from FIFO  
#10 rd_en = 1;  
#10 rd_en = 0;  
    if (dout != 8'hAA) $display("Error: The 1st read: dout should be 8'hAA.");  
  
#10 rd_en = 1;  
#10 rd_en = 0;  
    if (dout != 8'hBB) $display("Error: The 2nd read: dout should be 8'hBB.");  

后面的wr_en和rd_en的脉冲宽度按同样方式进行修改后,验证就通过了。

当然这个testbench只执行了简单的验证操作,要进行同步FIFO的完备的验证,估计不能指望大模型,还得自己花点功夫进行testcase设计。

3.3 RTL中empty/full状态标志逻辑问题

进一步测试发现,原始RTL代码中empty和full标志的逻辑有问题。

比如说,当FIFO_DEPTH=16时,连续写入16个数据,一方面full信号没有拉起来,另一方面empty信号反而(在写入第一个数据后拉低之后)在写入第16个数据后被拉低了。。。

经分析后错误的原因如下所述。

3.3.1 full generation logic

首先,full信号的生成逻辑有问题:

    // FIFO full flag  
    assign full = (count == FIFO_DEPTH);  

在该实现中count其实是用于计数FIFO中所剩下的有效数据。但是verilog中的计数是从0开始,所以以上条件应该是(count == (FIFO_DEPTH-1))。 

3.3.2 read empty and write full protection

其次,更为严重的问题在于在full时没有防止进一步写入的机制,以及在empty时没有防止读取的机制。

当前代码中,在full(count == 15)时继续写入的话,count又变回0。同理,empty时继续读的话,count也会从0变为15。这样的动作显然不是所想看到的。

当然,这只是个简单的设计。可以要求读写控制方管理读写保护控制,即在full时不写入,在empty不读取。而更为robust的设计则是比如说full时写入的话不发生实际写操作同时反馈出错信号;在empty时读取的话不发生实际读操作,同时反馈出错信号。这个修改起来稍微麻烦了一点,超出了本文所有讨论的范围,这里就不再赘述。

4. 小结

        大模型针对简单的通用的功能模块能生成一些verilog代码,但是不能完全采信,需要仔细验证,文责自负。当然,有些问题有可能通过给更详细的生成需求来解决。另外,该实验用的是免费模型,版本稍低,如果用付费(VIP)版本是不是应该有更高质量一点的生成呢?

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

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

相关文章

VS Code创建VUE项目(一)工具安装与项目创建

一.安装与配置npm 1.下载安装Node.js 安装Node.js 下载地址&#xff1a; Node.js — 在任何地方运行 JavaScript (nodejs.org)或下载 | Node.js 中文网 下载后一步步安装就好&#xff08;安装过程基本一路直接“NEXT”就可以了&#xff0c;直到Finished&#xff09;&#x…

第十五届蓝桥杯C/C++学B组(解)

1.握手问题 解题思路一 数学方法 50个人互相握手 &#xff08;491&#xff09;*49/2 &#xff0c;减去7个人没有互相握手&#xff08;61&#xff09;*6/2 答案&#xff1a;1024 解题思路二 思路&#xff1a; 模拟 将50个人从1到50标号&#xff0c;对于每两个人之间只握一…

内嵌服务器Netty Http Server

内嵌式服务器不需要我们单独部署&#xff0c;列如SpringBoot默认内嵌服务器Tomcat,它运行在服务内部。使用Netty 编写一个 Http 服务器的程序&#xff0c;类似SpringMvc处理http请求那样。举例&#xff1a;xxl-job项目的核心包没有SpringMvc的Controller层&#xff0c;客户端却…

李德仁院士携实验室及大势文旅团队参加“湖北旅游、武当突破”名家谈,分享数智文旅发展新经验

10月12日上午&#xff0c;2024世界武当太极大会在湖北省十堰市武当山盛大开幕。 2023年国家科学技术最高奖获得者、中国科学院、中国工程院院士、武汉大学李德仁教授携测绘遥感信息工程国家重点实验室&#xff08;后简称“实验室”&#xff09;团队以及大势智慧文旅团队&#…

gcc学习

理论 在使用 GCC (GNU Compiler Collection) 进行 C 或 C 程序的编译时&#xff0c;可以将整个过程分为四个主要阶段&#xff1a;预处理、编译、汇编和链接。下面是每个阶段的命令示例&#xff1a; 1. 预处理-E 预处理阶段会处理所有的预处理指令&#xff08;如 #include 和…

Qt消息对话框

问题对话框 对应API [static] QMessageBox::StandardButton QMessageBox::question( QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons StandardButtons(Yes | No), QMessageBox::StandardButton defaultButt…

「Java服务」快速接入SkyWalking方法指南

一、背景 背景&#xff1a;Apache SkyWalking 是一个开源的分布式应用性能监控&#xff08;APM&#xff09;系统&#xff0c;主要用于监控微服务、云原生和容器化应用的性能。接入SkyWalking可以排查以智能投放服务为主的服务响应问题 技术架构 SkyWalking 的核心架构包括以…

【开源物联网平台】Fastbee数据库持久层架构

目录 一&#xff0c;数据库持久层架构 二&#xff0c;数据库组件 2.1 Druid 2.2 MyBatis-Plus 2.3 dynamic-datasource 2.4 ShardingSphere 一&#xff0c;数据库持久层架构 二&#xff0c;数据库组件 2.1 Druid Druid是Java语言中最好的数据库连接池。Druid能够提供强…

Chrome与Firefox浏览器HTTP自动跳转HTTPS的解决方案

一、背景介绍 随着网络安全意识的不断提高&#xff0c;越来越多的网站开始采用HTTPS协议&#xff0c;以确保数据传输的安全性。然而&#xff0c;有时用户在浏览网页时&#xff0c;可能会遇到HTTP请求被自动跳转至HTTPS的情况导致网站打不开&#xff0c;提示安全问题&#xff0…

android——自定义控件(不停变化的textview、开关switch、动画效果的打勾)

一、从开始数字到结束数字&#xff0c;不断变化 import android.animation.TypeEvaluator; import android.animation.ValueAnimator; import android.content.Context; import android.util.AttributeSet; import android.view.animation.AccelerateDecelerateInterpolator;i…

深度学习实战94-基于图卷积神经网络GCN模型的搭建以及在金融领域的场景

大家好,我是微学AI,今天给大家介绍一下深度学习实战94-基于图卷积神经网络GCN模型的搭建以及在金融领域的场景。文章首先介绍了GCN模型的原理及模型结构,随后提供了数据样例,并详细展示了实战代码。通过本文,读者可以深入了解GCN模型在金融场景下的应用,同时掌握代码的具…

使用标注工具并跑通官方yolov8分割segment自己的数据集

1.下载标注工具用于打标签 使用标注工具&#xff0c;后面会用到智能标注 点击 创建AI多边形后命令行就自动下载对应的模型 单机要选中的图像就行&#xff0c;就可以智能选中&#xff0c;双击设置标签 依次标注所有图片 &#xff0c;最后保存成json格式的文件 2.使用labelme2y…

关于mac下的nvm设置淘宝镜像源

1. 进入配置文件修改镜像源 vim ~/.bash_profile增加下面内容 export NVM_NODEJS_ORG_MIRRORhttps://npmmirror.com/mirrors/node/2. 查看远程node镜像 nvm ls-remote3. 下载镜像 nvm install 14.17.64. 使用镜像 nvm use 14.17.6

总台戏曲探访类创新节目《风味梨园》开播 探寻一座城市的戏曲文化地图

戏曲艺术犹如一颗璀璨的明珠&#xff0c;承载着中华民族千年的历史文化底蕴&#xff0c;以其独有的艺术魅力&#xff0c;如悠扬的旋律、精湛的表演&#xff0c;深深吸引着无数观众。而每一座城市隐匿其后的美食文化&#xff0c;恰似一首动人的诗篇&#xff0c;代表着人们对美好…

2013年国赛高教杯数学建模A题车道被占用对城市道路通行能力的影响解题全过程文档及程序

2013年国赛高教杯数学建模 A题 车道被占用对城市道路通行能力的影响 车道被占用是指因交通事故、路边停车、占道施工等因素&#xff0c;导致车道或道路横断面通行能力在单位时间内降低的现象。由于城市道路具有交通流密度大、连续性强等特点&#xff0c;一条车道被占用&#x…

数学建模算法与应用 第11章 偏最小二乘回归及其方法

目录 11.1 偏最小二乘回归概述 11.2 Matlab 偏最小二乘回归命令 Matlab代码示例&#xff1a;偏最小二乘回归 11.3 案例分析&#xff1a;化学反应中的偏最小二乘回归 Matlab代码示例&#xff1a;光谱数据的PLS回归 习题 11 总结 偏最小二乘回归&#xff08;Partial Least …

MySQL 【日期】函数大全(三)

DATEOFYEAREXTRACTFROM_DAYSFROM_UNIXTIMEHOURLAST_DAYLOCALTIMELOCALTIMESTAMP 1、DATEOFYEAR DATEOFYEAR(expr) &#xff1a;返回一个从 1 到 366 代表给定日期是一年中的第几天的数字。 如果指定的表达式不是一个合法的日期或者日期时间&#xff0c;DAYOFYEAR() 函数将返回…

无功补偿设备在室内及室外安装的区别

无功补偿设备在室内和室外的安装存在多方面的区别&#xff0c;包括环境条件、设备选择、安装要求以及维护方式。下面详细介绍两者的区别及相应的注意事项。 一、环境条件的差异 1、室内安装 温度和湿度&#xff1a;相对受控&#xff0c;温度变化较小&#xff0c;湿度可调节&…

k8s的部署和安装

k8s的部署和安装 一、Kubernets简介及部署方法 1.1 应用部署方式演变 在部署应用程序的方式上&#xff0c;主要经历了三个阶段&#xff1a; 传统部署&#xff1a;互联网早期&#xff0c;会直接将应用程序部署在物理机上 优点&#xff1a;简单&#xff0c;不需要其它技术的参…

STM32传感器模块编程实践(六) 1.8寸液晶屏TFT LCD彩屏简介及驱动源码

文章目录 一.概要二.TFT彩屏主要参数三.TFT彩屏参考原理图四.TFT彩屏模块接线说明五.模块SPI通讯协议介绍六.TFT彩屏模块显示1.显示英文字符串2.显示数字3.显示中文 七.TFT彩屏实现图片显示八.STM32单片机1.8寸 TFT LCD显示实验1.硬件准备2.软件工程3.软件主要代码4.实验效果 九…