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

HDLBits中文版,标准参考答案 | 6 CS450

关注👆 望森FPGA 👆 查看更多FPGA资讯

这是望森的第 25 期分享

作者 | 望森
来源 | 望森FPGA

目录

1 Cs450/timer

2 Cs450/counter 2bc

3 Cs450/history shift

4 Cs450/gshare


本文中的代码都能够正常运行,请放心食用😋~

练习的官方网站是:https://hdlbits.01xz.net/

注:作者将每个练习的知识点都放在了题目和答案之后


1 Cs450/timer

题目:

实现一个定时器,该定时器按给定数量的时钟周期倒计时,然后发出信号以指示给定的持续时间已过去。实现此目的的一个好方法是使用一个倒计数器,当计数变为 0 时发出输出信号。

在每个时钟周期:

  • 如果 load = 1,则将 10 位数据加载到内部计数器,即定时器在超时前应计数的时钟周期数。计数器可以随时加载,包括它仍在计数但尚未达到 0 时。

  • 如果 load = 0,内部计数器应减 1。

输出信号 tc(“终端计数”)指示内部计数器是否已达到 0。一旦内部计数器达到 0,它应该保持 0(停止计数),直到计数器再次加载。

以下是要求定时器计数 3 个周期时发生的情况的示例:

答案:

module top_module(input clk, input load, input [9:0] data, output tc
);parameter x = 4;reg [9:0] counter;//data inputalways@(posedge clk)beginif(load)begincounter <= data;endelse if(counter)begincounter <= counter - 1;endelse begincounter <= 0;endendassign tc = !counter;endmodule

2 Cs450/counter 2bc

题目:

分支方向预测器通常被构造为由程序计数器和分支历史记录索引的计数器表。每个表条目通常使用两位状态,因为一位状态(记住最后的结果)没有足够的滞后并且太容易翻转状态。

两位饱和计数器的状态图。四种状态是 Strong/Weak Taken (T)/Not-Taken (NT).

一个工作良好的两位状态机是饱和计数器,它向上计数到 3(或 2'b11)或向下计数到 0(或 2'b00),但不会回绕。“ taken ”结果会增加计数器,而“ not-taken ”结果会减少计数器。当计数为 2 或 3(或 2'b1x)时,预测会采取分支。添加一些滞后可防止在强偏差分支偶尔采取不同方向时预测发生翻转,需要在相反方向上增加两次才能翻转预测。

说明:

构建一个 2 位饱和计数器。

当 train_valid = 1 且 train_taken = 1 时,计数器递增(最多 3)。 当 train_valid = 1 且 train_taken = 0 时,计数器递减(最低为 0)。 当不进行训练(train_valid = 0)时,计数器保持其值不变。

areset 是一种异步重置,可将计数器重置为 weakly not-taken (2'b01) 。 输出 state[1:0] 是 2 位计数器值。

答案:

module top_module(input clk,input areset,input train_valid,input train_taken,output reg [1:0] state
);parameter SNT   =2'b00; parameter WNT   =2'b01; parameter WT    =2'b10; parameter ST    =2'b11; reg [1:0] next_state;wire SNT2SNT,SNT2WNT;wire WNT2SNT,WNT2WT,WNT2WNT;wire WT2WNT,WT2ST,WT2WT;wire ST2WT,ST2ST;//状态跳转always @(posedge clk, posedge areset) beginif(areset)beginstate <= WNT;endelse beginstate <= next_state;endend//状态跳转控制always @(*) begincase(state)SNT : beginif (SNT2SNT)beginnext_state = SNT;endelse if(SNT2WNT)beginnext_state = WNT;endendWNT : beginif (WNT2SNT)beginnext_state = SNT;endelse if(WNT2WT)beginnext_state = WT;endelse if(WNT2WNT)beginnext_state = WNT;endendWT : beginif (WT2WNT)beginnext_state = WNT;endelse if(WT2ST)beginnext_state = ST;endelse if(WT2WT)beginnext_state = WT;endendST : beginif (ST2WT)beginnext_state = WT;endelse if(ST2ST)beginnext_state = ST;endenddefault next_state = WNT;endcaseend//状态跳转控制条件assign SNT2SNT  = train_valid && !train_taken || !train_valid;assign SNT2WNT  = train_valid && train_taken;assign WNT2SNT  = train_valid && !train_taken;assign WNT2WT   = train_valid && train_taken;assign WNT2WNT  = !train_valid;assign WT2WNT   = train_valid && !train_taken;assign WT2ST    = train_valid && train_taken;assign WT2WT    = !train_valid;assign ST2WT    = train_valid && !train_taken;assign ST2ST    = train_valid && train_taken || !train_valid;endmodule

知识点:

分支预测器(Branch Predictor)介绍

  • 除了按照状态图中的状态跳转以外,注意“当不进行训练(train_valid = 0)时,计数器保持其值不变”这部分逻辑的描述。

  • 这是一个二位饱和计数器形式的分支预测器,这种方法的优点是,该条件分支指令必须连续选择某条分支两次,才能从强状态翻转,从而改变了预测的分支。


3 Cs450/history shift

题目:

构建一个 32 位全局历史移位寄存器,包括支持回滚状态以响应由分支预测错误引起的流水线刷新。

当进行分支预测时 (predict_valid = 1),将 predict_taken 从 LSB 侧移入predict_history,以更新预测分支的分支历史记录。(predict_history[0] 是最新分支的方向。)

当发生分支预测错误时 (train_mispredicted = 1),用发生错误之前的历史记录(train_history)覆盖到预测历史(predict_history),并将正确结果(train_taken)从LSB移位进入predict_history覆盖原值。

如果预测(predict_valid)和预测错误(train_mispredicted)同时发生,则预测错误优先。

predict_history 是分支历史记录寄存器的值。

areset 是异步重置,将历史计数器(predict_history)重置为零。

答案:

module top_module(input clk,input areset,input predict_valid,input predict_taken,output [31:0] predict_history,input train_mispredicted,input train_taken,input [31:0] train_history
);always @(posedge clk, posedge areset) beginif(areset)beginpredict_history <= 32'd0;endelse if(train_mispredicted )beginpredict_history <= {train_history[30:0],train_taken};endelse if(predict_valid)beginpredict_history <= {predict_history[30:0],predict_taken};endelse beginpredict_history <= predict_history;endendendmodule

知识点:

分支方向预测器通常被构造为由程序计数器和分支历史记录索引的计数器表。分支历史记录是最近分支的“被采用”或“不被采用”("taken" or "not taken")结果序列。

在硬件中,分支历史记录寄存器可以实现为 N 位移位寄存器。在预测每个条件分支方向后,其预测方向将移入移位寄存器。因此,移位寄存器保存了最近的 N 个分支结果。

分支历史记录寄存器及其周围硬件。此练习在蓝色虚线矩形内构建分支历史记录寄存器。

该图显示分支执行单元发出的分支预测错误信号,但根据处理器设计,这也可能发生在退出或其他时间点。

由于分支预测是推测性的,因此由于管道刷新而产生了额外的复杂性。当发生分支预测错误时,处理器状态需要回滚到预测错误的分支之后的状态。这包括回滚全局历史寄存器,该寄存器可能包含由比错误预测分支更年轻的分支移入的预测分支结果,但现在需要丢弃。

我们在此假设分支预测器之外有硬件,可以记住用于预测每个分支的分支历史寄存器的状态,该状态将保存以供以后用于分支预测器训练和流水线刷新。当发生分支预测错误时,该硬件会通知分支预测器分支预测错误、分支应采取的方向以及与程序中预测错误的分支之前的点相对应的分支历史寄存器的状态。

当然,由于处理器重新启动到预测错误的分支之后的点,因此流水线刷新后的分支历史寄存器需要附加预测错误的分支的实际方向。


4 Cs450/gshare

题目:

分支方向预测器

分支方向预测器生成条件分支指令方向的执行/不执行(taken/not-taken)预测。它位于处理器流水线的前端附近,负责引导指令提取到 (hopefully) 正确的程序执行路径。分支方向预测器通常与分支目标缓冲区 (BTB) 一起使用,其中 BTB 预测目标地址,方向预测器选择是分支到目标还是继续沿失败路径提取。

在流水线的稍后时间(通常在分支执行或退出时),执行的分支指令的结果被发送回分支预测器,以通过观察过去的分支行为来训练它在未来更准确地预测。当出现错误预测的分支时,也可能会出现流水线刷新。

分支方向预测器位于提取阶段。分支预测器使用当前 pc 和历史寄存器进行预测,预测结果会影响下一个 pc 值。训练和错误预测请求来自流水线的稍后部分。

对于本练习,假设分支方向预测器位于图中所示的假设处理器流水线的提取阶段。本练习仅构建分支方向预测器,由图中的蓝色虚线矩形表示。

分支方向预测是一条组合路径:pc 寄存器用于计算采用/不采用预测,这会影响下一个 pc 多路复用器以确定下一个周期的 pc 值。

相反,对模式历史表 (PHT) 和分支历史寄存器的更新将在下一个正时钟沿生效,正如触发器中存储的状态所预期的那样。

Gshare 预测器

分支方向预测器通常被构造为由程序计数器和分支历史记录索引的计数器表。表索引是分支地址和历史记录的哈希值,并尝试为每个分支和历史记录组合提供自己的表条目(或至少减少冲突次数)。每个表条目包含一个两位饱和计数器,用于记住过去执行相同分支和历史记录模式时的分支方向。

这种类型的预测器的一个例子是 gshare 预测器。在 gshare 算法中,分支地址 (pc) 和历史记录位“共享”表索引位。基本 gshare 算法通过将 N 个分支地址位和 N 个全局分支历史记录位异或在一起来计算 N 位 PHT 表索引。

然后使用 N 位索引访问 2N 条目两位饱和计数器表的一个条目。该计数器的值提供预测 (0 or 1 = not taken, 2 or 3 = taken).

训练以类似的方式索引表。训练 pc 和历史记录用于计算表索引。然后,根据分支的实际结果,该索引处的两位计数器将递增或递减。

说明

构建一个具有 7 位 pc 和 7 位全局历史记录的 gshare 分支预测器,将其散列 (using xor) 到 7 位索引中。此索引访问一个深度为 128 的两位饱和计数器表(类似于 cs450/counter_2bc)。分支预测器应包含一个 7 位全局分支历史记录寄存器(类似于 cs450/history_shift)。

分支预测器有两组接口:一组用于进行预测,一组用于进行训练。预测接口用于处理器的获取阶段,以要求分支预测器对正在获取的指令进行分支方向预测。一旦这些分支沿着管道进行并执行,就会知道分支的真实结果。然后使用实际的分支方向结果训练分支预测器。

当为给定的 pc 请求分支预测 (predict_valid = 1) 时,分支预测器会生成用于进行预测的分支历史寄存器的预测分支方向和状态。然后更新分支历史寄存器(在下一个正时钟沿)以预测分支。

当请求分支训练 (train_valid = 1)时,分支预测器会被告知正在训练的分支的 pc 和分支历史寄存器值,以及实际分支结果以及分支是否是错误预测(需要流水线刷新)。更新模式历史表 (PHT) 以训练分支预测器,以便下次更准确地预测此分支。此外,如果正在训练的分支被错误预测,还要将分支历史寄存器恢复到错误预测分支完成执行后的状态。

如果错误预测和预测(针对不同的较新的指令)的训练发生在同一周期,则两个操作都将要修改分支历史寄存器。当这种情况发生时,训练优先,因为无论如何都会丢弃正在预测的分支。如果同一 PHT 条目的训练和预测同时发生,则预测会在训练之前看到 PHT 状态,因为训练仅在下一个正时钟沿修改 PHT。下面的时序图显示了同时训练和预测 PHT 条目 0 时的时序。周期 4 的训练请求改变了周期 5 的 PHT 条目状态,但周期 4 的预测请求输出了周期 4 的 PHT 状态,没有考虑周期 4 的训练请求的影响。

areset 是一个异步重置,它将整个 PHT 清除为 2b'01(weakly not-taken)。它还将全局历史寄存器清除为 0。

答案:

module top_module(input clk,input areset,input  predict_valid,input  [6:0] predict_pc,output predict_taken,output [6:0] predict_history,input train_valid,input train_taken,input train_mispredicted,input [6:0] train_history,input [6:0] train_pc
);reg [1:0] PHT[127:0];integer i;always@(posedge clk,posedge areset) beginif(areset) beginpredict_history <= 7'd0;for(i=0;i<=127;i++) PHT[i] <= 2'b01;endelse beginif(train_mispredicted&&train_valid) beginpredict_history <= {train_history[5:0],train_taken};            endelse if(predict_valid) beginpredict_history <= {predict_history[5:0],predict_taken};endif(train_valid) beginif(train_taken) begin //11PHT[train_pc^train_history] <= (PHT[train_pc^train_history] == 2'b11)? PHT[train_pc^train_history]:PHT[train_pc^train_history] + 2'd1;endelse begin //10               PHT[train_pc^train_history] <= (PHT[train_pc^train_history] == 2'b00)? PHT[train_pc^train_history]:PHT[train_pc^train_history] - 2'd1;end            end           endendassign predict_taken = PHT[predict_pc^predict_history][1];endmodule

知识点:

仔细阅读题解,根据需求设计电路即可。


- END -

HDLBits完结啦,撒花~~~

公z号/CSDN/知乎搜索【望森FPGA】,查看更多FPGA资讯~

相关推荐文章,点击跳转:

望森FPGA的HDLBits合集


http://www.mrgr.cn/news/53550.html

相关文章:

  • 从空口分析经典蓝牙A2DP和AVRCP协议
  • 获取指定函数的用法说明help()
  • 【设计一个恒流转恒压用于电池充电管理】2022-01-25
  • Github 2024-10-19 Rust开源项目日报 Top10
  • 中科星图(GVE)——过火面积识别(dNBR)和CART方法进行火灾识别
  • 基于SSM+微信小程序的家庭记账本管理系统(家庭1)
  • Flutter Column和Row组件
  • 【星闪技术】WS63E模块的WiFi客户端测试
  • 大数据治理--数据安全管理
  • 内存墙与LLM 计算
  • UEFI BIOSAPP编程开发查询手册.pdf
  • Element-plus中的表单验证
  • 三周精通FastAPI:1 第一步入门
  • (新手入门篇)2024年10 月 Java JDK 1.8版本WIN 10 系统安装教程!!!!!!!
  • 【rCore OS 开源操作系统】Rust 宏
  • C++ -string -常见用法4
  • Ruby CGI Cookie
  • 骑砍战团MOD天芒传奇-多人联机
  • 阿里巴巴达摩院|Chain of Ideas: 利用大型语言模型代理革新新颖创意开发的研究
  • Openlayers高级交互(3/20):动态添加 layer 到 layerGroup,并动态删除