首页 > 其他分享 >简易CPU设计入门:译码模块(一)

简易CPU设计入门:译码模块(一)

时间:2024-11-05 23:21:05浏览次数:3  
标签:decode en 信号 译码 instruct 模块 CPU 入门

项目代码下载

还是请大家首先准备好本项目所用的源代码。如果已经下载了,那就不用重复下载了。如果还没有下载,那么,请大家点击下方链接,来了解下载本项目的CPU源代码的方法。

下载本项目代码

准备好了项目源代码以后,我们接着去讲解。

本节前言

有一段时间没写本专栏的教程了。在之前的章节里,我是讲解了系统初始化模块和取指令模块。取完了指令以后,我们来讲解译码模块。

一.   代码展示

首先呢,让我们来看一看译码模块的全部代码。

module decode_unit
(
	input wire sys_clk,
	input wire sys_rst_n,
	input wire decode_en,
	input wire [15:0] instruct_word,
	
	output reg decode_done,
	output reg [4:0] op_code,
	output reg [2:0] reserve_bit,
	output reg [7:0] op_rand
);

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
	begin
		decode_done <= 1'b0;
		op_code <= 5'h0;
		reserve_bit <= 3'h0;
		op_rand <= 8'h0;
	end
	else if (decode_en == 1'b1)
	begin
		decode_done <= 1'b1;
		op_code <= instruct_word[15:11];
		reserve_bit <= 3'h0;
		op_rand <= instruct_word[7:0];
	end
	else
	begin
		decode_done <= 1'b0;
		op_code <= op_code;
		reserve_bit <= reserve_bit;
		op_rand <= op_rand;
	end

endmodule

不知道,是否因为,我学习电子学的Verilog HDL与数字电路的时间太短。我写完了译码模块以后,我自己都没想到,没想到译码单元竟然是这么少。译码模块,就是传说中的译码器。

在我这里,译码器模块,只有37行。

上面的代码块中的代码,位于【\cpu_me01\code】路径里面,代码文件的名字为【decode_unit.v】。

二.   输入信号

我们来看一看代码中的输入信号。

图1

图1中的3到6行,便是输入信号了。第3行与第4行,这俩是系统时钟与系统复位信号。其中,系统复位信号为低电平有效。值得关注的是第5行和第6行的译码使能信号【decode_en】与指令字信号【instruct_word】。

首先,我来说一说【字】的概念。在英特尔汇编里面,字可以指一种数据类型,它是16比特长度的整数,也就是相当于C语言中的【unsigned short】。而在学习一些个计算机技术领域的英文文档时,字往往是指连续多个比特组成的数据结构,它可能是一个字节的长度,也有可能是多个字节的长度。

在计算机技术里面,谈到字,首先它是有着一定的长度的,由连续的比特构成。第二,比特组合里面,它有着一定的格式。不同的位,或者不同的位的组合,会代表着不同的含义。

本节所述的指令字【instruct_word】,它是16位的长度,和汇编语言中的字型数据的长度相同。在这个16位的长度的比特组合里面,它包含有3个组成部分,分别是操作码,操作数和保留位。至于说,是怎么包含的,我们以后再讲。

译码使能信号【decode_en】和指令字信号【instruct_word】均来自于取指令模块的输出信号。我们来看一看它们的生成于连接情况。

图2,取指令模块

本模块中的译码信号【decode_en】和指令字信号【instruct_word】分别对应着取指令模块中的译码使能信号【decode_en】和指令码【instruct_code】信号。

从图2可以看出,当取指令模块检测到【rd_en_d1】为1的时候,取指令模块中的【decode_en】变为高电平,同时【instruct_code】信号被赋值为有效的值。还可以看到,取指令模块中的【decode_en】信号和【instruct_code】信号同时变为有效,并且译码使能信号【decode_en】仅仅维持一个时钟周期。

图2显示了取指令模块的【decode_en】和【instruct_code】信号的生成情况。接下来,我们去本项目的顶层模块【cpu_top】中查看一下连接情况。

图3,本项目顶层设计模块【cpu_top】

在图3里面,我们可以看到,我在顶层模块里面申请的几个用于连接不同模块的变量。其中呢,红色框线所示的第13行和第14行,显示了我所声明的译码使能【decode_en】信号和指令字信号【instruct_word】。

我们接着看。

图4,本项目顶层设计模块【cpu_top】

图4中,我们可以看到,取指令模块的【decode_en】和【instruct_code】信号,分别连接到顶层模块的【decode_en】和【instruct_word】变量。

我们接着看。

图5,本项目顶层设计模块【cpu_top】

如图5的红色框线所示,顶层模块中的【decode_en】与【instruct_word】分别连接到本模块的同名信号。

这样一来,我们就清楚了本模块的输入信号【decode_en】与【instruct_word】的来源了。

三.    输出信号

讲完了输入信号以后,我们再来讲解输出信号。

图1,副本

在图1副本中,我们去看8到11行的代码。这里呢,包括两部分,第一部分呢,是译码完成信号【decode_done】,第二部分,是对输入的指令字的分解出来的各部分信号,分别是操作码【op_code】,操作数【op_rand】,还有保留位。

我们还是来看一下代码。

图6,本模块的输出信号的逻辑代码

在图6中,主要是输出信号的逻辑。我们首先来看译码完成信号【decode_done】。它的逻辑,根据图6的代码,我们可以看到,当系统复位信号为低电平有效时,它是0值。当系统监测到输入信号译码使能【decode_en】为1时,译码使能信号【decode_done】被非阻塞赋值为1。然后呢,在else分支里面,【decode_done】又变为了0值。输入信号中的译码使能信号【decode_en】仅仅是维持一个时钟周期的高电平,所以呢,本模块中的【decode_done】信号也是仅仅维持着一个时钟的高电平。

也就是说,本模块的输出信号,译码完成信号【decode_done】,也是仅仅维持一个时钟周期的高电平。仅当检测到输入信号,译码使能信号【decode_en】为1时,译码完成信号【decode_done】才变为1,且仅仅维持一个时钟周期的高电平,随即又变为0值。

说完了这个译码完成信号以后,我们再来说其余的三个输出信号。

在输入信号里面,指令字信号【instruct_word】是一个16比特的信号。对于这个信号,本模块,也就是译码模块,需要将其分为三个部分。第一部分,是它的位15到位11,这一部分,我们要将其提取出来,并赋给输出信号,操作码【op_code】。第二部分,是位10到位8,我们忽略这三位的信号值,并固定地,将【3'h0】赋给输出信号,保留位【reserve_bit】。第三部分,是位7到位0,我们要将其提取出来,并赋给输出信号,操作数【op_rand】。

我们来看一看图6中,关于【op_code】,【reserve_bit】与【op_rand】的情形,基本上与我的讲述是一致的。。

操作码【op_code】,保留位【reserve_bit】和操作数【op_rand】,在系统复位信号为有效的低电平时,均为0值。而在检测到高电平有效的译码使能信号【decode_en】以后,将输入的指令字信号【instruct_word】的位选 [15:11] 赋给了【op_code】,将保留位 【reserve_bit】设置为固定的【3'h0】,将【instruct_word】的位选 [7:0] 赋给了【op_rand】。当仅仅维持一个有效的高电平信号,译码使能信号变为低电平时,操作码【op_code】,保留位【reserve_bit】和操作数【op_rand】维持不变。

 四.    本模块总体逻辑

本模块的总体逻辑其实很简单。就是将输入信号【instruct_word】的位选 [15:11] 与位选 [7:0] 提取出来,并分别赋给操作码信号【op_code】和操作数信号【op_rand】。而对于保留位,则固定地将其设置为【3'h0】。

本模块的逻辑还是很简单的。

结束语

到了这里,本节也就该结束了。然后呢,按照以往的经验,我们又该去编写验证代码了。这一块,我觉得,其实写不写验证都是那么回事。因为本模块的逻辑真的很简单。

对于本模块,我就不去写test bench代码了。

验证代码虽然不写了,我们还是会有其他的任务。

到了这里,由于取指令和译码模块,我都讲完了,我也讲过了本项目的机器码格式,那么,接下来,我打算来讲一讲,我在本系统里面,往指令ram中写入了哪些指令。

下一节开始,我们要来看一看,本系统所要执行的几条机器指令。当然了,在后面,我也会讲到,如何来将你想要去执行的指令,写入指令ram中。

本节结束。

标签:decode,en,信号,译码,instruct,模块,CPU,入门
From: https://blog.csdn.net/2401_82825368/article/details/143243975

相关文章

  • 树形 dp / 换根 dp 入门小记
    背景4.14打abc的时候一眼e题是换根模板,但是我不会,于是就来补档了。什么是树形dp/换根dp一种在树上的dp,一般用dfs进行状态转移。树形dp一般用儿子来更新父亲的答案。换根dp一般在第二次dfs时用父亲的答案转移到儿子去。引入经典树形dp例题:没有上司的舞......
  • LPC1100 系列_1.简介与入门
    1.简介与入门1.1LPC1100系列概述LPC1100系列是NXP推出的一款基于ARMCortex-M0内核的低功耗、高性能单片机。该系列单片机适用于各种嵌入式应用,包括传感器网络、工业控制、消费电子和医疗设备等。LPC1100系列的主要特点包括:低功耗:具有多种低功耗模式,适用于电池......
  • JWT令牌——从入门到精通
    一、跨域认证的问题互联网服务离不开用户认证。一般流程是下面这样。1、用户向服务器发送用户名和密码。2、服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等等。3、服务器向用户返回一个session_id,写入用户的Cookie。4、用户随后的每一......
  • 静态库、动态库、framework、xcframework、use_frameworks!的作用、关联核心SDK工程和
    1.1库的概念库:程序代码的集合,编译好的二进制文件加上头文件供使用,共享程序代码的一种方式。1.2库的分类根据开源情况分为:开源库(能看到具体实现)、闭源库(只公开调用的的接口,是编译后的二进制文件,看不到具体实现,使用时链接即可。)闭源库分为:动态库.td(之前叫.dylib)或.framework......
  • Nop入门: 动态SQL管理
    Nop平台提供了类似MyBatis的动态SQL管理能力,但是功能特性远比MyBatis丰富、强大。同时它的实现反而更加简单,在NopORM的基础上实现SqlLibManager只需要300多行的代码。一.使用说明1.1增加一个sql-lib.xml文件<!--/nop/demo/sql/demo.sql-lib.xml--><sql-libx:schema......
  • rust学习二、入门之运行单个脚本
    入门者,在搭建好环境好之后,接下来得先熟悉工具。有了趁手的工具,学起来才会快得多!作为入门者,非常希望能够单独运行一个rust脚本,而没有必要一个练习就建立一个项目。在https://crates.io上,我们可以找到各种各样的工具,有两个可以关注:cargo-script ,很不幸的是,这个项目自从2017年......
  • Java入门十二——static详解(含toString)
    上节课,我们只是微微提到了static,今天我们来具体讲讲static的用法static1.类名.静态成员变量(上篇博客Java入门十一有讲)为了方便大家查看,我把链接放在这里Java入门11——关键字总结+static-CSDN博客2.类名.静态成员方法这里,我们首先创建两个类,分别是java12和demo1,然后调用d......
  • 全网最详细大语言模型(LLM)入门学习路线图
    Github项目上有一个大语言模型学习路线笔记,它全面涵盖了大语言模型的所需的基础知识学习,LLM前沿算法和架构,以及如何将大语言模型进行工程化实践。这份资料是初学者或有一定基础的开发/算法人员入门活深入大型语言模型学习的优秀参考。这份资料重点介绍了我们应该掌握哪些核......
  • Go 语言变量类型:从入门到精通,一篇搞定所有知识点!
    Go语言变量类型1.基本类型1.1数值类型1.2布尔类型1.3字符串类型2.复合类型2.1数组2.2切片2.3字典(map)2.4结构体2.5接口3.类型转换4.零值5.示例1.基本类型Go语言中的基本类型主要包括数值类型、布尔类型和字符串类型。1.1数值类型整型:int:根据......
  • 挖漏洞怎么赚钱?挖漏洞入门到精通,收藏这篇就够了
    我就是一个最普通的网络安全工程师,出道快10年了,不出意外地遭遇到瓶颈期,但是凭技术在各大平台挖漏洞副业,硬是妥妥扛过来了。因为对于程序员来讲,这是个试错成本很低、事半功倍的选择。编程技能是一种强大生产力,决定程序员是一个高薪职业,同时由于技术迭代太快,决定程序员也是......