国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

FPGA純verilog代碼實(shí)現(xiàn)8位精簡指令集CPU,一學(xué)期的微機(jī)原理不如看懂這套代碼,提供工程源碼和技術(shù)支持

這篇具有很好參考價值的文章主要介紹了FPGA純verilog代碼實(shí)現(xiàn)8位精簡指令集CPU,一學(xué)期的微機(jī)原理不如看懂這套代碼,提供工程源碼和技術(shù)支持。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報違法"按鈕提交疑問。

1、前言

本文章主要針對大學(xué)本科階段學(xué)生;
讀文章之前先來幾個靈魂拷問:
1、你是否學(xué)過《微機(jī)原理》、《單片機(jī)》、《匯編語言》之類有關(guān)微型計算機(jī)的課程?
2、上這些課時你的老師是否只是機(jī)械的講著PPT,你聽著無聊,聽不懂,逐漸對計算機(jī)專業(yè)產(chǎn)生了畏懼?
3、這些計算機(jī)專業(yè)的基礎(chǔ)課程你學(xué)懂了嗎?悟了嗎?真正理解了嗎?
4、這些課里面的專業(yè)術(shù)語你理解嗎?寄存器、總線、累加器。。。
以上4條都真正理解的人少之又少,你上學(xué)時怎么都理解不了,出來上班后就逐漸理解了,這是為啥呢?
因?yàn)樯蠈W(xué)時你面對的是枯燥的課本和混日子至念PPT的老師,加之這些東西都是抽象的沒有實(shí)物,你只能靠腦子想象,所以難以理解;
出來上班后你面對的是代碼,電路,板子,項(xiàng)目,以及公司里的大佬,你接觸的是實(shí)實(shí)在在的東西,所以沒有距離感,你天天敲著代碼,書本里的寄存器什么的都是你敲出來的,加之專業(yè)的大佬給你指點(diǎn)明津,所以你很容易就理解了;

2、設(shè)計思想和架構(gòu)

本設(shè)計采用純verilog代碼編寫,可在FPGA上綜合、編譯、運(yùn)行,起實(shí)質(zhì)就是一個小型CPU;
主要參數(shù)如下:
8位數(shù)據(jù)總線;
8位地址總線;
2位控制總線;
256字節(jié)ROM;用于存放cpu指令;
256字節(jié)RAM;用于存放cpu數(shù)據(jù);
1字節(jié)的cache,用于存放cpu計算的中間結(jié)果和預(yù)取;
32字節(jié)通用計算器,用于暫存cpu計算的中間結(jié)果;
2字節(jié)指令寄存器,用于暫存cpu指令和預(yù)取;
CPU功能很簡單,取ROM里面的65、66、67地址的三個常數(shù)累加和并輸出,整個過程由CPU自動完成,功能雖然簡單,卻涵蓋了計算機(jī)架構(gòu)的基本內(nèi)容和操作順序,后續(xù)的功能強(qiáng)大的CPU,也是由這樣簡單的計數(shù)慢慢發(fā)展起來的,其實(shí)CPU的本質(zhì)是很笨的,他只會最簡單的1+1的數(shù)學(xué)題,小學(xué)生水平都不如,只不過他的計算速度很快,顯得很聰明而已,當(dāng)你看懂了代碼就會明白,計算機(jī)真的很蠢。
設(shè)計架構(gòu)如下:
FPGA純verilog代碼實(shí)現(xiàn)8位精簡指令集CPU,一學(xué)期的微機(jī)原理不如看懂這套代碼,提供工程源碼和技術(shù)支持
由于線太多不好連接,就畫了一個框架;后面會一一講解;

3、硬件組成講解

ROM用于存儲要執(zhí)行的指令;指令采用精簡指令集;
我們定義的RISC指令集長度類型兩種,分別為短指令和長指令:
FPGA純verilog代碼實(shí)現(xiàn)8位精簡指令集CPU,一學(xué)期的微機(jī)原理不如看懂這套代碼,提供工程源碼和技術(shù)支持
其中指令編碼采用三位二進(jìn)制表示,共定義有8種指令。短指令共8位,高三位為指令編碼,低五位為通用寄存器地址。長指令為16位,每個長指令分兩次取,每次取8位,首先取高8位,格式和短指令相通,也是高3位為指令編碼,低5位為通用寄存器地址;第二次取低8位,表示ROM或者RAM地址,取決于指令編碼。
所謂的指令集,聽著很高級,其實(shí)就這么簡單,就是認(rèn)為規(guī)定的一些協(xié)議而已;
因此有指令集如下表所示,為了方便理解指令的縮寫含義,表中用英文進(jìn)行了描述并將縮寫的由來使用加粗來表示:

//rom存儲的是指令集
//短指令(8bit): 高三位為指令編碼,低五位為通用寄存器地址
//3'b000 -->NOP 空操作
//3'b001 -->LDO Loads the contents of the ROM address into the REG address
//3'b010 -->LDA Loads the contents of the RAM address into the REG address
//3'b011 -->STO Store intermediate results into RAM address
//3'b100 -->PRE Prefetch Data from REG address
//3'b101 -->ADD Adds the contents of the REG address or integer to the accumulator
//3'b110 -->LDM Load Multiple
//3'b111 -->HLT 停機(jī)指令

ROM頂層接口如下:

module cpu_rom #(
	parameter ADD_NUMBER_0 = 37,	//測試的第一個累加數(shù)
	parameter ADD_NUMBER_1 = 89,	//測試的第二個累加數(shù)
	parameter ADD_NUMBER_2 = 53		//測試的第三個累加數(shù)
)
(
	input        i_rom_read, 
	input        i_rom_ena ,
	input  [7:0] i_rom_addr,
	output [7:0] o_rom_data
);

ROM,只讀指令。接受輸入地址,當(dāng)讀信號和使能信號高電平時輸出對應(yīng)地址存儲的指令,否則輸出保持高阻態(tài)。地址和數(shù)據(jù)都是8位,可尋址以及內(nèi)部存儲的大小為256Bytes。

RAM存儲數(shù)據(jù),可讀可寫;接收8位地址,當(dāng)讀信號和使能信號有效時,輸出對應(yīng)地址存儲的數(shù)據(jù),否則輸出保持高阻態(tài)。當(dāng)寫信號上升沿是觸發(fā),將輸入輸出寫入地址對應(yīng)位置。內(nèi)部存儲以及可循址大小也為256Byters。
RAM頂層接口如下:

module cpu_ram(
	input       i_ram_ena  , 
	input       i_ram_read , 
	input       i_ram_write,
	input [7:0] i_ram_addr ,
	inout [7:0] io_ram_data 
);

cpu_PC程序計數(shù)器,有時也叫做指令地址寄存器(Instruction Address Register, IAR),對應(yīng)于Intel X86體系CPU中的指令指針(Instruction pointer)寄存器。其功能是用來存放要執(zhí)行的下一條指令在現(xiàn)行代碼段中的偏移地址。本文中PC由Controller自動修改,使得其中始終存放著下一條將要執(zhí)行指令的地址。因此,PC是用來控制指令序列執(zhí)行流程的寄存器。
cpu_PC頂層接口如下:

module cpu_PC(
	input            clk    , 
	input            rstn     , 
	input            i_en     ,
	output reg [7:0] o_pc_addr
);

異步清零。時鐘上升沿觸發(fā),高電平使能時程序計數(shù)器計數(shù),指向下一條要執(zhí)行指令的地址。指令存儲在ROM中,故每次pc_addr加1。

cpu_cache一級緩存,用于儲存計算的中間結(jié)果。
cpu_cache頂層接口如下:

module cpu_cache( 
	input            clk   ,
	input            rstn  ,
	input            i_ena ,
	input [7:0]      i_data,
	output reg [7:0] o_data
);

異步清零。時鐘上升沿觸發(fā),高電平使能時輸出當(dāng)前輸入信號。

cpu_addr_mux地址選擇器,接受控制使能信號對輸入的來自程序計數(shù)器和指令寄存器的地址進(jìn)行選擇;
cpu_addr_mux頂層接口如下:

module cpu_addr_mux(
	input [7:0]  i_ir_ad, 
	input [7:0]  i_pc_ad,
	input        i_addr_sel  ,
	output [7:0] o_addr_bus 
); 

當(dāng)選擇信號為1時,選擇來自寄存器輸入的地址到數(shù)據(jù)總線,否則將程序計數(shù)器中的地址加載到數(shù)據(jù)總線。

cpu_ALU算術(shù)邏輯運(yùn)算單元,根據(jù)指令類型來決定進(jìn)行哪種運(yùn)算,從而將運(yùn)算結(jié)果輸出通用寄存器或者累加器中。
cpu_ALU頂層接口如下:

module cpu_ALU(   
	input [2:0]      i_op     ,
	input [7:0]      i_alu_in ,
	input [7:0]      i_accum  ,
	output reg [7:0] o_alu_out
);

cpu_reg_32通用寄存器,ALU輸出結(jié)果,指令寄存器輸出的操作數(shù)都可以存儲到寄存器中的特定的地址。輸出寄存器中存儲的數(shù)據(jù)到數(shù)據(jù)總線。
cpu_reg_32頂層接口如下:

module cpu_reg_32(
	input        clk    ,
	input        i_write, 
	input        i_read , 
	input [7:0]  i_data ,
	input [7:0]  i_addr , 
	output [7:0] o_data 
);

當(dāng)寫信號有效時,將輸入數(shù)據(jù)(來自ALU的輸出)存儲到寄存器中的特定地址。當(dāng)讀信號有效時,將寄存器中特定位置的數(shù)據(jù)輸出(到數(shù)據(jù)總線)。寄存器大小為32Bytes。

cpu_ins_reg指令寄存器,從數(shù)據(jù)總線上獲取數(shù)據(jù),根據(jù)輸入控制信號,根據(jù)指令類型將特定指令和地址輸出到ALU,通用寄存器和地址選擇器。
cpu_ins_reg頂層接口如下:

module cpu_ins_reg(
	input        clk  , 
	input        rstn ,
	input  [1:0] i_fetch,
	input  [7:0] i_data ,
	output [2:0] o_ins  ,
	output [4:0] o_ad1  ,
	output [7:0] o_ad2  
); 

異步清零。當(dāng)輸入控制信號為01時表示數(shù)據(jù)總線當(dāng)前為指令(形式為指令編碼+寄存器地址,見第三章),將其從ins和ad1輸出,當(dāng)控制信號為10時,表示當(dāng)前數(shù)據(jù)總線上的為數(shù)據(jù)(8位地址數(shù)據(jù),見第三章),將其從ad2輸出到地址選擇器。

cpu_controller控制器是系統(tǒng)的核心,具有以下功能:取指令,指令排隊(duì),讀寫操作數(shù),總線控制等。這里采用(Mealy型)有限狀態(tài)機(jī)(FSM)來實(shí)現(xiàn)控制器,指令存儲在ROM中來執(zhí)行,控制器接受外界時鐘和復(fù)位信號,控制器根據(jù)當(dāng)前狀態(tài)以及輸入進(jìn)行狀態(tài)的轉(zhuǎn)移。
根據(jù)指令的任務(wù),設(shè)計了如上圖所示的狀態(tài)轉(zhuǎn)移圖,從左至右依次為狀態(tài)Sidle,S0~S12。各個狀態(tài)的含義如下:
FPGA純verilog代碼實(shí)現(xiàn)8位精簡指令集CPU,一學(xué)期的微機(jī)原理不如看懂這套代碼,提供工程源碼和技術(shù)支持
cpu_controller頂層接口如下:

module cpu_controller(
	input       clk   , 
	input 	    rstn   ,   		// clock, reset
	input [2:0] i_ins   ,  		// i_instructions, 3 bits, 8 types
	// Enable signals
	output reg o_write_r, 
	output reg o_read_r , 
	output reg o_PC_en  ,	//控制地址總線, o_PC_en為高時地址總線+1
	output reg o_ac_ena , 
	output reg o_ram_ena, 
	output reg o_rom_ena,
	// ROM: where i_instructions are storaged. Read only.
	// RAM: where data is storaged, readable and writable.
	output reg o_ram_write  , 
	output reg o_ram_read   , 
	output reg o_rom_read   , 
	output reg o_ad_sel     ,
	output reg [1:0] o_fetch  	// 01: to o_fetch from RAM/ROM; 10: to o_fetch from REG
);

最后將各個高性模塊例化成一個頂層,頂層代碼如下:

module risc_8bit_cpu #(
	parameter ADD_NUMBER_0 = 20,	//測試的第一個累加數(shù)
	parameter ADD_NUMBER_1 = 40,	//測試的第二個累加數(shù)
	parameter ADD_NUMBER_2 = 6		//測試的第三個累加數(shù)
)(
	input        clk      , 
	input        rstn     ,
	output [7:0] o_cpu_out
);	

wire write_r, read_r, PC_en, ac_ena, ram_ena, rom_ena;
wire ram_write, ram_read, rom_read, ad_sel;

wire [1:0] fetch;	//控制總線
wire [7:0] data;	//地址總線 
wire [7:0] addr;	//數(shù)據(jù)總線
wire [7:0] accum_out, alu_out;
wire [7:0] ir_ad, pc_ad;
wire [4:0] reg_ad;
wire [2:0] ins;

assign o_cpu_out=accum_out;

//RAM存儲數(shù)據(jù),可讀可寫
cpu_ram u_cpu_ram(
	.io_ram_data(data     ), 
	.i_ram_addr(addr      ), 
	.i_ram_ena (ram_ena   ), 
	.i_ram_read(ram_read  ), 
	.i_ram_write(ram_write)
); 

//ROM用于存儲要執(zhí)行的指令,只讀
cpu_rom #(
	.ADD_NUMBER_0 (ADD_NUMBER_0),	//測試的第一個累加數(shù)
	.ADD_NUMBER_1 (ADD_NUMBER_1),	//測試的第二個累加數(shù)
	.ADD_NUMBER_2 (ADD_NUMBER_2)	//測試的第三個累加數(shù)	
)u_cpu_rom(
	.o_rom_data(data    ), 
	.i_rom_addr(addr    ), 
	.i_rom_ena (rom_ena ), 
	.i_rom_read(rom_read)
);					

//地址選擇器,接受控制使能信號對輸入的來自程序計數(shù)器和指令寄存器的地址進(jìn)行選擇
//sel-->1 輸出指令寄存器地址
//sel-->0 輸出程序計數(shù)器地址
cpu_addr_mux u_cpu_addr_mux(
	.o_addr_bus(addr  ), 
	.i_addr_sel(ad_sel), 
	.i_ir_ad   (ir_ad ), 
	.i_pc_ad   (pc_ad )
);					

//PC程序計數(shù)器,用來存放要執(zhí)行的下一條指令在現(xiàn)行代碼段中的偏移地址
//輸出地址總線的值
//PC_en為高時地址總線+1
cpu_PC u_cpu_PC( 
	.clk      (clk  ), 
	.rstn     (rstn ), 
	.i_en     (PC_en),
	.o_pc_addr(pc_ad)	
);						

//緩存,用于儲存計算的中間結(jié)果
cpu_cache u_cpu_cache(
	.o_data(accum_out), 
	.i_data(alu_out  ), 
	.i_ena (ac_ena   ), 
	.clk   (clk      ), 
	.rstn  (rstn     )
); 		

//算術(shù)邏輯運(yùn)算單元,根據(jù)指令類型來決定進(jìn)行哪種運(yùn)算,從而將運(yùn)算結(jié)果輸出通用寄存器或者累加器中
cpu_ALU u_cpu_ALU(
	.o_alu_out(alu_out  ), 
	.i_alu_in (data     ), 
	.i_accum  (accum_out), 
	.i_op     (ins      )
);				

//通用寄存器,ALU輸出結(jié)果,指令寄存器輸出的操作數(shù)都可以存儲到寄存器中的特定的地址。輸出寄存器中存儲的數(shù)據(jù)到數(shù)據(jù)總線
cpu_reg_32 u_cpu_reg_32(
	.i_data (alu_out     ), 
	.o_data (data        ), 
	.i_write(write_r     ), 
	.i_read (read_r      ), 
	.i_addr ({ins,reg_ad}), 
	.clk    (clk         )
);	

//指令寄存器,從數(shù)據(jù)總線上獲取數(shù)據(jù),根據(jù)輸入控制信號,根據(jù)指令類型將特定指令和地址輸出到ALU,通用寄存器和地址選擇器
//fetch==2'b01 operation1, to fetch data from RAM/ROM
//fetch==2'b10 operation2, to fetch data from REG 
cpu_ins_reg u_cpu_ins_reg(
	.i_data (data  ), 
	.i_fetch(fetch ), 
	.clk    (clk   ), 
	.rstn   (rstn  ), 
	.o_ins  (ins   ), 
	.o_ad1  (reg_ad), 
	.o_ad2  (ir_ad )
);	

//控制器,核心部分
cpu_controller u_cpu_controller(
	.i_ins      (ins      ), 
	.clk        (clk      ), 
	.rstn       (rstn     ), 
	.o_write_r  (write_r  ), 
	.o_read_r   (read_r   ), 
	.o_PC_en    (PC_en    ), 
	.o_fetch    (fetch    ), 
	.o_ac_ena   (ac_ena   ), 
	.o_ram_ena  (ram_ena  ), 
	.o_rom_ena  (rom_ena  ),
	.o_ram_write(ram_write), 
	.o_ram_read (ram_read ), 
	.o_rom_read (rom_read ), 
	.o_ad_sel   (ad_sel   )
);
				
endmodule

4、vivado仿真

仿真代碼如下:

`timescale 1ps / 1ps
module risc_8bit_cpu_tb  ; 

  parameter T=10;
  reg    rstn   ; 
  reg    clk    ; 
  
risc_8bit_cpu #(
	.ADD_NUMBER_0 (20),
	.ADD_NUMBER_1 (60),
	.ADD_NUMBER_2 (9 )	
)u_risc_8bit_cpu( 
	.rstn     (rstn),
	.clk      (clk ), 
	.o_cpu_out()
); 

initial begin
	rstn=0;
    clk=0;
	#100;
	rstn=1;
	#1000;
	$stop;
end

always #(T/2) clk=~clk;

endmodule

仿真結(jié)果如下:
FPGA純verilog代碼實(shí)現(xiàn)8位精簡指令集CPU,一學(xué)期的微機(jī)原理不如看懂這套代碼,提供工程源碼和技術(shù)支持
在testbench中我們填入的三個數(shù)如下:
FPGA純verilog代碼實(shí)現(xiàn)8位精簡指令集CPU,一學(xué)期的微機(jī)原理不如看懂這套代碼,提供工程源碼和技術(shù)支持
累加和等于89;仿真波形紅圈的計算結(jié)果也是89;功能正常;

下面改變輸入如下:
FPGA純verilog代碼實(shí)現(xiàn)8位精簡指令集CPU,一學(xué)期的微機(jī)原理不如看懂這套代碼,提供工程源碼和技術(shù)支持
此時累加和等于88,再仿真結(jié)果如下:
FPGA純verilog代碼實(shí)現(xiàn)8位精簡指令集CPU,一學(xué)期的微機(jī)原理不如看懂這套代碼,提供工程源碼和技術(shù)支持
仿真波形紅圈的計算結(jié)果也是88;功能正常;

5、vivado工程

開發(fā)板:Xilinx Artix7開發(fā)板;
開發(fā)環(huán)境:vivado2019.1;
輸出:led燈;
系統(tǒng)上電后cup核自動運(yùn)行,并輸出累加和,若輸出的累加和與輸入的一致則led等閃爍,否則led常滅;
工程頂層代碼如下:

module top(
	input  clk_in1_p,
	input  clk_in1_n,
	output led
);
	
parameter ADD_NUMBER_0 = 20;	//測試的第一個累加數(shù)
parameter ADD_NUMBER_1 = 60;	//測試的第二個累加數(shù)
parameter ADD_NUMBER_2 = 8;	//測試的第三個累加數(shù)
parameter CPU_SUM=ADD_NUMBER_0+ADD_NUMBER_1+ADD_NUMBER_2;

parameter SYS_TIME=100;
parameter SYS_TIPS=1000/SYS_TIME;
parameter LED_CYC_80MS=80000000/SYS_TIPS;

wire [7:0] o_cpu_out;
wire led_run;
reg [31:0] cnt;
assign led_run=(o_cpu_out==CPU_SUM)? 1'b1: 1'b0;
assign led= (cnt<LED_CYC_80MS/2)? 1'b0: 1'b1;

always @(posedge clk_100m) begin
	if(~rstn) cnt<='d0;
	else if(led_run) begin
		if(cnt<LED_CYC_80MS) cnt<=cnt+'d1;
		else cnt<='d0;
	end
	else cnt<='d0;
end

clk_wiz_0 u_clk_wiz_0
   (
    .clk_100m(clk_100m),     // output clk_100m
    .locked(rstn),       // output locked
    .clk_in1_p(clk_in1_p),    // input clk_in1_p
    .clk_in1_n(clk_in1_n)
);   

risc_8bit_cpu #(
	.ADD_NUMBER_0(ADD_NUMBER_0),	//測試的第一個累加數(shù)
	.ADD_NUMBER_1(ADD_NUMBER_1),	//測試的第二個累加數(shù)
	.ADD_NUMBER_2(ADD_NUMBER_2)		//測試的第三個累加數(shù)
)helai_risc_8bit_cpu(
	.clk      (clk_100m      ), 
	.rstn     (rstn     ),
	.o_cpu_out(o_cpu_out)
);	
endmodule

代碼架構(gòu)如下:
FPGA純verilog代碼實(shí)現(xiàn)8位精簡指令集CPU,一學(xué)期的微機(jī)原理不如看懂這套代碼,提供工程源碼和技術(shù)支持

6、上板調(diào)試驗(yàn)證

上板輸出演示視頻如下:

上板輸出演示視頻

7、福利:工程源碼獲取

福利:工程代碼的獲取
代碼太大,無法郵箱發(fā)送,以某度網(wǎng)盤鏈接方式發(fā)送,
資料如下:獲取方式:文章末尾的V名片。
網(wǎng)盤資料如下:
也可直接下載工程源碼,
點(diǎn)擊下載工程源碼
FPGA純verilog代碼實(shí)現(xiàn)8位精簡指令集CPU,一學(xué)期的微機(jī)原理不如看懂這套代碼,提供工程源碼和技術(shù)支持文章來源地址http://www.zghlxwxcb.cn/news/detail-502135.html

到了這里,關(guān)于FPGA純verilog代碼實(shí)現(xiàn)8位精簡指令集CPU,一學(xué)期的微機(jī)原理不如看懂這套代碼,提供工程源碼和技術(shù)支持的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包