【RISC-V设计-08】- RISC-V处理器设计K0A之BMU

embedded/2024/10/18 19:27:03/

【RISC-V设计-08】- RISC-V处理器设计K0A之BMU

文章目录

  • 【RISC-V设计-08】- RISC-V处理器设计K0A之BMU
    • 1.简介
    • 2.顶层设计
    • 3.端口说明
    • 4.总线时序
      • 4.1 总线写时序
      • 4.2 总线读时序
    • 5.代码设计
    • 6.总结

1.简介

总线管理单元(Bus Management Unit,简称 BMU)是 CPU 中负责取指以及数据加载与存储的模块。其主要涵盖两个功能:其一为指令获取,当 CPU 开始运行,BMU 模块会依据程序计数器 PC,依序逐步加载指令,随后交付给译码、执行单元处理。其二是数据的加载与存储,当执行到加载指令时,按照译码、执行单元的指示,向总线发起读请求,所读取到的数据会返回至通用寄存器组;而在执行到数据的存储指令时,同样依据译码、执行单元的指示,向总线发起写请求。在 BMU 的设计当中,数据的加载与存储具备高优先级,而指令的获取则具有低优先级。

2.顶层设计

3.端口说明

序号端口位宽方向说明
1core_clk1input内核时钟
2core_rstn1input内核复位信号,低有效
3bus_avalid1output总线的地址有效信号
4bus_aready1input总线的地址就绪信号
5bus_write1output总线的写使能信号
6bus_addr18output总线地址
7bus_strb4output总线写字节有效信号
8bus_wdata32output总线写数据
9bus_rvalid1input总线读有效信号
10bus_rready1output总线读就绪信号
11bus_rdata32input总线读数据
12idu2bmu_pc_set1input程序计数器设置
13idu2bmu_pc_new18input新的程序计数器
14bmu2idu_pc_ack1output程序计数器应答
15idu2bmu_ls_req1input加载与存储请求
16idu2bmu_ls_cmd1input加载与存储命令,1写0读
17idu2bmu_ls_size2input加载与存储写数据字节数
18idu2bmu_ls_addr20input加载与存储的地址
19idu2bmu_ls_wdata32input加载与存储的写数据
20bmu2idu_ls_rdata32output加载与存储的读数据
21bmu2idu_valid1output指令有效指示
22bmu2idu_instr32output需要执行的指令
23bmu2idu_pc_cur18output当前指令的PC
24bmu2idu_pc_nxt18output下一条指令的PC

4.总线时序

此总线分为两个通道,分别是主机向丛机传输的地址和写数据通道,丛机向数据传输的读数据通道。两个通道均采用双向握手机制,在valid和ready同时为高时,通道内数据(包含地址、控制信号)传输完成。

4.1 总线写时序

在上图中,第一次传输为单次写操作,数据、地址同时发出,bus_avalid和bus_aready同时为高时,写数据传输完成。第二次传输时,bus_aready为低,在等到bus_aready为高时,写数据传输完成。第三次传输为连续写操作。第四次传输由于bus_aready为低,之后主机并未保持传输,而是切换为第五次传输,所有第四次传输被取消,数据D4不会被写入。

4.2 总线读时序

在上图中,第一次传输为单次读操作,地址发出后,bus_avalid和bus_aready同时为高时,读地址被接受,同时开始数据传输,在遇到bus_rvalid和bus_rready同时为高时,数据传输完成。第二次传输时,bus_aready为低,在等到bus_aready为高时,读地址被接受。第三次传输为连续读操作。第四次传输由于bus_aready为低,之后主机并未保持传输,而是切换为第五次传输,所有第四次传输被取消,数据D4不会被读出。

5.代码设计

// -------------------------------------------------------------------------------------------------
// Copyright 2024 Kearn Chen, kearn.chen@aliyun.com
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// -------------------------------------------------------------------------------------------------
// Description :
//             1. Bus Management Unit
// -------------------------------------------------------------------------------------------------module k0a_core_bmu (input  wire         core_clk         ,input  wire         core_rstn        ,output reg          bus_avalid       ,input  wire         bus_aready       ,output wire         bus_write        ,output wire [17:0]  bus_addr         ,output wire [3:0]   bus_strb         ,output wire [31:0]  bus_wdata        ,input  wire         bus_rvalid       ,output wire         bus_rready       ,input  wire [31:0]  bus_rdata        ,input  wire         idu2bmu_pc_set   ,input  wire [17:0]  idu2bmu_pc_new   ,output wire         bmu2idu_pc_ack   ,input  wire         idu2bmu_ls_req   ,input  wire         idu2bmu_ls_cmd   ,input  wire [1:0]   idu2bmu_ls_size  ,input  wire [19:0]  idu2bmu_ls_addr  ,input  wire [31:0]  idu2bmu_ls_wdata ,output wire [31:0]  bmu2idu_ls_rdata ,output wire         bmu2idu_valid    ,output wire [31:0]  bmu2idu_instr    ,output reg  [17:0]  bmu2idu_pc_cur   ,output wire [17:0]  bmu2idu_pc_nxt
);reg             discard;
reg             load_data;
reg  [17:0]     prefetch_pc;reg             instr_wsel;
reg             instr_rsel;
reg  [1:0]      instr_size;
reg  [31:0]     instr_buf0;
reg  [31:0]     instr_buf1;wire bus_addr_fire = bus_avalid & bus_aready;
wire bus_resp_fire = bus_rvalid & bus_rready;
wire bus_data_fire = bus_resp_fire & ~discard &  load_data;
wire bus_inst_fire = bus_resp_fire & ~discard & ~load_data;wire bus_load_fire  = idu2bmu_ls_req & ~idu2bmu_ls_cmd & bus_data_fire;
wire bus_store_fire = idu2bmu_ls_req &  idu2bmu_ls_cmd & bus_addr_fire;
wire instr_out_fire = bmu2idu_valid & (bus_store_fire | bus_load_fire | ~idu2bmu_ls_req);wire byte_at_0 = idu2bmu_ls_size[1] | idu2bmu_ls_size[0] & ~idu2bmu_ls_addr[1] | idu2bmu_ls_addr[1:0] == 2'd0;
wire byte_at_1 = idu2bmu_ls_size[1] | idu2bmu_ls_size[0] & ~idu2bmu_ls_addr[1] | idu2bmu_ls_addr[1:0] == 2'd1;
wire byte_at_2 = idu2bmu_ls_size[1] | idu2bmu_ls_size[0] &  idu2bmu_ls_addr[1] | idu2bmu_ls_addr[1:0] == 2'd2;
wire byte_at_3 = idu2bmu_ls_size[1] | idu2bmu_ls_size[0] &  idu2bmu_ls_addr[1] | idu2bmu_ls_addr[1:0] == 2'd3;wire pc_set_fire = idu2bmu_pc_set & bmu2idu_pc_ack;assign bmu2idu_pc_ack = instr_out_fire;assign bus_write = idu2bmu_ls_cmd;assign bus_strb  = {byte_at_3, byte_at_2, byte_at_1, byte_at_0};assign bus_addr  = idu2bmu_ls_req & ~load_data ? idu2bmu_ls_addr[19:2] : prefetch_pc;assign bus_wdata = idu2bmu_ls_wdata;assign bus_rready = 1'b1;assign bmu2idu_ls_rdata = bus_rdata;assign bmu2idu_valid = |instr_size;assign bmu2idu_instr = instr_rsel ? instr_buf1 : instr_buf0;assign bmu2idu_pc_nxt = bmu2idu_pc_cur + 1'b1;always @(posedge core_clk or negedge core_rstn)
beginif(!core_rstn)discard <= 1'b0;else if(pc_set_fire)discard <= 1'b1;else if(bus_addr_fire)discard <= 1'b0;
endalways @(posedge core_clk or negedge core_rstn)
beginif(!core_rstn)load_data <= 1'b0;else if(bus_addr_fire & idu2bmu_ls_req & ~load_data & ~idu2bmu_ls_cmd)load_data <= 1'b1;else if(bus_data_fire)load_data <= 1'b0;
endalways @(posedge core_clk or negedge core_rstn)
beginif(!core_rstn)prefetch_pc <= 18'd0;else if(pc_set_fire)prefetch_pc <= idu2bmu_pc_new;else if(bus_addr_fire & (~idu2bmu_ls_req | load_data))prefetch_pc <= prefetch_pc + 1'b1;
endalways @(posedge core_clk or negedge core_rstn)
beginif(!core_rstn)bus_avalid <= 1'b0;elsebus_avalid <= 1'b1;
endalways @(posedge core_clk or negedge core_rstn)
beginif(!core_rstn)bmu2idu_pc_cur <= 18'd0;else if(pc_set_fire)bmu2idu_pc_cur <= idu2bmu_pc_new;else if(instr_out_fire)bmu2idu_pc_cur <= bmu2idu_pc_nxt;
endalways @(posedge core_clk or negedge core_rstn)
beginif(!core_rstn)instr_wsel <= 1'b0;else if(pc_set_fire)instr_wsel <= 1'b0;else if(bus_inst_fire)instr_wsel <= ~instr_wsel;
endalways @(posedge core_clk or negedge core_rstn)
beginif(!core_rstn)instr_rsel <= 1'b0;else if(pc_set_fire)instr_rsel <= 1'b0;else if(instr_out_fire)instr_rsel <= ~instr_rsel;
endalways @(posedge core_clk or negedge core_rstn)
beginif(!core_rstn)instr_size <= 2'd0;else if(pc_set_fire)instr_size <= 2'd0;elseinstr_size <= instr_size + bus_inst_fire - instr_out_fire;
endalways @(posedge core_clk)
beginif(~instr_wsel & bus_inst_fire)instr_buf0 <= bus_rdata;
endalways @(posedge core_clk)
beginif(instr_wsel & bus_inst_fire)instr_buf1 <= bus_rdata;
endendmodule

6.总结

本文设计了总线管理单元,内部包含了2个指令缓存,电路结构简单。通过精细的逻辑控制和状态管理,实现了与外部总线的高效交互,支持指令的预取和数据的加载存储操作,是处理器设计中重要的组成部分。


http://www.ppmy.cn/embedded/93422.html

相关文章

力扣高频SQL 50题(基础版)第四十一题之1517.查找拥有有效邮箱的用户

文章目录 力扣高频SQL 50题&#xff08;基础版&#xff09;第四十一题1517.查找拥有有效邮箱的用户题目说明实现过程准备数据实现方式结果截图总结 力扣高频SQL 50题&#xff08;基础版&#xff09;第四十一题 1517.查找拥有有效邮箱的用户 题目说明 表: Users -----------…

Redis实现IP限流的两种方式详解

gateway网关ip限流 通过reids实现 限流的流程图 在配置文件配置限流参数 blackIP:# ip 连续请求的次数continue-counts: ${counts:3}# ip 判断的时间间隔&#xff0c;单位&#xff1a;秒time-interval: ${interval:20}# 限制的时间&#xff0c;单位&#xff1a;秒limit-time…

FPGA第4篇,中国FPGA芯片市场,发展分析与报告

前言 FPGA&#xff08;Field-Programmable Gate Array&#xff09;&#xff0c;即现场可编程门阵列&#xff0c;是一种可由用户配置的集成电路&#xff0c;具有高度的灵活性和强大的计算能力&#xff0c;被广泛应用于通信、航空航天、汽车电子、消费电子、数据中心、人工智能等…

MongoDB笔记1——MongoDB简介

MongoDB 什么是MongoDB 2007年10月&#xff0c;MongoDB由10gen团队所开发&#xff0c;2009年2月首度推出。 基于分布式文件存储的数据库由C语言编写。旨在为WEB应用提供可拓展的高性能数据存储解决方案。 MongoDB是一个介于关系数据库和非关系数据库&#xff08;NoSQL&…

write_sdc和write_script区别

文章目录 一、set_disable_clock_gating_check二、write_sdc和write_script区别1. write_sdc2. write_script 一、set_disable_clock_gating_check set_disable_clock_gating_check对指定的cell/pin/lib_cell/lib_pin设置是否进行clock gating的时序检查。 对于工具插入或者…

Python中各类常用内置转换函数

Python中各类常用内置转换函数 函数功能说明int(x)将 x 转换为整数类型float(x)将 x 转换为浮点数类型str(x)将 x 转换为字符串repr(x)将 x 转换为表达式字符串eval(str)计算在字符串中的有效Python表达式&#xff0c;并返回一个对象list(s)将序列 s 转换为一个列表tuple(s)将…

Linux与Docker常用运维命令一览

大家好&#xff0c;欢迎各位工友。 在博主陆陆续续的运维过程中&#xff0c;经常会用到许多运维相关的命令&#xff0c;以往都是现用现查&#xff0c;如今抽时间都记录一下&#xff0c;便于查阅和使用。 Linux常用命令 文件和目录操作 ls&#xff1a;列出目录内容cd [direc…

用Python打造精彩动画与视频,9.1 综合运用所学技术进行项目开发

第九章&#xff1a;综合项目 9.1 综合运用所学技术进行项目开发 在本章中&#xff0c;我们将综合运用前面章节所学的各种技术&#xff0c;开发一个完整的3D动画项目。这个项目将包括3D建模、动画制作、渲染&#xff0c;以及一些高级技巧&#xff0c;如光照和材质设置。通过这…