当前位置:网站首页>Understand Chisel language. 33. Chisel advanced hardware generator (2) - Chisel combinational logic circuit generation: take BCD coding table as an example
Understand Chisel language. 33. Chisel advanced hardware generator (2) - Chisel combinational logic circuit generation: take BCD coding table as an example
2022-08-06 21:32:00 【github-3rr0r】
Chisel进阶之硬件生成器(二)——ChiselCombination logic circuit generation:以BCDTake the coding table as an example
In the previous article we learned about two types of variablesChisel之中的使用,然后分别介绍了Chisel中四种参数化的方法,对于我们构建可复用的模块有重大意义.这一部分的关键是将Chisel作为写硬件生成器的语言,而不仅仅是作为描述硬件的语言,这个参数化就是作为硬件生成器的开始.This article will introduce the example of a logical tableChisel中组合逻辑电路的生成,作为用Chisel写硬件生成器的例子.
Use logic tables to generate combinational logic
在Chisel中,We can generate combinational logic circuits by creating a logic table,利用的是Scala的Array转换来的Chisel的Vec.We might have a file with logic tables in it,Then we can read this logic table file in hardware generation.The following example demonstrates how to use itScala标准io库中的Source类来读取data.txt,data.txtThe file contains integer constants represented by text:
import chisel3._
import scala.io.Source
class FileReader extends Module {
val io = IO(new Bundle {
val address = Input(UInt(8.W))
val data = Output(UInt(8.W))
})
val array = new Array[Int](256)
var idx = 0
// 读取文件到Scala数组
val source = Source.fromfile("data.txt")
for (line <- source.getLines()) {
array(idx) = line.toInt
idx += 1
}
// 把ScalaInteger arrays are converted toChisel UInt的Vec
val table = VecInit(array.map(_.U(8.W)))
// 使用真值表
io.data := table(io.address)
}
The above code as a whole looks very understandable,But there is one thing that is really scary:
val table = VecInit(array.map(_.U(8.W)))
Scala中的ArrayCan be implicitly converted to a sequence(Seq),And the sequence is supportedmap函数的.mapA function calls a function on each element of the sequence,It then returns a sequence of return values from these function calls.然后再看,我们的函数是_.U(8.W),乍一看,This can also be a function?This function means this:_Indicates that each comes fromScala数组的Int值,然后基于这个_调用Scala整数到Chisel的UIntLiteral conversion function,宽度为8位.Finally based on this sequence generated,用Chisel对象VecInit创建一个Chisel中的的Vec.
We can use this fromScalasequence bandChisel的Vecinitialization to represent a message,Then send to serial port.The following code puts a standard"Hello World!"从Scala的String转换成了Chisel的Vec:
val msg = "Hello World!"
val text = VecInit(msg.map(_.U))
val len = msg.length.U
Scala中的String也可以用作序列,因此map函数可以在每个Scala的字符Char上执行Chisel的.U转换.This string of code is taken from the example of the serial port used to send the welcome message,There will be a dedicated article later on the implementation of this serial port.
我们可以利用Scalafull capability to generate combinatorial logic(or a logical table),For example, generate a table of trigonometric functions represented by fixed-point constants,Constant used to calculate the digital filter,Or write a small oneScalaassembler to generate the ANDChiselcode written for the microprocessor.All of these functions are in the same codebase(同一个语言)中,And it can be executed when the hardware is generated.
BCDExample of a logical table
A classic example of combinatorial logic is binary numbersBCD(Binary-Coded Decimal,二进码十进数)表示的转换.BCDUsed to use every digit of a number represented in decimal4位二进制数来表示.比如,十进制数13用二进制表示是1101,而BCD中分别对1和3进行编码,即为00010011.BCDEncodings allow numbers to be represented in decimal,More user friendly than hexadecimal representation.
If it is a traditional hardware description language,比如Verilog和VHDL,We need another scripting language or programming language to generate a similar logic table.比如我们可以用JavaThe program computes the binary conversion to BCD的逻辑表,然后JavaProgram printouts can be used for projectsVerilog代码.这么写的话,JavaThe code probably has to be written100行,Most of these codes are used for generationVerilog字符串,And the critical part is only two lines.
但是用Chisel的话,情况就完全不同了,We can directly generate the logic table as part of the hardware generation.The following code is usedChiselImplemented binary(0到99)到BCDThe generation of a logical table of transformations:
import chisel3._
class BcdTable extends Module {
val io = IO(new Bundle {
val address = Input(UInt(8.W))
val data = Output(UInt(8.W))
})
val table = Wire(Vec(100, UInt(8.W)))
// 二进制转换为BCD
for (i <- 0 until 100) {
table(i) := (((i/10)<<4) + i%10).U
}
io.data := table(io.address)
}
生成的Verilog代码如下:
module BcdTable(
input clock,
input reset,
input [7:0] io_address,
output [7:0] io_data
);
wire [7:0] _GEN_1 = 7'h1 == io_address[6:0] ? 8'h1 : 8'h0; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_2 = 7'h2 == io_address[6:0] ? 8'h2 : _GEN_1; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_3 = 7'h3 == io_address[6:0] ? 8'h3 : _GEN_2; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_4 = 7'h4 == io_address[6:0] ? 8'h4 : _GEN_3; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_5 = 7'h5 == io_address[6:0] ? 8'h5 : _GEN_4; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_6 = 7'h6 == io_address[6:0] ? 8'h6 : _GEN_5; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_7 = 7'h7 == io_address[6:0] ? 8'h7 : _GEN_6; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_8 = 7'h8 == io_address[6:0] ? 8'h8 : _GEN_7; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_9 = 7'h9 == io_address[6:0] ? 8'h9 : _GEN_8; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_10 = 7'ha == io_address[6:0] ? 8'h10 : _GEN_9; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_11 = 7'hb == io_address[6:0] ? 8'h11 : _GEN_10; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_12 = 7'hc == io_address[6:0] ? 8'h12 : _GEN_11; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_13 = 7'hd == io_address[6:0] ? 8'h13 : _GEN_12; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_14 = 7'he == io_address[6:0] ? 8'h14 : _GEN_13; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_15 = 7'hf == io_address[6:0] ? 8'h15 : _GEN_14; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_16 = 7'h10 == io_address[6:0] ? 8'h16 : _GEN_15; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_17 = 7'h11 == io_address[6:0] ? 8'h17 : _GEN_16; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_18 = 7'h12 == io_address[6:0] ? 8'h18 : _GEN_17; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_19 = 7'h13 == io_address[6:0] ? 8'h19 : _GEN_18; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_20 = 7'h14 == io_address[6:0] ? 8'h20 : _GEN_19; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_21 = 7'h15 == io_address[6:0] ? 8'h21 : _GEN_20; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_22 = 7'h16 == io_address[6:0] ? 8'h22 : _GEN_21; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_23 = 7'h17 == io_address[6:0] ? 8'h23 : _GEN_22; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_24 = 7'h18 == io_address[6:0] ? 8'h24 : _GEN_23; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_25 = 7'h19 == io_address[6:0] ? 8'h25 : _GEN_24; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_26 = 7'h1a == io_address[6:0] ? 8'h26 : _GEN_25; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_27 = 7'h1b == io_address[6:0] ? 8'h27 : _GEN_26; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_28 = 7'h1c == io_address[6:0] ? 8'h28 : _GEN_27; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_29 = 7'h1d == io_address[6:0] ? 8'h29 : _GEN_28; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_30 = 7'h1e == io_address[6:0] ? 8'h30 : _GEN_29; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_31 = 7'h1f == io_address[6:0] ? 8'h31 : _GEN_30; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_32 = 7'h20 == io_address[6:0] ? 8'h32 : _GEN_31; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_33 = 7'h21 == io_address[6:0] ? 8'h33 : _GEN_32; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_34 = 7'h22 == io_address[6:0] ? 8'h34 : _GEN_33; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_35 = 7'h23 == io_address[6:0] ? 8'h35 : _GEN_34; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_36 = 7'h24 == io_address[6:0] ? 8'h36 : _GEN_35; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_37 = 7'h25 == io_address[6:0] ? 8'h37 : _GEN_36; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_38 = 7'h26 == io_address[6:0] ? 8'h38 : _GEN_37; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_39 = 7'h27 == io_address[6:0] ? 8'h39 : _GEN_38; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_40 = 7'h28 == io_address[6:0] ? 8'h40 : _GEN_39; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_41 = 7'h29 == io_address[6:0] ? 8'h41 : _GEN_40; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_42 = 7'h2a == io_address[6:0] ? 8'h42 : _GEN_41; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_43 = 7'h2b == io_address[6:0] ? 8'h43 : _GEN_42; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_44 = 7'h2c == io_address[6:0] ? 8'h44 : _GEN_43; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_45 = 7'h2d == io_address[6:0] ? 8'h45 : _GEN_44; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_46 = 7'h2e == io_address[6:0] ? 8'h46 : _GEN_45; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_47 = 7'h2f == io_address[6:0] ? 8'h47 : _GEN_46; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_48 = 7'h30 == io_address[6:0] ? 8'h48 : _GEN_47; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_49 = 7'h31 == io_address[6:0] ? 8'h49 : _GEN_48; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_50 = 7'h32 == io_address[6:0] ? 8'h50 : _GEN_49; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_51 = 7'h33 == io_address[6:0] ? 8'h51 : _GEN_50; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_52 = 7'h34 == io_address[6:0] ? 8'h52 : _GEN_51; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_53 = 7'h35 == io_address[6:0] ? 8'h53 : _GEN_52; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_54 = 7'h36 == io_address[6:0] ? 8'h54 : _GEN_53; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_55 = 7'h37 == io_address[6:0] ? 8'h55 : _GEN_54; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_56 = 7'h38 == io_address[6:0] ? 8'h56 : _GEN_55; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_57 = 7'h39 == io_address[6:0] ? 8'h57 : _GEN_56; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_58 = 7'h3a == io_address[6:0] ? 8'h58 : _GEN_57; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_59 = 7'h3b == io_address[6:0] ? 8'h59 : _GEN_58; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_60 = 7'h3c == io_address[6:0] ? 8'h60 : _GEN_59; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_61 = 7'h3d == io_address[6:0] ? 8'h61 : _GEN_60; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_62 = 7'h3e == io_address[6:0] ? 8'h62 : _GEN_61; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_63 = 7'h3f == io_address[6:0] ? 8'h63 : _GEN_62; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_64 = 7'h40 == io_address[6:0] ? 8'h64 : _GEN_63; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_65 = 7'h41 == io_address[6:0] ? 8'h65 : _GEN_64; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_66 = 7'h42 == io_address[6:0] ? 8'h66 : _GEN_65; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_67 = 7'h43 == io_address[6:0] ? 8'h67 : _GEN_66; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_68 = 7'h44 == io_address[6:0] ? 8'h68 : _GEN_67; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_69 = 7'h45 == io_address[6:0] ? 8'h69 : _GEN_68; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_70 = 7'h46 == io_address[6:0] ? 8'h70 : _GEN_69; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_71 = 7'h47 == io_address[6:0] ? 8'h71 : _GEN_70; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_72 = 7'h48 == io_address[6:0] ? 8'h72 : _GEN_71; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_73 = 7'h49 == io_address[6:0] ? 8'h73 : _GEN_72; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_74 = 7'h4a == io_address[6:0] ? 8'h74 : _GEN_73; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_75 = 7'h4b == io_address[6:0] ? 8'h75 : _GEN_74; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_76 = 7'h4c == io_address[6:0] ? 8'h76 : _GEN_75; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_77 = 7'h4d == io_address[6:0] ? 8'h77 : _GEN_76; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_78 = 7'h4e == io_address[6:0] ? 8'h78 : _GEN_77; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_79 = 7'h4f == io_address[6:0] ? 8'h79 : _GEN_78; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_80 = 7'h50 == io_address[6:0] ? 8'h80 : _GEN_79; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_81 = 7'h51 == io_address[6:0] ? 8'h81 : _GEN_80; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_82 = 7'h52 == io_address[6:0] ? 8'h82 : _GEN_81; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_83 = 7'h53 == io_address[6:0] ? 8'h83 : _GEN_82; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_84 = 7'h54 == io_address[6:0] ? 8'h84 : _GEN_83; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_85 = 7'h55 == io_address[6:0] ? 8'h85 : _GEN_84; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_86 = 7'h56 == io_address[6:0] ? 8'h86 : _GEN_85; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_87 = 7'h57 == io_address[6:0] ? 8'h87 : _GEN_86; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_88 = 7'h58 == io_address[6:0] ? 8'h88 : _GEN_87; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_89 = 7'h59 == io_address[6:0] ? 8'h89 : _GEN_88; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_90 = 7'h5a == io_address[6:0] ? 8'h90 : _GEN_89; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_91 = 7'h5b == io_address[6:0] ? 8'h91 : _GEN_90; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_92 = 7'h5c == io_address[6:0] ? 8'h92 : _GEN_91; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_93 = 7'h5d == io_address[6:0] ? 8'h93 : _GEN_92; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_94 = 7'h5e == io_address[6:0] ? 8'h94 : _GEN_93; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_95 = 7'h5f == io_address[6:0] ? 8'h95 : _GEN_94; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_96 = 7'h60 == io_address[6:0] ? 8'h96 : _GEN_95; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_97 = 7'h61 == io_address[6:0] ? 8'h97 : _GEN_96; // @[hello.scala 16:{13,13}]
wire [7:0] _GEN_98 = 7'h62 == io_address[6:0] ? 8'h98 : _GEN_97; // @[hello.scala 16:{13,13}]
assign io_data = 7'h63 == io_address[6:0] ? 8'h99 : _GEN_98; // @[hello.scala 16:{13,13}]
endmodule
See if it's easy?
结语
这一篇文章以BCD为例,explained how to use itScalaThe characteristics of the generated logic table and inChiselUsed in hardware builds.我们用到了ScalaFile read operations and for循环,以及Scalacommonly used in sequencemap函数,Logic table based can be implemented within a programming environmentChisel代码的生成,More complex logic tables can do the same.This article is only usedScala的基本功能,the next two articles,We will use them separatelyScalaFeatures of object-oriented programming and functional programming,Learn more about how to take advantage of the powerfulScala生成Chisel硬件.
边栏推荐
猜你喜欢
随机推荐
【Atlas快速入门】
【WPF】级联Combobox及其与ListView的联动
亿流量大考(5):百亿流量全链路99.99%高可用架构最佳实践
Node学习笔记
【How to use Medooze to realize multi-party video conference】
uniapp 左滑删除效果二、效果一(2个方式自选其一)(整理)
cdh6,使用oozie进行spark的jar任务调度
【pytorch 模型量化方法总结】
Shell系统学习之文件操作
pinia 基于插件pinia-plugin-persist的 持久化
s905l3a系列刷armbian 教你从0搭建自己的博客
What can the "Ninth-Order Evaluation Model" bring?
勒索软件频繁升级,了解常见勒索软件很有必要
LoRa组网解决方案
【边缘部署 AI】
0x000000f4蓝屏是怎么回事 win7蓝屏0x000000f4解决方法
蓝屏0x0000007B是什么原因 win7开机蓝屏0x0000007B怎么恢复
公告|Gear 官方白皮书正式发布!
oracle associated table query with in associated query separated by characters comma separated
uniapp Jiugongge lottery function effect demo (sorting)









