发个极简单8位CPU的实现代码,只有通用寄存器,IO指令,跳转指令和空指令,可以学习用~
如题,自己做的,还不完善,没RAM,只有通用寄存器,指令只有取指,IO指令,跳转指令和空指令(因为有这几个指令就可以FPGA验证in,out看结果了),自然没法用,可以给学习Verilog的同学和学习CPU结构的同学用~`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Engineer: LJT
// Create Date: 08:53:12 11/21/2010
// Module Name: top_modu
//////////////////////////////////////////////////////////////////////////////////
module top_modu(clk,rst,P1_IN,P1_OUT);
//IO Part
input clk;
input rst;
input P1_IN;
output P1_OUT;
//BUS
wire DB_IN; //data bus
wire DB_OUT;
wire ABUS; //address bus
wire CBUS; // ctrl bus
//各模块间互连线
wire irdb_out;
wire iodb_in;
wire iodb_out;
//Ctrl_Unit
ctrl_unit ctrl_unit (
.clk(clk),
.rst(rst),
.DB_IN(DB_IN),
.DB_OUT(DB_OUT),
.ABUS(ABUS),
.CBUS(CBUS)
);
//instruction rom
instru_rom instru_rom (
.clk(clk),
.addr(ABUS),
.db_out(irdb_out)
);
//bus interface module
bus_if_modu bus_if_modu (
.CBUS(CBUS),
.DB_IN(DB_IN),
.DB_OUT(DB_OUT),
.irdb_out(irdb_out),
.iodb_in(iodb_in),
.iodb_out(iodb_out)
);
//io interface
io_modu io_modu (
.clk(clk),
.db_in(iodb_in),
.db_out(iodb_out),
.P1_IN(P1_IN),
.P1_OUT(P1_OUT)
);
Endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: SDU
// Engineer: Lijiangtao
// Create Date: 22:28:42 11/16/2010
// Module Name: Ctrl_Unit
// Revision 0.01
//////////////////////////////////////////////////////////////////////////////////
module ctrl_unit(clk,rst,DB_IN,DB_OUT,ABUS,CBUS);
//IO part
input clk;
input rst;
input DB_IN;
output reg DB_OUT;
output reg ABUS;//address bus
output CBUS;
reg CBUS_IN;// ctrl bus in&out
reg CBUS_OUT;
assign CBUS=CBUS_IN;
assign CBUS=CBUS_OUT;
//important register
reg PC;
reg IR;
reg MSR;
//general reg
reg A;
reg B;
reg C;
reg D;
//Instruction Cycle Count
reg In_Cy;
//A Temp register
reg RTMP;
//instructions
parameter NOP = 8'b01100000;
parameter JMP = 8'b01100001;
parameter IN = 8'b01100010;
parameter OUT = 8'b01100011;
parameter MOV1 = 8'b10000001;
parameter MOV2 = 8'b10000010;
//4 bits, @bus address---挂在总线上的外设ID
parameter CUID = 4'h1; //Contrl Uint
parameter ROMID = 4'h6;//instrution@---Harward Architecture
parameter RAMID = 4'he;//data
parameter INID = 4'h4; //IO
parameter OUTID = 4'h5;
/////////////////////////////////////////////////////////////////////////////
//PC description
//In_Cy==1 取指; 0时 PC+1
always@(posedge clk)
begin
if(rst==1)
PC<=0;
else if(IR==JMP&&In_Cy==1)//JMP instruction
PC<=DB_IN;
else if(MSR==1||In_Cy==0) //取指 or 取操作数 --at next cycle
PC<=PC+1;
else
PC<=PC;
end
//In_Cy description: instruction cycle count
always@(posedge clk)
begin
if(rst==1)
In_Cy<=3;//In_Cy==0时,PC++,In_Cy==1时取指
else if(In_Cy==0)
In_Cy<=IR;
//IR设置为该指令的(执行周期数-1),不大于32条指令(实际上可以更多)的情况下可以减小译码所占用面积
else
In_Cy<=In_Cy-1;
end
//IR description : instruction register
always@(posedge clk)
begin
if(In_Cy==1) //取指
begin
IR<=DB_IN;
end
else
IR<=IR;
end
///////////////////////////////////////////////////////////////////////////////////
//Here Describ: reg ABCD, RTMP, ABUS, CBUS_IN, CBUS_OUT, DB_OUT , MSR
//the main frame is here
//the most important part of this deaign
//In_Cy-- 4:... 3:PC->abus 2:CBUS 1:取指 0:PC+1
///////////////////////////////////////////////////////////////////////////////////
always@(posedge clk)
begin
if(rst||In_Cy==2)//下周期取指
begin
CBUS_IN<=CUID;
CBUS_OUT<=ROMID;
MSR<=0;
ABUS<=PC;
end
else
begin
//指令译码
case (IR)
//在不同的机器周期(IN_CY)内执行不同的操作
//3时改变地址总线,2时选通指令存储器,1时取指,0时PC加1;
//2,1时无法执行其他操作,3,0时可以同时执行其他操作,但要注意地址总线和没变的PC值
NOP: case (In_Cy) //上次1时取指NOP,上次是0时incy被赋值1,然后直接取指下一条,因此在0时准备取指 4T
3'd0:
begin
CBUS_IN<=CUID;
CBUS_OUT<=ROMID;
end
3'd3:
begin
ABUS<=PC;
end
endcase
JMP: case (In_Cy) //上次1时取指JMP,上次是0时incy被赋值1,然后直接取指下一条 4T
3'd0: //准备取操作数
begin
CBUS_OUT<=ROMID;
CBUS_IN<=CUID;
end
3'd3: //操作数给PC在PC的描述里,取操作数--注意指令存储器的设计
begin
ABUS<=PC;
end
endcase
IN: case (In_Cy)//IN=>寄存器A 4T
3'd0:
begin
CBUS_OUT<=INID;
CBUS_IN<=CUID;
end
3'd3:
begin
A<=DB_OUT;
ABUS<=PC;
end
endcase
OUT: case (In_Cy) //取寄存器A,给OUT 4T
3'd0:
begin
CBUS_OUT<=CUID;
CBUS_IN<=OUTID;
DB_OUT<=A;
end
3'd3: //IO要在这个时钟周期锁存
begin
ABUS<=PC;
end
endcase
MOV1: case (In_Cy) //未完成
3'd0: //准备取操作数
begin
CBUS_OUT<=ROMID;
CBUS_IN<=CUID;
ABUS<=PC;
MSR<=1;
end
3'd4: //取操作数
begin
RTMP<=DB_IN;
MSR<=0;
CBUS_OUT<=INID;
CBUS_IN<=RAMID;
A<=DB_IN;
B<=DB_IN;
end
3'd3:
begin
CBUS_OUT<=RAMID;
CBUS_IN<=CUID;
ABUS<=PC;
MSR<=1;
C<=DB_IN;
D<=DB_IN; end
endcase
endcase //指令译码部分结束
end
end
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Engineer: LJT
//////////////////////////////////////////////////////////////////////////////////
module instru_rom(clk,addr, db_out);
input clk;
input addr;
output db_out;
wire addr11;
IN_ROM IN_ROM (
.addr_11(addr11),
.data_8(db_out),
.clk(clk)
);
assign addr11=0;
assign addr11=addr;
endmodule
module IN_ROM(addr_11,
data_8,
clk);
input clk;
input addr_11;
output data_8;
RAMB16_S9 #(
.INIT(9'h000),// Value of output RAM registers at startup
.SRVAL(9'h000), // Output value upon SSR assertion
.WRITE_MODE("WRITE_FIRST"), // WRITE_FIRST, READ_FIRST or NO_CHANGE
// The following INIT_xx declarations specify the initial contents of the RAM
// Address 0 to 511
.INIT_00(256'h62_63_62_63_61_00_61_00_61_00_00_00_00_00_0(后面全为0)
) RAMB16_S9_inst (
.DO(data_8), // 8-bit Data Output--------------------
.DOP(DOP), // 1-bit parity Output --to a reg
.ADDR(addr_11),// 11-bit Address Input-----------------change to 8bit,others 0.
.CLK(clk), // Clock
.DI(DI), // 8-bit Data Input --0
.DIP(DIP), // 1-bit parity Input--0
.EN(EN), // RAM Enable Input --1
.SSR(SSR), // Synchronous Set/Reset Input --0
.WE(WE) // Write Enable Input --0
);
//End of RAMB16_S9_inst instantiation
//assign addr_8=ADDR;
//assign ADDR=0;
assign DI=0;
assign DIP=0;
assign EN=1;
assign SSR=0;
assign WE=0;
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
// Create Date: 16:14:41 11/21/2010
// Module: Bus_Interface_Module
//////////////////////////////////////////////////////////////////////////////////
module bus_if_modu(CBUS,
DB_IN,DB_OUT,
irdb_out,//instru rom
iodb_in,iodb_out //io
);
input CBUS;
input DB_OUT;
output reg DB_IN;
input irdb_out;
input iodb_out;
output reg iodb_in;
//挂在总线上的外设ID
parameter CUID = 4'h1; //Contrl Uint
parameter ROMID = 4'h6;//instrution@---Harward Architecture
parameter RAMID = 4'he;//data
parameter INID = 4'h4; //IO
parameter OUTID = 4'h5;
always @ (CBUS) begin
case (CBUS)
ROMID: DB_IN <= irdb_out;
INID:DB_IN <= iodb_out;
RAMID: DB_IN <= irdb_out;
endcase
end
always @ (CBUS) begin
case (CBUS)
OUTID: iodb_in <= DB_OUT;
RAMID: iodb_in <= DB_OUT;
endcase
end
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Design Name:
// Module Name: io_modu
//////////////////////////////////////////////////////////////////////////////////
module io_modu(clk,
db_in,
db_out,
P1_IN,
P1_OUT
);
input clk;
input P1_IN;
input db_in;
output reg P1_OUT;
output reg db_out;
always@(posedge clk)
begin
P1_OUT<=db_in;
db_out<=P1_IN;
end
endmodule 做个简单的 讲解或贴个仿真图就更好了 想起来ZPU,是个很小的堆栈机 学习,正想学习学习CPU的结构自己写代码 学习不错!不过可以看看FREEARM的代码,几千行的代码,就可以用FPGA跑UCLINUX了 收藏 怎么不是用VHDL写的呢?Verilog没有学过呀! 回复【4楼】jiangchun9981
学习不错!不过可以看看freearm的代码,几千行的代码,就可以用fpga跑uclinux了
-----------------------------------------------------------------------
这么犀利。。。。。我看看 楼主威武。。 楼主不错,能做个图文解说就更好了 回复【9楼】.oOo.
楼主不错,能做个图文解说就更好了
-----------------------------------------------------------------------
主要的部分注释写的很详细 ,而且又简单, 呵呵。应该比较容易看懂 我想问楼主,P1_IN P1_OUT 在外部是同一个引脚么?还是单独的?
最近在搞CPLD的INOUT,老是出问题~ 可以,加油! 收藏,有空学习下! 回复【11楼】yuyu87 雨
我想问楼主,p1_in p1_out 在外部是同一个引脚么?还是单独的?
最近在搞cpld的inout,老是出问题~
-----------------------------------------------------------------------
这个是单独的
一般INOUT子模块内还是in和out单独的,外面加个三态门控制成INOUT吧
页:
[1]