02-chisel-tutorial代码学习之组合逻辑

chisel-tutorial代码学习 - 02

wire类型变量的声明

在verilog中,使用wire关键字声明一个变量是wire类型,在chisel中也非常简单,我从wiki先贴过来一段话,

Constructing combinational logic blocks in Chisel is fairly straightforward; when you declare a val in Scala, it creates a node that represents the data that it is assigned to. As long as the value is not assigned to be a register type (explained later), this tells the Chisel compiler to treat the value as wire. Thus any number of these values can be connected and manipulated to produce the value that we want.

这段话的重点就是,在chisel中,如果某个变量没有被声明为register,那么chisel编译器就会把这个变量当作wire处理。

1-bit全加器

1-bit全加器是一个非常经典的组合逻辑电路,如下图所示,

1-bit全加器
那么使用chisel来写,就如下面代码所示,我直接从chisel-tutorial中贴过来,

package examples

import chisel3._

class FullAdder extends Module {
  val io = IO(new Bundle {
    val a    = Input(UInt(1.W))
    val b    = Input(UInt(1.W))
    val cin  = Input(UInt(1.W))
    val sum  = Output(UInt(1.W))
    val cout = Output(UInt(1.W))
  })

  // Generate the sum
  val a_xor_b = io.a ^ io.b
  io.sum := a_xor_b ^ io.cin
  // Generate the carry
  val a_and_b = io.a & io.b
  val b_and_cin = io.b & io.cin
  val a_and_cin = io.a & io.cin
  io.cout := a_and_b | b_and_cin | a_and_cin
}

代码val a_xor_b = io.a ^ io.b就声明了一个wire类型的变量,该wire型变量等于两个输入ab的异或。

注意下一行的:=,其实在第一篇笔记中我也提到,因为io.sum已经在io中被定义为val不可变的变量了,在scala中,就不能给io.sum重新赋值,因此chisel定义了操作符:=用于变量的重新赋值。记住一点,如果一个变量是首次定义,就使用=赋值,而如果这个变量已经被定义为val,那么就使用:=符号给变量重赋值。

这个代码比较简单,就是描述了图片中的电路行为。

位宽推断

第一篇笔记已经提到,chisel具有很强大的位宽推断功能,1-bit全加器编译生成的verilog代码如下所示,

module FullAdder(
  input   clock,
  input   reset,
  input   io_a,
  input   io_b,
  input   io_cin,
  output  io_sum,
  output  io_cout
);
  wire  a_xor_b = io_a ^ io_b; // @[FullAdder.scala 16:22]
  wire  a_and_b = io_a & io_b; // @[FullAdder.scala 19:22]
  wire  b_and_cin = io_b & io_cin; // @[FullAdder.scala 20:24]
  wire  a_and_cin = io_a & io_cin; // @[FullAdder.scala 21:24]
  wire  _T_1 = a_and_b | b_and_cin; // @[FullAdder.scala 22:22]
  assign io_sum = a_xor_b ^ io_cin; // @[FullAdder.scala 17:10]
  assign io_cout = _T_1 | a_and_cin; // @[FullAdder.scala 22:11]
endmodule

如果我把代码改成2-bit的全加器,代码如下所示,注意我只是修改了端口的位宽,模块内比如a_xor_b等变量的位宽还是没有指定的,

package examples

import chisel3._

class FullAdder extends Module {
  val io = IO(new Bundle {
    val a    = Input(UInt(2.W))
    val b    = Input(UInt(2.W))
    val cin  = Input(UInt(2.W))
    val sum  = Output(UInt(2.W))
    val cout = Output(UInt(2.W))
  })

  // Generate the sum
  val a_xor_b = io.a ^ io.b
  io.sum := a_xor_b ^ io.cin
  // Generate the carry
  val a_and_b = io.a & io.b
  val b_and_cin = io.b & io.cin
  val a_and_cin = io.a & io.cin
  io.cout := a_and_b | b_and_cin | a_and_cin
}

这样我们再次生成verilog代码看看,模块内的变量的位宽自动推断成了2-bit,注意并不是我声明端口为2-bit,内部变量就被推断为2-bit,而是内部变量的位宽按需推断,保证计算不出错,

module FullAdder(
  input        clock,
  input        reset,
  input  [1:0] io_a,
  input  [1:0] io_b,
  input  [1:0] io_cin,
  output [1:0] io_sum,
  output [1:0] io_cout
);
  wire [1:0] a_xor_b = io_a ^ io_b; // @[FullAdder.scala 16:22]
  wire [1:0] a_and_b = io_a & io_b; // @[FullAdder.scala 19:22]
  wire [1:0] b_and_cin = io_b & io_cin; // @[FullAdder.scala 20:24]
  wire [1:0] a_and_cin = io_a & io_cin; // @[FullAdder.scala 21:24]
  wire [1:0] _T_1 = a_and_b | b_and_cin; // @[FullAdder.scala 22:22]
  assign io_sum = a_xor_b ^ io_cin; // @[FullAdder.scala 17:10]
  assign io_cout = _T_1 | a_and_cin; // @[FullAdder.scala 22:11]
endmodule
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值