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

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

文章目录

1.简介

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

2.顶层设计

3.端口说明

序号 端口 位宽 方向 说明
1 core_clk 1 input 内核时钟
2 core_rstn 1 input 内核复位信号,低有效
3 bus_avalid 1 output 总线的地址有效信号
4 bus_aready 1 input 总线的地址就绪信号
5 bus_write 1 output 总线的写使能信号
6 bus_addr 18 output 总线地址
7 bus_strb 4 output 总线写字节有效信号
8 bus_wdata 32 output 总线写数据
9 bus_rvalid 1 input 总线读有效信号
10 bus_rready 1 output 总线读就绪信号
11 bus_rdata 32 input 总线读数据
12 idu2bmu_pc_set 1 input 程序计数器设置
13 idu2bmu_pc_new 18 input 新的程序计数器
14 bmu2idu_pc_ack 1 output 程序计数器应答
15 idu2bmu_ls_req 1 input 加载与存储请求
16 idu2bmu_ls_cmd 1 input 加载与存储命令,1写0读
17 idu2bmu_ls_size 2 input 加载与存储写数据字节数
18 idu2bmu_ls_addr 20 input 加载与存储的地址
19 idu2bmu_ls_wdata 32 input 加载与存储的写数据
20 bmu2idu_ls_rdata 32 output 加载与存储的读数据
21 bmu2idu_valid 1 output 指令有效指示
22 bmu2idu_instr 32 output 需要执行的指令
23 bmu2idu_pc_cur 18 output 当前指令的PC
24 bmu2idu_pc_nxt 18 output 下一条指令的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.代码设计

verilog 复制代码
// -------------------------------------------------------------------------------------------------
// 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)
begin
    if(!core_rstn)
        discard <= 1'b0;
    else if(pc_set_fire)
        discard <= 1'b1;
    else if(bus_addr_fire)
        discard <= 1'b0;
end

always @(posedge core_clk or negedge core_rstn)
begin
    if(!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;
end

always @(posedge core_clk or negedge core_rstn)
begin
    if(!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;
end

always @(posedge core_clk or negedge core_rstn)
begin
    if(!core_rstn)
        bus_avalid <= 1'b0;
    else
        bus_avalid <= 1'b1;
end

always @(posedge core_clk or negedge core_rstn)
begin
    if(!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;
end

always @(posedge core_clk or negedge core_rstn)
begin
    if(!core_rstn)
        instr_wsel <= 1'b0;
    else if(pc_set_fire)
        instr_wsel <= 1'b0;
    else if(bus_inst_fire)
        instr_wsel <= ~instr_wsel;
end

always @(posedge core_clk or negedge core_rstn)
begin
    if(!core_rstn)
        instr_rsel <= 1'b0;
    else if(pc_set_fire)
        instr_rsel <= 1'b0;
    else if(instr_out_fire)
        instr_rsel <= ~instr_rsel;
end

always @(posedge core_clk or negedge core_rstn)
begin
    if(!core_rstn)
        instr_size <= 2'd0;
    else if(pc_set_fire)
        instr_size <= 2'd0;
    else
        instr_size <= instr_size + bus_inst_fire - instr_out_fire;
end

always @(posedge core_clk)
begin
    if(~instr_wsel & bus_inst_fire)
        instr_buf0 <= bus_rdata;
end

always @(posedge core_clk)
begin
    if(instr_wsel & bus_inst_fire)
        instr_buf1 <= bus_rdata;
end

endmodule

6.总结

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

相关推荐
BigDark的笔记1 个月前
【鸿蒙】0x02-LiteOS-M基于Qemu RISC-V运行
华为·harmonyos·risc-v
早上真好1 个月前
【项目推荐】CakeMu-RV:一个开放的 RISC-V 处理器模拟器学习项目
嵌入式硬件·mcu·学习·计算机外设·risc-v
sinovoip1 个月前
Banana Pi BPI-RV2 RISC-V路由开发板采用矽昌通信SF2H8898芯片
risc-v
CV金科1 个月前
freertos的基础(二)内存管理:堆和栈
stm32·开源·arm·freertos·risc-v
BroccoliKing1 个月前
An FPGA-based SoC System——RISC-V On PYNQ项目复现
arm开发·单片机·mcu·fpga开发·dsp开发·risc-v
百里杨1 个月前
X86(Local APIC+I/O APIC)与RISC-V(IMSIC+APLIC)对比
risc-v·x86·local apic·ioapic·imsic·aplic
嵌入式Linux,1 个月前
一块钱的RISC-V 32位芯片
risc-v
世事如云有卷舒2 个月前
RISC-V学习笔记
笔记·学习·risc-v
oahrzvq2 个月前
【CPU】RISC-V 与 x86 操作数字段的区别
系统架构·risc-v
MounRiver_Studio2 个月前
基于VSCode软件框架的RISC-V IDE MRS2正式上线发布
ide·vscode·mcu·risc-v