当前位置:网站首页>吃透Chisel语言.17.Chisel模块详解(四)——用函数实现轻量级模块
吃透Chisel语言.17.Chisel模块详解(四)——用函数实现轻量级模块
2022-07-19 13:23:00 【github-3rr0r】
Chisel模块详解(四)——用函数实现轻量级模块
前面三篇文章我们学习了模块的实现语法、模块嵌套以及模块之间的连接方法,一般来说模块是Chisel中构造硬件描述的基本方法。但是Chisel中的模块和Verilog这类语言一样,定义模块会需要很多样板代码,又是从Module
拓展,又是定义IO
接口的,实例化和连接的时候又很费劲。不过Chisel中还是有简单的方法来定义轻量级模块的,那就是使用函数来实现。这一篇文章就讲讲如何用函数实现轻量级模块。
函数实现轻量级组合电路
Scala函数可以接受Chisel类型的参数并返回生成的硬件,举一个简单的例子,还是加法器,用Chisel的模块来实现是这样的:
class adder extends Module {
val io = IO(new Bundle {
val x = Input(UInt(32.W))
val y = Input(UInt(32.W))
val z = Output(UInt(32.W))
})
z := x + y
}
然后使用adder
模块的使用就用new
实例化,然后用Module
封装,再把它的输入输出和要使用adder
的信号连接起来,比如:
class testModule extends Module {
val io = IO(new Bundle {
val a = Input(UInt(32.W))
val b = Input(UInt(32.W))
val out = Output(UInt(32.W))
})
val adder = Module(new adder())
adder.io.x := io.a
adder.io.y := io.b
io.out := adder.io.z
}
生成的Verilog代码如下:
module adder(
input [31:0] io_x,
input [31:0] io_y,
output [31:0] io_z
);
assign io_z = io_x + io_y; // @[hello.scala 13:18]
endmodule
module test(
input clock,
input reset,
input [31:0] io_a,
input [31:0] io_b,
output [31:0] io_out
);
wire [31:0] adder_io_x; // @[hello.scala 22:23]
wire [31:0] adder_io_y; // @[hello.scala 22:23]
wire [31:0] adder_io_z; // @[hello.scala 22:23]
adder adder ( // @[hello.scala 22:23]
.io_x(adder_io_x),
.io_y(adder_io_y),
.io_z(adder_io_z)
);
assign io_out = adder_io_z; // @[hello.scala 25:12]
assign adder_io_x = io_a; // @[hello.scala 23:16]
assign adder_io_y = io_b; // @[hello.scala 24:16]
endmodule
其实是有点麻烦的,而且就这还整了个模块嵌套,其实我们可以用函数来生成一个adder
:
def adder (x: UInt, y: UInt) = {
x + y
}
这个函数的参数是两个Chisel的UInt
,返回值是x + y
,现在可以这么生成并使用加法器:
class testModule extends Module {
def adder (x: UInt, y: UInt) = {
x + y
}
val io = IO(new Bundle {
val a = Input(UInt(32.W))
val b = Input(UInt(32.W))
val out = Output(UInt(32.W))
})
val out = adder(io.a, io.b)
io.out := out
}
生成的Verilog代码如下:
module testModule(
input clock,
input reset,
input [31:0] io_a,
input [31:0] io_b,
output [31:0] io_out
);
assign io_out = io_a + io_b; // @[hello.scala 18:11]
endmodule
非常简洁,没有模块的嵌套,毕竟加法器这种组件还用个模块有点太奢侈的。
这就是轻量级模块,而adder
函数就是个硬件生成器。在展开的时候这个函数不会执行加法操作,而是创建了一个加法器的硬件实例。当然了,这里加法器的例子是刻意选取的简单例子,Chisel已经定义了加法器函数,也就是+(that:UInt)
运算符。
函数实现轻量级有状态电路
函数作为轻量级的硬件生成器,还可以包含状态,比如寄存器。下面的例子会返回一个单周期延迟模块(也就是寄存器):
def delay(x : UInt) = RegNext(x)
如果函数体只有一行的话,我们可以省略大括号,然后和函数写到一行里面。
我们现在可以通过以这个函数为参数调用这个函数构造一个二周期延迟模块:
class testModule extends Module {
def delay(x : UInt) = RegNext(x)
val io = IO(new Bundle {
val delIn = Input(UInt(32.W))
val delOut = Output(UInt(32.W))
})
// 调用两次delay
io.delOut := delay(delay(io.delIn))
}
生成的Verilog代码如下:
module testModule(
input clock,
input reset,
input [31:0] io_delIn,
output [31:0] io_delOut
);
reg [31:0] io_delOut_REG; // @[hello.scala 17:34]
reg [31:0] io_delOut_REG_1; // @[hello.scala 17:34]
assign io_delOut = io_delOut_REG_1; // @[hello.scala 24:15]
always @(posedge clock) begin
io_delOut_REG <= io_delIn; // @[hello.scala 17:34]
io_delOut_REG_1 <= io_delOut_REG; // @[hello.scala 17:34]
end
endmodule
可以看到,构造的模块中有两个寄存器,输入会在另两个周期后变成输出。不过这个例子跟加法器的例子一样的,RegNext()
也是Chisel中已经有了的函数,这里直接调用RegNext()
替代delay
是一样的。
上面的两个例子中,函数都是在Module
内部定义的,但是通常这种模块都会在不同的模块中用到,所以更好的办法是把这类实用函数都放到一个Scala对象里面,不管在哪个模块都可以调用。
结语
这一篇文章讲述的函数实现轻量级模块内容很简单,用好可以帮我们节约很多时间,在Scala对象中实现所有实用函数可以方便所有模块调用,大幅度提升编码效率。不过首先还是用好Chisel提供了的函数,避免重复造轮子,也方便Chisel编译器优化生成的硬件电路。除了Chisel中我们写的模块,我们可能还需要在我们的工程中使用现有的IP,而这些IP通常是用Verilog来写的,我们该如何使用这些IP呢?下一篇文章就详细说说。
边栏推荐
- 2022 Henan League game 2: Henan University of Technology
- 数据中台、商业智能BI业务访谈(一):行业和业务研究的准备
- Introduction to hotspot virtual machine
- Which is the best test management tool?
- 【SCADA案例】mySCADA助力Vib公司实现产线现代化升级
- 【综合笔试题】难度 4/5,字符处理的线段树经典运用
- Various template materials
- 广州深入开展经营性自建房安全整治“百日行动” 两个月排查房屋逾两百万栋
- [LSTM regression prediction] Based on MATLAB attention mechanism, LSTM time series regression prediction [including Matlab source code, 1992]
- About the development of chain game system (analysis and description of the principle of smart contract uplink) - Analysis and cases of the development principle of NFT chain game system
猜你喜欢
[introduction series of redis] get to know redis and the installation of redis
Fiddler set breakpoint (I)
Do you still have certificates to participate in the open source community?
Use octree structure to manage scenes
有奖互动|7.19数据库升舱计划实战峰会:行业领袖齐聚,他们因何而来?
Ceres之Powell’s Function
运营商的时代之旅:种下5.5G的魔豆,攀上数字化的天空花园
Ceres曲线拟合
“还是太年轻”,实习生花2分钟解决bug,老程序员的反应耐人寻味
【LSTM回归预测】基于matlab attention机制LSTM时间序列回归预测【含Matlab源码 1992期】
随机推荐
⾦融衍⽣产品是什么?
查询效率提升10倍!3种优化方案,帮你解决MySQL深分页问题
RISC-V MCU 物联网智能外卖柜
Only 22 years old! This Post-00 doctor plans to work in 985 universities!
What are the products of Rongyan?
Qu'est - ce que ça veut dire? Quels sont les détournements courants?
C语言深度剖析笔记1
网络原理(2)——网络开发
QGIS mosaic tile grid data
Fiddler set breakpoint (I)
ES6 —— 迭代器,生成器的基本使用
UVM中set/get_config_int/string/object与uvm_cofig_int/string/object的使用
PHP 匿名函数使用
学习笔记——C#字符串删除字符
Omnipeek 抓包工具
Assignment of golang interface variables and call of methods
浮点数探秘
In depth explanation of the development function of Multi Chain Wallet system and analysis of the development principle of multi currency wallet system
Pytorch, initialize tensor
Notes in October 2020