chisel多时钟域设计(注释)

2023-11-05

在数字电路中免不了用到多时钟域设计,尤其是设计异步FIFO这样的同步元件。

  • 在Verilog里,多时钟域的设计很简单,只需声明多个时钟端口,然后不同的always语句块根据需要选择不同的时钟作为敏感变量即可。
  • 在Chisel里,则相对复杂一些,因为这与Scala的变量作用域相关,而且时序元件在编译时都是自动地隐式跟随当前时钟域

本章将介绍多时钟域设计的语法,这其实很简单。

一、没有隐式端口的模块

继承自Module的模块类会获得隐式的全局时钟与同步复位信号,即使在设计中用不上它们也没关系。如果读者确实不喜欢这两个隐式端口,则可以选择继承自RawModule,这样在转换成Verilog时就没有隐式端口。它在chisel3包里,也是UserModule类的别名

这样的模块一般用于纯组合逻辑。在类内顶层不能出现使用时钟的相关操作(这里之所以说顶层,是因为还会存在自定义时钟域和复位域),比如定义寄存器(因为寄存器是时序元件,需要用到时钟和复位信号),否则会报错没有隐式端口。例如:

// module.scala
package test
 
import chisel3._
import chisel3.experimental._
 
class MyModule extends RawModule {
  val io = IO(new Bundle {
    val a = Input(UInt(4.W))
    val b = Input(UInt(4.W))
    val c = Output(UInt(4.W))
  })
 
  io.c := io.a & io.b
}
 
object ModuleGen extends App {
  chisel3.Driver.execute(args, () => new MyModule)
}

它生成的Verilog代码为:

// MyModule.v
module MyModule(
  input  [3:0] io_a,
  input  [3:0] io_b,
  output [3:0] io_c
);
  assign io_c = io_a & io_b; // @[module.scala 13:8]
endmodule

RawModule也可以包含时序逻辑,但要使用多时钟域语法。

二、定义一个时钟域和复位域

chisel3包里有一个单例对象withClockAndReset(这点和原文不同,因为该单例对象已经移到了chisel3包里面),其apply方法定义如下:

def apply[T](clock: Clock, reset: Reset)(block: ⇒ T): T

该方法的作用就是创建一个新的时钟和复位域,作用范围仅限于它的传名参数的内部

class MultiClockModule extends Module {
   val io = IO(new Bundle {
   	   //注意不要忘记定义自定义的时钟和复位信号端口,
   	   //以前不定义,是因为隐式的时钟和复位信号会自动添加这两个端口
       val clockB = Input(Clock())
       val resetB = Input(Bool())
       val stuff = Input(Bool())
   })
   // 这个寄存器跟随当前模块的隐式全局时钟clock
   val regClock1 = RegNext(io.stuff)

   withClockAndReset(io.clockB, io.resetB) {
       // 在该花括号内,所有时序元件都跟随时钟io.clockB
       // 所有寄存器的复位信号都是io.resetB

       // 这个寄存器跟随io.clockB
       val regClockB = RegNext(io.stuff)
       // 还可以例化其它模块
       val m = Module(new ChildModule)
    }

   // 这个寄存器跟随当前模块的隐式全局时钟clock
   val regClock2 = RegNext(io.stuff)
}

注意不要忘记在IO中定义自定义的时钟域和复位域要用的时钟和复位信号的端口;使用隐式时钟和复位域时不用定义,是因为隐式的时钟和复位信号的端口会被自动添加。

因为第二个参数列表只有一个传名参数,所以可以把圆括号写成花括号,这样还有自动的分号推断。再加上传名参数的特性,尽管需要一个无参函数,但是可以省略书写“() =>”。所以,

withClockAndReset(io.clockB, io.resetB) {
    sentence1
    sentence2
    ...
    sentenceN
}

实际上相当于:

withClockAndReset(io.clockB, io.resetB)( () => (sentence1; sentence2; ...; sentenceN) )

这结合了Scala的柯里化、传名参数和单参数列表的语法特性,让DSL语言的自定义方法看上去就跟内建的while、for、if等结构一样自然,所以Scala很适合构建DSL语言。


读者再仔细看一看apply方法的定义,它的第二个参数是一个函数,同时该函数的返回结果也是整个apply方法的返回结果。也就是说,独立时钟域的定义里,最后一个表达式的结果会被当作函数的返回结果。可以用一个变量来引用这个返回结果,这样在独立时钟域的定义外也能使用。例如引用最后返回的模块:

class MultiClockModule extends Module {
   val io = IO(new Bundle {
       val clockB = Input(Clock())
       val resetB = Input(Bool())
       val stuff = Input(Bool())
   })
   
   val clockB_child = withClockAndReset(io.clockB, io.resetB) {
       Module(new ChildModule)
    }

   clockB_child.io.in := io.stuff  
} 

如果传名参数全都是定义,最后没有表达式用于返回,那么apply的返回结果类型自然就是Unit。此时,外部不能访问独立时钟域里的任何内容。例如把上个例子改成如下代码:

class MultiClockModule extends Module {
   val io = IO(new Bundle {
       val clockB = Input(Clock())
       val resetB = Input(Bool())
       val stuff = Input(Bool())
   })
   
   val clockB_child = withClockAndReset(io.clockB, io.resetB) {
       val m = Module(new ChildModule)
    }

   clockB_child.m.io.in := io.stuff  
} 

现在,被例化的模块不是作为返回结果,而是变成了变量m的引用对象,故而传名参数是只有定义、没有有用的返回值的空函数。如果编译这个模块,就会得到“没有相关成员”的错误信息:

[error] /home/esperanto/chisel-template/src/main/scala/module.scala:42:16: 
value m is not a member of Unit
[error]   clockB_child.m.io.in := io.stuff
[error]                ^ 

如果独立时钟域有多个变量要与外部交互,则应该在模块内部的顶层定义全局的线网,让所有时钟域都能访问。

注1:

注意,是定义在模块内部的顶层,不能定义在某一个时钟域内,否则外顶层和其他时钟域都无法访问

除了单例对象withClockAndReset,还有单例对象withClock和withReset,分别用于构建只有独立时钟和只有独立复位信号的作用域,三者的语法是一样的,具体可以参考下例。


下面再举一个例子来引出一些细节

package grammer

import chisel3._

class ChildModule extends Module {
  val io = IO(new Bundle{
    val in = Input(Bool())
    val clockChild = Input(Clock())
    val out = Output(Bool())
  })
  withClock(io.clockChild){
  	//该寄存器跟随时钟io.clockChild,隐式复位信号reset
    val regclock = RegNext(io.in,0.U)
    io.out := regclock
  }
}
class MultiClockTester extends Module {
   val io = IO(new Bundle {
   	   //注意不要忘记定义自定义的时钟和复位信号端口,
   	   //以前不定义,是因为隐式的时钟和复位信号会自动添加这两个端口
       val clockA = Input(Clock())
       val resetA = Input(Bool())
       val clockChild = Input(Clock())
       val resetB = Input(Bool())
       val stuff_in = Input(Bool())
       val stuff_out = Output(Bool())
       val outregClock = Output(Bool())
       val outregClockA = Output(Bool())
       val outregClockB = Output(Bool())
   })
   // 这个寄存器跟随当前模块的隐式全局时钟clock
   val regClock = RegNext(io.stuff_in,0.U)

   val clockA_child = withClockAndReset(io.clockA,io.resetA.asAsyncReset()) {
       // 在该花括号内,所有时序元件都跟随时钟io.clockA
       // 所有寄存器的复位信号都是io.resetA

       // 这个寄存器跟随io.clockA
       val regClockA = RegNext(io.stuff_in,0.U)

       regClock := regClockA
       io.outregClockA := regClockA

       Module(new ChildModule)
    }
    clockA_child.io.clockChild := io.clockChild
    clockA_child.io.in := io.stuff_in
    io.stuff_out := clockA_child.io.out

   withReset(io.resetB) {
       // 在该花括号内,所有时序元件都跟随时钟隐式时钟clock
       // 所有寄存器的复位信号都是io.resetB

       // 这个寄存器跟随clock
       val regClockB = RegNext(io.stuff_in,0.U)
       io.outregClock := regClock
       io.outregClockB := regClockB
    }
}

object MultiClockTester extends App {
  (new chisel3.stage.ChiselStage).emitVerilog(new MultiClockTester(), Array("--target-dir", "generated"))
}

生成的部分verilog代码如下:

module ChildModule(
  input   reset,
  input   io_in,
  input   io_clockChild,
  output  io_out
);
`ifdef RANDOMIZE_REG_INIT
  reg [31:0] _RAND_0;
`endif // RANDOMIZE_REG_INIT
  reg  REG; // @[MultiClockTester.scala 12:27]
  assign io_out = REG; // @[MultiClockTester.scala 13:12]
  always @(posedge io_clockChild or posedge reset) begin
    if (reset) begin
      REG <= 1'h0;
    end else begin
      REG <= io_in;
    end
  end
endmodule
module MultiClockTester(
  input   clock,
  input   reset,
  input   io_clockA,
  input   io_resetA,
  input   io_clockChild,
  input   io_resetB,
  input   io_stuff_in,
  output  io_stuff_out,
  output  io_outregClock,
  output  io_outregClockA,
  output  io_outregClockB
);
`ifdef RANDOMIZE_REG_INIT
  reg [31:0] _RAND_0;
  reg [31:0] _RAND_1;
  reg [31:0] _RAND_2;
`endif // RANDOMIZE_REG_INIT
  wire  clockA_child_reset; // @[MultiClockTester.scala 43:14]
  wire  clockA_child_io_in; // @[MultiClockTester.scala 43:14]
  wire  clockA_child_io_clockChild; // @[MultiClockTester.scala 43:14]
  wire  clockA_child_io_out; // @[MultiClockTester.scala 43:14]
  reg  regClock; // @[MultiClockTester.scala 31:26]
  reg  REG; // @[MultiClockTester.scala 38:31]
  reg  REG_1; // @[MultiClockTester.scala 54:31]
  ChildModule clockA_child ( // @[MultiClockTester.scala 43:14]
    .reset(clockA_child_reset),
    .io_in(clockA_child_io_in),
    .io_clockChild(clockA_child_io_clockChild),
    .io_out(clockA_child_io_out)
  );
  assign io_stuff_out = clockA_child_io_out; // @[MultiClockTester.scala 47:18]
  assign io_outregClock = regClock; // @[MultiClockTester.scala 55:23]
  assign io_outregClockA = REG; // @[MultiClockTester.scala 41:24]
  assign io_outregClockB = REG_1; // @[MultiClockTester.scala 56:24]
  assign clockA_child_reset = io_resetA; // @[MultiClockTester.scala 33:72]
  assign clockA_child_io_in = io_stuff_in; // @[MultiClockTester.scala 46:24]
  assign clockA_child_io_clockChild = io_clockChild; // @[MultiClockTester.scala 45:32]
  always @(posedge clock) begin
    if (reset) begin // @[MultiClockTester.scala 31:26]
      regClock <= 1'h0; // @[MultiClockTester.scala 31:26]
    end else begin
      regClock <= REG; // @[MultiClockTester.scala 40:17]
    end
    if (io_resetB) begin // @[MultiClockTester.scala 54:31]
      REG_1 <= 1'h0; // @[MultiClockTester.scala 54:31]
    end else begin
      REG_1 <= io_stuff_in; // @[MultiClockTester.scala 54:31]
    end
  end
  always @(posedge io_clockA or posedge io_resetA) begin
    if (io_resetA) begin
      REG <= 1'h0;
    end else begin
      REG <= io_stuff_in;
    end
  end
endmodule

注2:

从上面的例子中可以看出:

  • 一个寄存器只和它定义时所处的时钟域有关,即使在其他时钟域被赋值,那么它还是跟随自己的时钟。从regClock在顶层定义,在时钟域A中被赋值,然后verilog代码中regClock还是跟随隐式的clock时钟可以看出来。
  • 不同的时钟域,会生成不同的always块,它们的敏感变量不一样,都是自己时钟域的时钟信号。但是不同的复位域不会产生不同的always块,因为复位信号属于哪一个always块取决于它跟随哪一个时钟信号。如上例中的io_resetB,它就在always @(posedge clock)块中。
  • always块中使用的时钟和复位信号默认都是上升沿。
  • 时钟域是可以嵌套的,当前的时钟域会覆盖掉上一层的时钟域。隐式的时钟域属于最顶层的时钟域,当我们再自定义时钟域时,自定义的时钟域就会覆盖掉顶层隐式的时钟域。同理,我们还可以在自定义时钟域中再定义子时钟域。
  • 当使用withClock时,时序元件只跟随显式提供的时钟信号,复位信号仍然使用默认的;同理使用withReset时,时序元件只跟随显式提供的复位信号,时钟信号仍然使用默认的。这里的默认指的不一定是顶层的隐式时钟和复位信号,更准确的说是上一层时钟域的时钟或者复位信号。
  • 我们还可以在时钟域中例化其他模块,如ChildModule,该模块默认使用的是自己顶层的隐式时钟。但它也可以像顶层模块MultiClockTester一样,定义自己的时钟域,具体使用哪个时钟和复位信号就可以由顶层模块显式提供。

三、使用时钟负沿和低有效的复位信号

默认情况下,声明的时序元件都是以时钟的正沿和高有效的复位信号作为敏感变量,但是在多时钟域的语法里,可以改变其行为。

  • 复位信号比较简单,只需要加上取反符号或逻辑非符号。
  • 时钟信号稍微麻烦一些,需要先用asUInt方法把Clock类型转换成UInt类型,再用asBool转换成Bool类型,此时可以加上取反符号或逻辑非符号,最后再用asClock变回Clock类型。例如:
// negclkrst.scala
package test
 
import chisel3._
import chisel3.experimental._
 
class NegativeClkRst extends RawModule {
  val io = IO(new Bundle {
    val in = Input(UInt(4.W))
    val myClk = Input(Clock())
    val myRst = Input(Bool())
    val out = Output(UInt(4.W))
  })
  
  withClockAndReset((~io.myClk.asUInt.asBool).asClock, ~io.myRst) {
    val temp = RegInit(0.U(4.W))
    temp := io.in
    io.out := temp
  }
}
 
object NegClkRstGen extends App {
  chisel3.Driver.execute(args, () => new NegativeClkRst)
}

它生成的Verilog主要是:

// NegativeClkRst.v
module NegativeClkRst(
  input  [3:0] io_in,
  input        io_myClk,
  input        io_myRst,
  output [3:0] io_out
);
  wire  _T; // @[negclkrst.scala 14:32]
  wire  _T_2; // @[negclkrst.scala 14:22]
  wire  _T_3; // @[negclkrst.scala 14:47]
  wire  _T_4; // @[negclkrst.scala 14:56]
  reg [3:0] _T_5; // @[negclkrst.scala 15:23]
  assign _T = $unsigned(io_myClk); // @[negclkrst.scala 14:32]
  assign _T_2 = ~ _T; // @[negclkrst.scala 14:22]
  assign _T_3 = _T_2; // @[negclkrst.scala 14:47]
  assign _T_4 = ~ io_myRst; // @[negclkrst.scala 14:56]
  assign io_out = _T_5; // @[negclkrst.scala 17:12]
 
  always @(posedge _T_3) begin
    if (_T_4) begin
      _T_5 <= 4'h0;
    end else begin
      _T_5 <= io_in;
    end
  end
endmodule

四、示例:异步FIFO

在跨时钟域设计中,经常需要使用异步FIFO来同步不同时钟域的数据传输。下面是笔者自己编写的一个异步FIFO例子,数据位宽和深度都是参数化的,读、写地址指针的交互采用格雷码和两级寄存器采样,以便改善亚稳态。通过在Vivado 2018.3里综合后,可以得到以BRAM为存储器的FIFO。

// FIFO.scala
package fifo
 
import chisel3._
import chisel3.util._
import chisel3.experimental._
class FIFO(width: Int, depth: Int) extends RawModule {
  val io = IO(new Bundle {
    // write-domain
    val dataIn = Input(UInt(width.W))
    val writeEn = Input(Bool())
    val writeClk = Input(Clock())
    val full = Output(Bool())
    // read-domain
    val dataOut = Output(UInt(width.W))
    val readEn = Input(Bool())
    val readClk = Input(Clock())
    val empty = Output(Bool())
    // reset
    val systemRst = Input(Bool())
  })
  val ram = SyncReadMem(1 << depth, UInt(width.W))   // 2^depth
  val writeToReadPtr = Wire(UInt((depth + 1).W))  // to read clock domain
  val readToWritePtr = Wire(UInt((depth + 1).W))  // to write clock domain
  // write clock domain
  withClockAndReset(io.writeClk, io.systemRst) {
    val binaryWritePtr = RegInit(0.U((depth + 1).W))
    val binaryWritePtrNext = Wire(UInt((depth + 1).W))
    val grayWritePtr = RegInit(0.U((depth + 1).W))
    val grayWritePtrNext = Wire(UInt((depth + 1).W))
    val isFull = RegInit(false.B)
    val fullValue = Wire(Bool())
    val grayReadPtrDelay0 = RegNext(readToWritePtr)
    val grayReadPtrDelay1 = RegNext(grayReadPtrDelay0)
    binaryWritePtrNext := binaryWritePtr + (io.writeEn && !isFull).asUInt
    binaryWritePtr := binaryWritePtrNext
    grayWritePtrNext := (binaryWritePtrNext >> 1) ^ binaryWritePtrNext
    grayWritePtr := grayWritePtrNext
    writeToReadPtr := grayWritePtr
    fullValue := (grayWritePtrNext === Cat(~grayReadPtrDelay1(depth, depth - 1), grayReadPtrDelay1(depth - 2, 0)))
    isFull := fullValue
    when(io.writeEn && !isFull) {
      ram.write(binaryWritePtr(depth - 1, 0), io.dataIn)
    }
    io.full := isFull    
  }
  // read clock domain
  withClockAndReset(io.readClk, io.systemRst) {
    val binaryReadPtr = RegInit(0.U((depth + 1).W))
    val binaryReadPtrNext = Wire(UInt((depth + 1).W))
    val grayReadPtr = RegInit(0.U((depth + 1).W))
    val grayReadPtrNext = Wire(UInt((depth + 1).W))
    val isEmpty = RegInit(true.B)
    val emptyValue = Wire(Bool())
    val grayWritePtrDelay0 = RegNext(writeToReadPtr)
    val grayWritePtrDelay1 = RegNext(grayWritePtrDelay0)
    binaryReadPtrNext := binaryReadPtr + (io.readEn && !isEmpty).asUInt
    binaryReadPtr := binaryReadPtrNext
    grayReadPtrNext := (binaryReadPtrNext >> 1) ^ binaryReadPtrNext
    grayReadPtr := grayReadPtrNext
    readToWritePtr := grayReadPtr
    emptyValue := (grayReadPtrNext === grayWritePtrDelay1)
    isEmpty := emptyValue
    io.dataOut := ram.read(binaryReadPtr(depth - 1, 0), io.readEn && !isEmpty)
    io.empty := isEmpty
  }  
}
object FIFOGen extends App {
  chisel3.Driver.execute(args, () => new FIFO(args(0).toInt, args(1).toInt))
}

五、总结

本章介绍了如何用Chisel设计多时钟域电路,重点是学会apply方法的使用,以及对第二个参数列表的理解。要注意独立时钟域里只有最后的表达式能被作为返回值给变量引用,并被外部访问,其它的定义都是对外不可见的。

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

chisel多时钟域设计(注释) 的相关文章

  • 数字电路(三)最小项和最大项

    逻辑抽象和描述 把实际问题抽象成变量和逻辑函数根据逻辑函数绘制框图使用真值表或者自然语言描述函数表达式 最小项和最大项 最小项和最大项的定义SSOP和 sum 记法最大项 xff1a 下标和真值表行号一样 xff0c 进制转换值要取反 同一
  • 【课内学习】数字电路Flip-Flop

    本文仅供博主自己复习使用 xff0c 因此只记录了自己容易忘记的知识点 xff0c 并非成体系的整理 Latches and Flip Flops S R latch Why do we need this stupid drive equ
  • 【环境配置】基于Docker配置Chisel-Bootcamp环境

    文章目录 Chisel是什么 Chisel Bootcamp是什么 基于Docker配置Chisel Bootcamp 官网下载Docker安装包 Docker换源 启动Bootcamp镜像 常用docker命令 可能产生的问题 Chise
  • Chisel教程——14.(完结篇)Scala和Chisel中的数据类型

    完结篇 Scala和Chisel中的数据类型 完结篇开头的碎碎念 这是这个系列的最后一篇文章了 官方的Chisel Bootcamp中后面还有FIRRTL相关的内容 但设计一个RISC V CPU这样的目标 靠本系列文章讲述的内容已经足够了
  • 第二十五章 Chisel进阶——隐式参数的应用

    用Chisel编写的CPU 比如Rocket Chip RISCV Mini等 都有一个特点 就是可以用一个配置文件来裁剪电路 这利用了Scala的模式匹配 样例类 偏函数 可选值 隐式定义等语法 本章内容就是来为读者详细解释它的工作机制
  • chisel线网(wire)和寄存器(reg)详解(更新)

    主体内容摘自 https blog csdn net qq 34291505 article details 87714172 在Verilog里 模块内部主要有 线网 wire 和 四态变量 reg 两种硬件类型 它们用于描述数字电路的组
  • 超详细!基于Proteus的出租车计价器实现(数字电路课程设计)

    本文阐述基于Proteus 7 8的出租车计价器电路的实现 附具体电路的工程文件下载 工程文件下载链接 设计要求 里程测量精确到1 按起步价7元 3公里 起步价外按1 4元 公里进行计价 等候按1 4元 10分钟计算 具有里程显示 收费显示
  • QuartusII软件异常:Error: Top-level design entity " " is undefined

    使用Quartus进行数字电路设计时 遇到了下面的编译错误 Info Info Running Quartus II 64 Bit Analysis Synthesis Info Version 11 0 Build 157 04 27 2
  • 实时CPU设计

    Patmos with Chisel https github com t crest patmos
  • 竞争与冒险

    竞争与冒险 文章目录 1 竞争与冒险产生原因 2 判断电路是否存在竞争 冒险现象 3 消除竞争与冒险 1 竞争与冒险产生原因 观察以下门电路 Gate1为 非门 Gate2为 与门 实现了逻辑 F A A
  • Chisel基础之Scala

    前言 Scala is yet another programming language which supports common programming paradigms We chose to use it for several
  • Chisel(四)Scala语法 操作符

    学习更多相关知识 关注博主知乎账号 用户名Trustintruth https www zhihu com people suo yi xin 90 activities Scala追求的是纯粹的面向对象 不推荐不属于面向对象的基本类型及其
  • chisel相比verilog优势之一:复用特性

    0 绪论 世界由于人这个最大的无厘头变量 还是比技术本身复杂难懂很多 各种技术的兴起与发展总是有其背后的理由的 这篇文章是这个系列的第三篇文章 主要来说明Chisel比Verilog在某些方面具有优势的理由 换句话说 为什么要用Chisel
  • 74160同步置数法解析(以接成同步八进制计数器为例)

    我们先来看一下电路逻辑图 从中提取核心信息 将QD QC QB QA接成0010是为了配合LOAD引脚使用 以将74160的状态置为0010 计数器的最大状态为1001 当74160到达1001时 通过7400N与非门将LOAD引脚置为0
  • chisel-book-chinese

    chisel book chinese 蓝奏云地址 https wwu lanzoue com isdim08x8x5i
  • STM32 USB DP/DM内置的上下拉电阻阻值

    根据USB协议 工作在主机模式 USB DP DM下拉到GND 工作在设备模式 上拉到VCC DP上拉表示高全速设备 DM上拉表示低速设备 STM32在Device模式只支持高速或全速 图片来源于 STM32F407数据手册 红色为示意 实
  • 第二章 Scala入门——让你的代码跑起来

    一 Scala的安装方法 要使用Scala 首先需要保证已经安装好了Java 8 对于Linux操作系统 Java 8已经默认安装了 而使用Windows操作系统的用户 则需要在Java官网下载安装包进行安装 请在CMD PowerShel
  • 第二十章 Chisel基础——生成Verilog与基本测试

    经过前三章的内容 读者已经了解了如何使用Chisel构建一个基本的模块 本章的内容就是在此基础上 把一个Chisel模块编译成Verilog代码 并进一步使用Verilator做一些简单的测试 一 生成Verilog 前面介绍Scala的内
  • 输入延时(Input Delay)与输出延时(Output Delay)

    一 设置输入延时 Input Delay 1 不同的路径需要使用不同的约束 2 输入延时的定义 由下图可以看出Input Delay是以上游芯片的时钟发送沿为参考 上游的输出数据到达FPGA的外部输入端口之间的延迟 输入延迟 input d
  • Chisel3:对 Vector IO 的多位切片的部分分配

    可以对向量 IO 进行部分赋值 如下所示 import chisel3 class example 1 extends Module val io IO new Bundle val in1 Input Vec 4 Bool val out

随机推荐

  • PyQt5 组件之QSlider

    QSlider简介 QSlider控件提供一个垂直或者水平的滑动条 滑动条是一个用于控制有界值典型的控件 它允许用户沿水平或者垂直方向在某一范围内移动滑块 并将滑块所在的位置转换为一个合法范围内的整数值 有时候这中方式比输入数字或者使用Sp
  • 双系统如何在Centos7中添加GRUB2启动项

    GRUB2是Centos7的默认引导加载程序 它可以轻松地加载所有的Linux发行版和其他操作系统 它提供一个菜单显示所有的操作系统 GRUB2具有高级特性以及一些基本特性 使其在所有Linux上都有效 文内含长段代码可复制可往左滑 希望对
  • Docker保存镜像到本地并载入本地镜像文件

    目录 一 适用情况 二 镜像保存到本机 1 查看已有的镜像文件 2 将镜像保存为本地文件 保存指令一 保存指令二 测试根据镜像ID保存镜像 三 载入本地镜像 载入指令一 载入指令二 载入通过镜像ID保存的本地镜像 四 批量保存和载入镜像脚本
  • 全网最详细中英文ChatGPT-GPT-4示例文档-步骤指示智能生成从0到1快速入门——官网推荐的48种最佳应用场景(附python/node.js/curl命令源代码,小白也能学)

    从0到1快速入门步骤指示智能生成应用场景 Introduce 简介 setting 设置 Prompt 提示 Sample response 回复样本 API request 接口请求 python接口请求示例 node js接口请求示例
  • 内网Https 自签Https证书 配合Tomcat 实现内网Https详细图文

    转载地址 https www cnblogs com ChromeT p 11122480 html 目录 开始制作CA根证书 创建私钥 创建证书请求 生成CA自签证书 制作服务器证书 向 本地keystore 密钥库中导入证书 导入服务器
  • 结构方程模型_结构方程模型(SEM)到底有多厉害?

    什么是结构方程模型 结构方程模型是高级定量方法中最常见的统计方法之一 在社会科学以及经济 市场 管理等研究领域 有时需处理多个原因 多个结果的关系 或者会碰到不可直接观测的变量 即潜变量 这些都是传统的统计方法不能很好解决的问题 结构方程模
  • qt传指针

    1 传指针 需要获取并且初始化 2 接口函数应该指明其父窗口
  • 【MedusaSTears】记一次踏坑:EL表达式不支持正则_EL表达式使用函数一览表_手机/座机号码脱敏正则规则

    吃水不忘挖井人系列 EL表达式中使用函数 以下这俩正则应该都可 应对诸如 010 12345678 这种座机 以及 13312345678 这种手机号
  • 基于类属属性的多标记学习——含python代码

    本文的基本内容翻译自Lift Multi Label Learning with Label Specific Features 1 含部分本人的理解 最后附带了我复现的python代码的github链接 类属属性 所谓多标记学习是相对于单
  • 修改Nuget包默认存放路径

    默认情况下所有的Nuget包都会下载到C盘 目前我这边有几十个G的大小 这导致我C盘的c 教程容量越来越小 我们可以在Nuget config中修改package存放路径 Nuget config 在C Users UserName App
  • 解决 R 语言中遇到的奇异拟合错误(singular fit encountered)

    解决 R 语言中遇到的奇异拟合错误 singular fit encountered 在 R 语言中 当执行线性回归或拟合模型时 有时会遇到奇异拟合错误 singular fit encountered 的问题 这个错误表示拟合过程中出现了
  • 关于知识的理解与忘却

    关于知识的理解与忘却 在做项目的过程中 我会遇到一些难题 会通过baidu与google来解决 解决之后 我很少对这些知识进行总结 但是 将来又遇到这方面的知识时 我发现却很难再找到记忆中的那些文章 当初对于自己理解这些知识有很大影响的文章
  • 使用OpenCV,Python进行图像哈希(差分哈希 dHash)处理

    使用OpenCV Phthon进行图像哈希处理的一个重要应用是去除重复的图像 当你有多个相册的图片 进行合并时 so boring 有一些图片是重复的 肉眼来看太难删除了 图像哈希可以帮助你完美的解决这个问题 找到完全相同的图片 只保留一张
  • python最详细的安装与完全卸载

    一 python的安装 1 python下载 在网上 输入网址https www python org downloads 下载Windows最新的python程序 我电脑为64位 注意 不要下载32位的且尽可能不要下载3 6 x以上的版本
  • 虚幻4——蓝图在脚本之间的交互

    从虚幻3到虚幻4 之前都已经习惯了在脚本中写节点 然后在编辑器中供关卡师使用 所以对于这种开发模式 也不会有什么不适应的感觉 可视化编辑 也是以后游戏开发的重要的一环吧 但是国内游戏开发还没有这一种概念 对于关卡师 尤其懂游戏逻辑的 这是多
  • 算法 - 冒泡排序(Bubble_ Sort)

    在总结冒泡排序前 先从头开始 对冒泡排序 BubbleSort 进行一个系统性了解 冒泡排序法 又称交换排序法 是从观察水中的气泡变化构思而成的 原理是从第一个元素开始 比较相邻元素的大小 如果大小顺序不对 则进行两个数据的调换 就好像气泡
  • 基于mybatis的数据库脱敏

    背景 思路 实现 思考 背景 最近接到需求需要对数据库中的电话 身份证号等敏感信息进行脱敏加密处理 再加上之前面试时也被问到相关问题 所有在此记录 脱敏对象是数据库的字段 所以在数据库存取的出入口进行加解密操作是最合适的 项目中使用myba
  • 【T1】T1飞跃专业版修改账套名称

    问题描述 使用友加畅捷T1飞跃专业版的过程中 建立完账套后 无法从前台操作进行账套名称的修改 解决方法 打开数据库管理器 执行下述语句 进行修改 update master Sub List set ztname 新名称 where ztn
  • 偏导数及其几何意义

    在一元函数中 我们已经知道导数就是函数的变化 率 对于二元函数我们同样要研究它的 变化率 然 而 由于自变量多了一个 情况就要复杂的多 一 几何意义 在xOy平面内 当动点由P x0 y0 沿不同方向变化时 函数f x y 的变化快慢一般说
  • chisel多时钟域设计(注释)

    在数字电路中免不了用到多时钟域设计 尤其是设计异步FIFO这样的同步元件 在Verilog里 多时钟域的设计很简单 只需声明多个时钟端口 然后不同的always语句块根据需要选择不同的时钟作为敏感变量即可 在Chisel里 则相对复杂一些