【单周期CPU】LoongArch | 32位寄存器DR | 32位的程序计数器PC | 通用寄存器堆Registers | 32位RAM存储器

这篇具有很好参考价值的文章主要介绍了【单周期CPU】LoongArch | 32位寄存器DR | 32位的程序计数器PC | 通用寄存器堆Registers | 32位RAM存储器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言:本章内容主要是演示在vivado下利用Verilog语言进行单周期简易CPU的设计。一步一步自己实现模型机的设计。本章先介绍单周期简易CPU中基本时序逻辑部件设计。

💻环境:一台内存4GB以上,装有64位Windows操作系统和Vivado 2017.4以上版本软件的PC机。

💎本章所采用的指令为LoongArch之LA32R版

【单周期CPU】LoongArch | 32位寄存器DR | 32位的程序计数器PC | 通用寄存器堆Registers | 32位RAM存储器,手糊一个CPU,fpga开发,Verilog

目录

Ⅰ前置知识 

0x00 32位寄存器DR

0x01 32位的程序计数器PC

0x02 通用寄存器堆Registers

0x03  32位RAM存储器

Ⅱ Verilog实现

0x00 32位寄存器DR

0x01 32位的程序计数器PC

0x02 通用寄存器堆Registers

0x03 32位RAM存储器


Ⅰ前置知识 

0x00 32位寄存器DR

32位寄存器DR,全称为数据寄存器(Data Register),是计算机中常见的寄存器之一。它用于存储数据,是CPU中的一个重要组成部分。 

本章介绍的32位寄存器DR模块的参考电路框图如下: 

【单周期CPU】LoongArch | 32位寄存器DR | 32位的程序计数器PC | 通用寄存器堆Registers | 32位RAM存储器,手糊一个CPU,fpga开发,Verilog

该模块的功能及引脚信号说明如下:

信号名称

功能说明

DataIn

32位数据输入信号

DataOut

32位数据输出信号

clk

时钟信号

WE

数据存入信号。当WE为1且在clk上升沿到来时,数据存入寄存器;当WE为0时,寄存器输出维持不变。

0x01 32位的程序计数器PC

32位程序计数器(Program Counter,PC)是计算机中一种重要的寄存器,它通常存储下一条指令的内存地址,是CPU能够顺利地执行指令的关键。

PC寄存器在CPU中被设计为自加的寄存器,它会在一个时钟周期中自动递增,从而指向下一条指令的地址,使得CPU可以连续地执行一系列指令。在程序执行过程中,PC寄存器会不断地指向下一条要执行的指令,直到程序结束或出现异常情况。

在现代计算机中,PC寄存器的位数一般为32位。当程序执行中遇到条件分支、循环等需要改变执行流程的指令时,CPU会根据条件跳转到不同的地址,PC寄存器也就被设置为相应的地址,从而改变了程序的执行路径。

本章介绍的32位的程序计数器PC模块的参考电路框图如下: 

【单周期CPU】LoongArch | 32位寄存器DR | 32位的程序计数器PC | 通用寄存器堆Registers | 32位RAM存储器,手糊一个CPU,fpga开发,Verilog

该模块的功能及引脚信号说明如下:

信号名称

功能说明

rst

PC异步清零信号,高电平有效,即:rst为1时,PCdata =0

clk

时钟信号

offset

32位偏移量

pc_inc

自增控制信号,与clk上升沿配合工作。

在clk上升沿时刻,当pc_inc=1时,PCdata =原PCdata +1;当pc_inc=0时,PCdata =原PCdata +offset。

PCdata

32位数据输出信号

0x02 通用寄存器堆Registers

通用寄存器堆 (Registers) 是计算机体系结构中的一种硬件组件,用于存储和操作数据。它通常由多个独立的寄存器组成,每个寄存器都有固定的位宽。寄存器堆用于执行各种计算机指令和数据传输操作。 

本章介绍的通用寄存器堆Registers的参考电路框图如下:  

【单周期CPU】LoongArch | 32位寄存器DR | 32位的程序计数器PC | 通用寄存器堆Registers | 32位RAM存储器,手糊一个CPU,fpga开发,Verilog

该模块的功能及引脚信号说明如下:

信号名称

功能说明

busA和busB

两路32位数据输出信号

Ra(5位)

读寄存器编号输入信号,该编号指定的寄存器的值经过“取数延迟”后,输出到busA

Rb(5位)

读寄存器编号输入信号,该编号指定的寄存器的值经过“取数延迟”后,输出到busB

Rw(5位)

写寄存器编号输入信号,该编号指定的数据要写入哪个寄存器

busW

32位数据输入信号

clk

写操作时钟控制信号,上升沿有效

RegWr

写使能控制信号,clk上升沿时刻,若RegWr为1,则busW上的数据被存入Rw指定的寄存器中

🚩注:

(1)寄存器堆的读操作不受clk控制;

(2)0号寄存器的值恒为0,不受写操作的影响。

0x03 32位RAM存储器

32位RAM存储器是一种具有32位数据线的随机存取存储器。RAM (Random Access Memory) 指的是随机存取存储器,它允许随机访问存储器中的任何位置,而无需按照顺序访问。32位RAM存储器的数据线有32条,可以同时传送32位二进制数据,因此它能够以非常快的速度读取和写入数据。

本章介绍的32位RAM存储器参考电路框图如下:   

【单周期CPU】LoongArch | 32位寄存器DR | 32位的程序计数器PC | 通用寄存器堆Registers | 32位RAM存储器,手糊一个CPU,fpga开发,Verilog

 该模块的功能及引脚信号说明如下:

信号名称

功能说明

addr

32位地址总线,用于传送地址,以便按地址访问存储单元。

data_in

32位数据输入总线

data_out

32位数据输出总线

clk

时钟信号,上升沿有效

MemWrEn

写使能信号。

当MemWrEn为0时,数据从addr地址端口指定的内存单元读出。

当MemWrEn为1时,配合clk时钟信号工作,在clk上升沿,数据存入由addr地址端口指定的内存单元。

Ⅱ Verilog实现

0x00 32位寄存器DR

设计一个32位的寄存器DR,利用Verilog HDL完成建模设计

设计代码:


module Register32 (
  input [31:0] DataIn,
  output reg [31:0] DataOut,
  input clk,
  input WE
);

  always @(posedge clk) begin
    if (WE) begin
      DataOut <= DataIn;
    end
  end

endmodule

  在Vivado中点击”RTL ANALYSIS->Open Elaborated Design”,可以查看综合得到的 32位寄存器DR的逻辑电路,如图所示: 

【单周期CPU】LoongArch | 32位寄存器DR | 32位的程序计数器PC | 通用寄存器堆Registers | 32位RAM存储器,手糊一个CPU,fpga开发,Verilog

 仿真代码:

module Register32_Test;

  reg [31:0] DataIn;
  wire [31:0] DataOut;
  reg clk;
  reg WE;

  Register32 dut (
    .DataIn(DataIn),
    .DataOut(DataOut),
    .clk(clk),
    .WE(WE)
  );

  always begin
    #5 clk = ~clk; // 时钟周期为10个时间单位
  end

  initial begin
    clk = 0;
    WE = 0;
    DataIn = 32'h11111111; // 设置输入数据
    #20 WE = 1; // 在20个时间单位后,使WE为1,触发数据存入
    #20 WE = 0; // 在另外20个时间单位后,使WE为0,保持输出稳定
    #20 DataIn = 32'h11101011; // 修改输入数据
    #20 WE = 1; // 再次触发数据存入
    #50 $finish; // 结束仿真
  end

endmodule

仿真结果:

【单周期CPU】LoongArch | 32位寄存器DR | 32位的程序计数器PC | 通用寄存器堆Registers | 32位RAM存储器,手糊一个CPU,fpga开发,Verilog

❓思考:

读者可以思考一个问题,刚开始时为什么DataOut为xxx态?

0x01 32位的程序计数器PC

设计代码:


module ProgramCounter(
  input rst,
  input clk,
  input [31:0] offset,
  input pc_inc,
  output reg [31:0] PCdata
);

  always @(posedge clk or posedge rst) begin
    if (rst) begin
      PCdata <= 32'd0;
    end else begin
      if (pc_inc) begin
        PCdata <= PCdata + 32'd1;
      end else begin
        PCdata <= PCdata + offset;
      end
    end
  end

endmodule

  在Vivado中点击”RTL ANALYSIS->Open Elaborated Design”,可以查看综合得到的32位的程序计数器PC的逻辑电路,如图所示:  

【单周期CPU】LoongArch | 32位寄存器DR | 32位的程序计数器PC | 通用寄存器堆Registers | 32位RAM存储器,手糊一个CPU,fpga开发,Verilog

仿真代码:

module ProgramCounter_tb;

  reg rst;
  reg clk;
  reg [31:0] offset;
  reg pc_inc;
  wire [31:0] PCdata;

  ProgramCounter dut (
    .rst(rst),
    .clk(clk),
    .offset(offset),
    .pc_inc(pc_inc),
    .PCdata(PCdata)
  );

  initial begin
    rst = 1;
    clk = 0;
    offset = 32'h00000001;
    pc_inc = 0;
    #10;

    rst = 0;
    #10;

    offset = 32'h00000002;
    pc_inc = 1;
    #10;

    pc_inc = 0;
    #10;

    $display("PCdata = %h", PCdata);

    #10;
    $finish;
  end

  always #5 clk = ~clk;

endmodule

仿真结果:

调整进制后可观察到下列波形

【单周期CPU】LoongArch | 32位寄存器DR | 32位的程序计数器PC | 通用寄存器堆Registers | 32位RAM存储器,手糊一个CPU,fpga开发,Verilog

🚩注: 若不知道如何调整进制,可翻看本专栏的第一篇博客:

【单周期CPU】LoongArch | 立即数扩展模块Ext | 32位算术逻辑运算单元(ALU)_流继承的博客-CSDN博客

0x02 通用寄存器堆Registers

 设计代码:

module Registers(
  input [4:0] Ra,
  input [4:0] Rb,
  input [4:0] Rw,
  input [1:0] busW,
  input clk,
  input RegWr,
  output reg [31:0] busA,
  output reg [31:0] busB
);

  reg [31:0] regfile [0:31];

  always @(*) begin
    busA = regfile[Ra];
    busB = regfile[Rb];
  end

  always @(posedge clk) begin
    if (RegWr) begin
      if (Rw != 0)
        regfile[Rw] <= busW;
    end
  end

  initial begin
    for (integer i = 0; i <= 31; i = i + 1)
      regfile[i] = 32'h0;
  end

endmodule

   在Vivado中点击”RTL ANALYSIS->Open Elaborated Design”,可以查看综合得到的通用寄存器堆Registers的逻辑电路,如图所示:  

【单周期CPU】LoongArch | 32位寄存器DR | 32位的程序计数器PC | 通用寄存器堆Registers | 32位RAM存储器,手糊一个CPU,fpga开发,Verilog

仿真代码:

module Registers_Test;

  reg [4:0] Ra;
  reg [4:0] Rb;
  reg [4:0] Rw;
  reg [1:0] busW;
  reg clk;
  reg RegWr;
  wire [31:0] busA;
  wire [31:0] busB;

  Registers dut (
    .Ra(Ra),
    .Rb(Rb),
    .Rw(Rw),
    .busW(busW),
    .clk(clk),
    .RegWr(RegWr),
    .busA(busA),
    .busB(busB)
  );

  initial begin
    clk = 0;
    RegWr = 0;
    Ra = 0;
    Rb = 0;
    Rw = 0;
    busW = 2'b01;

    #25;

    
   
    Ra = 2;
    Rb = 4;
    #25;
    $display("busA = %h, busB = %h", busA, busB);
   


    Rw = 6;
    busW = 2'b11;
    RegWr = 1;
    #50;
    $display("busA = %h, busB = %h", busA, busB);

    
    Ra = 6;
    Rb = 0;
    #25;
    $display("busA = %h, busB = %h", busA, busB);

    
    #10;
    $display("busA = %h, busB = %h", busA, busB);
  end

  always begin
    #50;
    clk = ~clk;
  end

endmodule

仿真结果:

调整进制后可观察到下列波形

【单周期CPU】LoongArch | 32位寄存器DR | 32位的程序计数器PC | 通用寄存器堆Registers | 32位RAM存储器,手糊一个CPU,fpga开发,Verilog

0x03 32位RAM存储器

设计代码:

module RAM(
input MemWrEn, input clk,
input [31:0] addr,
input [31:0] data_in, output reg [31:0] data_out
);
reg [31:0] ram [0:31];

always@(posedge clk) begin
if (MemWrEn) ram[addr] <= data_in; end
always@(*) begin
if(MemWrEn==0) data_out <= ram[addr]; end
endmodule

    在Vivado中点击”RTL ANALYSIS->Open Elaborated Design”,可以查看综合得到的32位RAM存储器的逻辑电路,如图所示:  

【单周期CPU】LoongArch | 32位寄存器DR | 32位的程序计数器PC | 通用寄存器堆Registers | 32位RAM存储器,手糊一个CPU,fpga开发,Verilog

仿真代码:

module RAM_sim; reg MemWrEn; reg clk;
reg [31:0] addr;
reg [31:0] data_in;
wire [31:0] data_out;

RAM
RAM1(.MemWrEn(MemWrEn),.clk(clk),
.addr(addr),.data_in(data_in),.data_out(data_out));

initial begin MemWrEn=1; addr=20; data_in=60; #200;
addr=15; data_in=30; #200;
addr=5; data_in=120; #200;
MemWrEn=0; addr=20; #100;
addr=15; #100;
addr=5; #200;
end

initial clk = 0;
always # 50 clk = ~clk; endmodule

仿真结果:

调整进制后可观察到下列波形

【单周期CPU】LoongArch | 32位寄存器DR | 32位的程序计数器PC | 通用寄存器堆Registers | 32位RAM存储器,手糊一个CPU,fpga开发,Verilog

❓思考

在完成上述四个模块之后,读者可以思考一下:

1.“如何将数据存入暂存器”、“如何读取暂存器的值”等问题。

2.“如何控制PC的值自增或加偏移量”、“如何给PC清0”等问题。

3.“如何指定要写入数据的寄存器编号”、“如何保证0号寄存器的值不受写入操作的影响而始终保持为0”,“如何指定从哪个寄存器读出数据”和“是否具有将所有寄存器一次性全部清0的功能”等问题。

4.“如何指定要写入数据的内存单元地址” “如何指定从哪个内存单元读出数据”和“是否具有将所有内存单元一次性全部清0的功能”等问题。

END 


📝因为作者的能力有限,所以文章可能会存在一些错误和不准确之处,恳请大家指出!文章来源地址https://www.toymoban.com/news/detail-522608.html

到了这里,关于【单周期CPU】LoongArch | 32位寄存器DR | 32位的程序计数器PC | 通用寄存器堆Registers | 32位RAM存储器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 实验二 CPU 部件实现之 ALU 和寄存器堆

     1.1设计要求 理解和掌握 CPU 中的算术逻辑运算部件(ALU)和寄存器堆(Register File)的工作原理,并使用 Verilog 和 ModelSim 进行设计和仿真。 1. 使用 Verilog 完成 ALU 的设计,并编写测试仿真文件验证其正确性。要求: ALU 支持 16 位的加、减、与、或以及移位运算。 2. 使用 Veril

    2024年02月01日
    浏览(26)
  • stm32的BRR寄存器和BSRR寄存器

    1、BRR---   bit   RESET(置0)  register   //高16位无,低16位置1为0,不能写1 2 、BSRR---   bit   SET(设置1或0)       register   //低16位设置1为0 BSRR:用于低16位的作用是让指定的IO口置1;而高16位的作用是让指定的IO口置0。  

    2024年02月11日
    浏览(38)
  • 硬盘、内存、缓存(CPU)和寄存器 空间大小与存取速度的区别及设计原理

    很多人会将 寄存器 与 存储器 二者混淆,认为它们是同一个东西。但并不是!! 寄存器是CPU上的一个模块 存储器是 内存+硬盘的统称 CPU(包含寄存器,缓存)    内存    硬盘 内存和硬盘之间的速度,差 3~4 个数量级;寄存器和内存之间的速度也差了 3~4 个数量级。       

    2024年03月22日
    浏览(38)
  • STM32之寄存器

    在学习STM32之前有必要了解一下ARM架构,以下相关ARM架构的知识来自百度百科​:​ ARM架构,曾称进阶精简指令集机器(Advanced RISC Machine)更早称作Acorn RISC Machine,是一个32位精简指令集(RISC)架构。还有基于ARM设计的派生产品,重要产品包括Marvell的XScale架构和德州仪器的

    2024年02月22日
    浏览(41)
  • 32-ADC的寄存器

    目录 stm32-adc通过比较获取电压原理 为什么会分注入组和规则组? “ECO\\\"是指\\\"Engineering Change Order”,即工程变更指令。 双ADC的不同模式以及为什么会有这个模式: 同步注入模式: 同步规则模式: 快速交叉模式: 慢速交叉模式  交替触发: 间断模式: 独立模式: 为什么ad

    2024年02月16日
    浏览(23)
  • STM32寄存器点亮LED灯

     这个灯是 PB5引脚 看原理图可以看出 让GPIOB5输出低电平 就能点亮 那么我们得让 打开控制GPIOB5的时钟 让GPIOB5 输出模式 让GPIOB5低电平 时钟就相当于一个阀门开关,或者理解成水龙头,你打开了 才有水出来,也就是你打开才能工作。 看中文参考手册 系统架构 找到你的GPIO

    2024年02月07日
    浏览(43)
  • STM32 入门 —— 寄存器与 GPIO

    STM32 总线构图: 什么是寄存器 根据百度百科介绍,寄存器是中央处理器内的组成部分。寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和地址。简单来说,寄存器就是存放东西的东西,存放的东西是指令、数据或地址 存放数据的寄存器最容易理解,不同

    2024年02月04日
    浏览(40)
  • STM32 寄存器配置笔记——GPIO配置输出

           本文主要介绍GPIO 作为输出时的寄存器配置。包括时钟配置,输出模式配置。以STM32F10xxx系列为例,配置PA8、PD2端口作为输出,输出高/低电平。         1)GPIO外设时钟          通过查找STM32F10xxx中文参考手册得知,GPIO PORT口的时钟配置在RCC_APB2ENR寄存器的第2~6位,

    2024年01月24日
    浏览(59)
  • STM32-ADC电压采样实验(寄存器版)

    STM32F10X系列支持三路ADC,其ADC通道及对应IO口如下表所示: 其能接受的电压输入范围一般为0-3.3V(V REF- ≤ V IN ≤ V REF+ ),因此,如果需要测量超出0-3.3v量程范围的电压数据,需要在外围硬件增加分压电阻,将电路转换到0-3.3V量程范围内再进行采集。 这里用于做ADC采集的引脚使

    2024年02月15日
    浏览(46)
  • STM32的GPIO操作(寄存器&HAL)

    (注:此为乐某学习记录,若有出错的地方欢迎各位指出!) 本人使用的开发板的芯片是STM32H743XIH6,所以外设也是根据此芯片来介绍。 在使用HAL库配置的时候,需要安装STM32CubeMX。此软件可在ST官网下载,剩下的安装步骤比较简单,不会单独出篇进行讲解。 STM32CubeMX下载网址

    2024年02月04日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包