当前位置:网站首页>Understand chisel language. 24. Chisel sequential circuit (IV) -- detailed explanation of chisel memory
Understand chisel language. 24. Chisel sequential circuit (IV) -- detailed explanation of chisel memory
2022-07-27 09:41:00 【github-3rr0r】
Chisel Sequential circuits ( Four )——Chisel Memory (Memory) Detailed explanation
The last article introduced the implementation of shift register and two commonly used shift registers , It will be very useful in realizing serial communication , It may have some inspiration for the later high-speed interface design . In Digital Design , There are not only registers that can store the state signal of the circuit , Memory (Memory, Or memory , This article is called memory ) You can also save status information , In processor design, memory is also used for storing program code and data , So it's absolutely important . Let's study this article together Chisel Memory implementation in, especially the implementation and initialization of synchronous memory .
Memory and Chisel Synchronous memory in SyncReadMem
Memory can be constructed with a set of registers , such as Chisel In a Vec Of Reg. However, it is too expensive to use registers to realize memory in hardware , So the larger memory structures are built as SRAM(Static Random Access Memory, Static random access memory ). about ASIC It uses memory compiler to build memory . and FPGA Bread on chip memory storage unit (On-chip Memory Block), It's also called block RAM, Block ram . These on-chip memory units can be combined into large memory .FPGA The memory on usually has a read port and a write port , Or two ports that can switch reading and writing at runtime .
FPGA and ASIC It usually supports synchronous memory , Synchronous memory has registers at their inputs , Used to store the read / write port 、 Writing data 、 Write enable signal, etc . This means that the data can only be read after one clock cycle after the address is set . The following figure is a schematic diagram of synchronous memory :

This is a dual port memory , There is a read port , A write port . The read port has an input rdAddr, Read address immediately , And an output rdData, That is, the data read . The write port has three inputs , Write the address (wrAddr)、 The data to be written (wrData) And write enable signal (wrEna). Here's the thing to watch out for , For all input , There is a register in memory for synchronous behavior .
As mentioned earlier, we don't want to use Chisel To realize memory , therefore Chisel In order to support on-chip memory , A special memory constructor is provided SyncReadMem. The following code implements one 1KiB Of memory Memory, And the input and output are byte width with write enable signal :
class Memory() extends Module {
val io = IO(new Bundle {
val rdAddr = Input(UInt(10.W))
val rdData = Output(UInt(8.W))
val wrEnable = Input(Bool())
val wrAddr = Input(UInt(10.W))
val wrData = Input(UInt(8.W))
})
val mem = SyncReadMem(1024, UInt(8.W))
io.rdData := mem.read(io.rdAddr)
when(io.wrEnable) {
mem.write(io.wrAddr, io.wrData)
}
}
You can probably see , Constructors SyncReadMem The generated memory is the synchronous memory with those registers , So we can directly define the relevant input and output ports for the module .SyncReadMem The two parameters of are the size of memory and the data type of memory unit , In the example, it is defined 1024 Bytes of memory , namely 1KiB Of memory . in addition ,mem.read(addr) You can read the address in memory as addr The data of , Empathy mem.write(addr, data) The address in memory can be addr Write data at data. Due to 1024 Indexing memory units requires 10 Address of bit , Left shift read and write addresses are 10 Bit width .
Synchronous memory with read / write forwarding
The above code looks ok , But there is an interesting point , That is, if the same address of the memory is read and written in the same clock cycle , Is the value we read the old value or the new value to be written ? This memory Read while writing (Read-During-Write) Behavior deserves attention , There are three possibilities for the value read :
- Newly written value ;
- Old value ;
- Undefined value ( For example, it may be a combination of bits of the old value and the new value );
FPGA In fact, the possibility depends on FPGA The type of , Sometimes it can be specified . But in the Chisel It is clear in the document of , This read data is Undefined Of .
therefore , If we want to read the newly written value , We can build a forwarding circuit , This circuit can detect whether the read and write addresses are consistent , If it's the same , Just forward the written data to the read data port . The following figure is the schematic diagram of synchronous memory with read-write forwarding :

You can see in the diagram , Read and write addresses will be compared , Then the result is matched with the write enable signal , It is used to select whether the read data is the value of write data or the value read in memory . Again , Because it is synchronous memory , So the selection signal also needs to be written into a register , The read data will be output in the next clock cycle .
The following is synchronous memory with read / write forwarding Chisel Realization :
class ForwardingMemory() extends Module {
val io = IO(new Bundle {
val rdAddr = Input(UInt(10.W))
val rdData = Output(UInt(8.W))
val wrEnable = Input(Bool())
val wrAddr = Input(UInt(10.W))
val wrData = Input(UInt(8.W))
})
val mem = SyncReadMem(1024, UInt(8.W))
val wrDataReg = RegNext(io.wrData)
val doForwardReg = RegNext(io.wrAddr === io.rdAddr && io.wrEnabale)
val memData = mem.read(io.rdAddr)
when(io.wrEnable) {
mem.write(io.wrAddr, io.wrData)
}
io.rdData := Mux(doForwardReg, wrDataReg, memData)
}
The code is still not difficult , We need to put the written data into a register wrDataReg Inside , So that the next clock cycle can be used , One is to adapt synchronous memory , On the other hand, it provides values for reading in the next cycle . At the same time, the code also compares the two input addresses , Read address immediately rdAddr And write address wrAddr, Check the write enable signal wrEnable, Used to judge whether the forwarding conditions are met . This forwarding condition should also be delayed by one clock cycle , So you need the whole register doForwardReg To store whether the forwarding conditions are true . Use one last Mux To select whether the read data is forwarded data or memory read data .
About Chisel Medium Mem
Chisel Another constructor is also provided in Mem, The memory constructed by this constructor is synchronously written 、 Asynchronously read . But this type is FPGA It can't be used directly , The synthesis tool will build it with triggers , Rather than using block RAM. therefore , We should still use SyncReadMem. If you really need to implement asynchronous read behavior , And you use FPGA There are corresponding resources ( For example Xilinx FPGA Inside LUTRAM Structure ), Then you can manually implement and package it as a BlackBox. Generally speaking, suppliers will provide code templates , You can use it directly .
Chisel Memory initialization ( Experimental feature content )
FPGA The memory on can be initialized with binary or hexadecimal initialization files , But note that these files are simple ASCII Text files instead of binary files , The number of lines in the file should be the same as the number of entries in the corresponding memory . Each character in the file represents a value of one or four digits , The binary file is .bin As a file suffix , Each character represents a binary , Hexadecimal files use .hex As a file suffix , Each character represents a four digit binary number .
stay Chisel Can be used in loadMemoryFromFile Function to initialize memory , Usage is as follows :
// You need to use these two packages
import chisel3.util.experimental.loadMemoryFromFile
import firrtl.annotations.MemoryLoadFileType
// Load hex text file into memory
loadMemoryFromFile(mem, "mem.hex", MemoryLoadFileType.Hex)
// Load binary text file into memory
loadMemoryFromFile(mem, "mem.bin", MemoryLoadFileType.Binary)
This loadMemoryFromFile A separate... Will be generated under the folder where the data text file is located Verilog file , The contents of the file are similar to the following code :
module BindsTo_0_Memory(
input clock,
input reset,
input [9:0] io_rdAddr,
output [7:0] io_rdData,
input io_wrEnable,
input [9:0] io_wrAddr,
input [7:0] io_wrData
);
initial begin
$readmemh("mem.hex", Memory.mem);
end
endmodule
bind Memory BindsTo_0_Memory BindsTo_0_Memory_Inst(.*);
This document will be in ChiselTest Work in China , Initialization is also based on Verilog Medium readmemb or readmemh To achieve .
Conclusion
We learned this article Chisel The last part of sequential circuit , Including the implementation and use of synchronous memory , We also talked about the experimental feature of memory initialization . Yes, of course , This is not the only thing about memory , There are also some higher-level content , At the end of this series, I will talk about , Content based on Chisel Official document Explainations, It will cover high-level content not covered in the basic part of this series of tutorials . The next part , We will learn Chisel Some medium-level content in , Respectively for signal processing 、 Finite state machine and communication state machine , It will involve Chisel Some medium order properties of , Useful in digital design .
边栏推荐
猜你喜欢
![WordPress prohibits login or registration of plug-ins with a specified user name [v1.0]](/img/94/92ad89751e746a18edf80296db9188.png)
WordPress prohibits login or registration of plug-ins with a specified user name [v1.0]

ESP8266-Arduino编程实例-ADC

Interviewer: what is scaffolding? Why do you need scaffolding? What are the commonly used scaffolds?

深度剖析分库分表最强辅助Sharding Sphere

通俗易懂!图解Go协程原理及实战

吃透Chisel语言.26.Chisel进阶之输入信号处理(二)——多数表决器滤波、函数抽象和异步复位

吃透Chisel语言.22.Chisel时序电路(二)——Chisel计数器(Counter)详解:计数器、定时器和脉宽调制

NCCL (NVIDIA Collective Communications Library)

吃透Chisel语言.23.Chisel时序电路(三)——Chisel移位寄存器(Shift Register)详解

Sentinel 万字教程 | 文末送书
随机推荐
面试官:什么是脚手架?为什么需要脚手架?常用的脚手架有哪些?
安装了HAL库如何恢复原来的版本
July training (day 07) - hash table
GO基础知识—数组和切片
Read the paper learning to measure changes: full revolutionary Siamese metric networks for scene change detect
七月集训(第26天) —— 并查集
2068. Check whether the two strings are almost equal
都什么年代了你还在用 Date
Lua函数嵌套调用
Nacos is used as a registration center
July training (day 24) - segment tree
七月集训(第17天) —— 广度优先搜索
Talk about 10 scenarios of index failure. It's too stupid
拟搬迁!211中国石油大学(华东)新校区,正式启用!
Transpose and inverse of [linear algebra 01] matrix
如何在树莓派上安装cpolar内网穿透
Sentry 2 orbital data download
好久不送书,浑身不舒服
Nacos做注册中心使用
July training (day 18) - tree