当前位置: 首页 > news >正文

SpinalHDL之仿真(八)

本文作为SpinalHDL学习笔记第三十六篇,介绍SpinalHDL仿真示例。

目录:

1.异步加法器

2.双时钟域 FIFO

3.单时钟域 FIFO
 

 

1.异步加法器

此示例使用组合逻辑创建一个 Component ,对 3 个操作数执行一些简单的算术运算。
测试平台执行 100 次以下步骤:
• 将 a, b, 和 c 初始化为 0..255 范围内的随机整数。
• 激励 DUT (Device Under Test) 匹配 a, b, c 的输入。
• 等待 1 个仿真步长(以允许输入传播)。
• 检查输出是否正确。

import spinal.core._
import spinal.core.sim._
import scala.util.Random
object SimAsynchronousExample {
class Dut extends Component {
val io = new Bundle {
val a, b, c = in UInt (8 bits)
val result = out UInt (8 bits)
}
io.result := io.a + io.b - io.c
}
def main(args: Array[String]): Unit = {
SimConfig.withWave.compile(new Dut).doSim{ dut =>
var idx = 0
while(idx < 100){
val a, b, c = Random.nextInt(256)
dut.io.a #= a
dut.io.b #= b
dut.io.c #= c
sleep(1) // Sleep 1 simulation timestep
assert(dut.io.result.toInt == ((a + b - c) & 0xFF))
idx += 1
}
}
}
}

 

2.双时钟域 FIFO

此示例创建了一个专为跨时钟域而设计的 StreamFifoCC 以及 3 个仿真线程。
线程处理:
• 两个时钟域的管理
• 推入 FIFO
• 从 FIFO 弹出

FIFO 推送线程将输入随机化。
FIFO 弹出线程根据参考模型(普通的 scala.collection.mutable.Queue 实例)检查 DUT 的输出。
 

import spinal.core._
import spinal.core.sim._
import scala.collection.mutable.Queue
object SimStreamFifoCCExample {
def main(args: Array[String]): Unit = {
// Compile the Component for the simulator.
val compiled = SimConfig.withWave.allOptimisation.compile(
rtl = new StreamFifoCC(
dataType = Bits(32 bits),
depth = 32,
pushClock = ClockDomain.external("clkA"),
popClock = ClockDomain.external("clkB",withReset = false)
)
)
// Run the simulation.
compiled.doSimUntilVoid{dut =>
val queueModel = mutable.Queue[Long]()
// Fork a thread to manage the clock domains signals
val clocksThread = fork {
// Clear the clock domains' signals, to be sure the simulation captures␣
,→their first edges.
dut.pushClock.fallingEdge()
dut.popClock.fallingEdge()
dut.pushClock.deassertReset()
sleep(0)
// Do the resets.
dut.pushClock.assertReset()
sleep(10)
dut.pushClock.deassertReset()
sleep(1)
// Forever, randomly toggle one of the clocks.
// This will create asynchronous clocks without fixed frequencies.
while(true) {
if(Random.nextBoolean()) {
dut.pushClock.clockToggle()
} else {
dut.popClock.clockToggle()
}
sleep(1)
}
}// Push data randomly, and fill the queueModel with pushed transactions.
val pushThread = fork {
while(true) {
dut.io.push.valid.randomize()
dut.io.push.payload.randomize()
dut.pushClock.waitSampling()
if(dut.io.push.valid.toBoolean && dut.io.push.ready.toBoolean) {
queueModel.enqueue(dut.io.push.payload.toLong)
}
}
}
// Pop data randomly, and check that it match with the queueModel.
val popThread = fork {
for(i <- 0 until 100000) {
dut.io.pop.ready.randomize()
dut.popClock.waitSampling()
if(dut.io.pop.valid.toBoolean && dut.io.pop.ready.toBoolean) {
assert(dut.io.pop.payload.toLong == queueModel.dequeue())
}
}
simSuccess()
}
}
}
}

 

3.单时钟域 FIFO

此示例创建一个 StreamFifo,并生成 3 个仿真线程。与Dual clock ffo 示例不同,此 FIFO 不需要复杂的时钟管理。
3 个仿真线程处理:
• 管理时钟/复位
• 推入 FIFO
• 从 FIFO 弹出

FIFO 推送线程将输入随机化。
FIFO 弹出线程根据参考模型(普通的 scala.collection.mutable.Queue 实例)检查 DUT 的输出。
 

import spinal.core._
import spinal.core.sim._
import scala.collection.mutable.Queue
object SimStreamFifoExample {
def main(args: Array[String]): Unit = {
// Compile the Component for the simulator.
val compiled = SimConfig.withWave.allOptimisation.compile(
rtl = new StreamFifo(
dataType = Bits(32 bits),
depth = 32
)
)// Run the simulation.
compiled.doSimUntilVoid{dut =>
val queueModel = mutable.Queue[Long]()
dut.clockDomain.forkStimulus(period = 10)
SimTimeout(1000000*10)
// Push data randomly, and fill the queueModel with pushed transactions.
val pushThread = fork {
dut.io.push.valid #= false
while(true) {
dut.io.push.valid.randomize()
dut.io.push.payload.randomize()
dut.clockDomain.waitSampling()
if(dut.io.push.valid.toBoolean && dut.io.push.ready.toBoolean) {
queueModel.enqueue(dut.io.push.payload.toLong)
}
}
}
// Pop data randomly, and check that it match with the queueModel.
val popThread = fork {
dut.io.pop.ready #= true
for(i <- 0 until 100000) {
dut.io.pop.ready.randomize()
dut.clockDomain.waitSampling()
if(dut.io.pop.valid.toBoolean && dut.io.pop.ready.toBoolean) {
assert(dut.io.pop.payload.toLong == queueModel.dequeue())
}
}
simSuccess()
}
}
}
}

 

 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Rust中的特殊类型(引用、智能指针等)所占的内存大小
  • WebStorm格式化JSON,将一行很长的JSON展开
  • 在vscode中远程连接linux进行开发
  • 数据结构与算法--递归
  • Terminator的分割终端功能确实非常实用,特别是当你需要同时监控多个任务时,快捷键来分割窗口
  • 计算机专业英语词汇
  • 无人机长生不老秘籍
  • C++之移动语义与左值右值深入学习:从入门到精通!
  • leetcode每日一题46
  • 《数据结构》(C语言版)第1章 绪论(下)
  • C语言 ——— 在控制台实现扫雷游戏(一次展开一片,递归实现)
  • java之静态内部类
  • 国内顶级 AI 的回答令人“贻笑大方”:看来苹果秃头码农们暂时还不会失业吧?
  • vue3+vite全局引入less变量和函数
  • playwrite今日头条自动发帖
  • angular组件开发
  • C++入门教程(10):for 语句
  • flask接收请求并推入栈
  • Javascript Math对象和Date对象常用方法详解
  • Java小白进阶笔记(3)-初级面向对象
  • python3 使用 asyncio 代替线程
  • SegmentFault 技术周刊 Vol.27 - Git 学习宝典:程序员走江湖必备
  • Traffic-Sign Detection and Classification in the Wild 论文笔记
  • Vue2.x学习三:事件处理生命周期钩子
  • 搞机器学习要哪些技能
  • 看域名解析域名安全对SEO的影响
  • 思否第一天
  • 通过几道题目学习二叉搜索树
  • 物联网链路协议
  • 学习笔记:对象,原型和继承(1)
  • 用Canvas画一棵二叉树
  • 从如何停掉 Promise 链说起
  • ​TypeScript都不会用,也敢说会前端?
  • (51单片机)第五章-A/D和D/A工作原理-A/D
  • (C++)八皇后问题
  • (delphi11最新学习资料) Object Pascal 学习笔记---第7章第3节(封装和窗体)
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (Python) SOAP Web Service (HTTP POST)
  • (纯JS)图片裁剪
  • (二十三)Flask之高频面试点
  • (附源码)springboot“微印象”在线打印预约系统 毕业设计 061642
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)
  • (一)为什么要选择C++
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • .cfg\.dat\.mak(持续补充)
  • .NET 2.0中新增的一些TryGet,TryParse等方法
  • .NET Core/Framework 创建委托以大幅度提高反射调用的性能
  • .NET 表达式计算:Expression Evaluator
  • @Value获取值和@ConfigurationProperties获取值用法及比较(springboot)
  • [@Controller]4 详解@ModelAttribute
  • [000-01-011].第2节:持久层方案的对比
  • [2019.3.5]BZOJ1934 [Shoi2007]Vote 善意的投票
  • [ACTF2020 新生赛]Upload 1
  • [AI Embedchain] 开始使用 - 全栈