代码部分:
module CPU(
input clk, //时钟
input reset, //复位
input [7:0]M_data_in,
output reg Wirte_read,
output [11:0]M_address,
output [7:0]M_data_out,
output reg overflow
);
//通用寄存器组
reg[7:0]R0;
reg[7:0]R1;
reg[7:0]R2;
reg[7:0]R3;
reg[11:0]PC; //程序计数器
reg[15:0]IR; //指令寄存器
reg [7:0]Acc; //累加寄存器/临时寄存器
reg [8:0]temp; //加减运算扩充符号位后的临时寄存器
reg [11:0]MAR; //内存地址寄存器
reg [7:0]MDR; //内存数据寄存器
assign M_address = MAR;
assign M_data_out = MDR;
//状态
localparam st_0 = 3'b000;
localparam st_1 = 3'b001;
localparam st_2 = 3'b010;
localparam st_3 = 3'b011;
localparam st_4 = 3'b100;
reg [2:0]status /*synthesis preserve*/;
//指令助记符
parameter Idle = 4'b0000;
parameter Load = 4'b0001;
parameter Move = 4'b0010;
parameter Add = 4'b0011;
parameter Sub = 4'b0100;
parameter AND = 4'b0101;
parameter OR = 4'b0110;
parameter XOR = 4'b0111;
parameter Shr = 4'b1000;
parameter Shl = 4'b1001;
parameter Swap = 4'b1010;
parameter Jmp = 4'b1011;
parameter Jz = 4'b1100;
parameter Read = 4'b1101;
parameter Write = 4'b1110;
parameter Stop = 4'b1111;
always @(*)
begin
if(status == st_3 && reset == 1'b1 && IR[15:12] == Write)
Wirte_read = 1'b1;
else
Wirte_read = 1'b0;
if(status == st_1 && reset == 1'b1 && (IR[15:12]==Add || IR[15:12]==Sub))
if(temp[8]^temp[7])
overflow = 1'b1;
else
overflow = 1'b0;
else overflow = 1'b0;
end
always @(posedge clk,negedge reset)
begin
if(reset == 1'b0)
begin
R0 = 8'b0000_0000;
R1 = 8'b0000_0000;
R2 = 8'b0000_0000;
R3 = 8'b0000_0000;
PC = 8'b0000_0000;
IR = 16'h0000;
MDR = 8'b0000_0000;
end
else
case(status)
st_0:
begin
IR[15:8] = M_data_in;
IR[7:0] = 8'b0000_0000;
if(IR[15:12] != 4'b1111)
PC = PC + 1'b1;
end
st_1:
begin
case(IR[15:12])
Idle:begin end
Load:begin
R0 = IR[11:8];
end
Move:begin
case(IR[11:10])
2'b00:R0 = Acc;
2'b01:R1 = Acc;
2'b10:R2 = Acc;
2'b11:R3 = Acc;
endcase
end
Add:begin
case(IR[11:10])
2'b00:begin
temp = {R0[7],R0}+{Acc[7],Acc};
R0 = temp[7:0];
end
2'b01:begin
temp = {R1[7],R1}+{Acc[7],Acc};
R1 = temp[7:0];
end
2'b10:begin
temp = {R2[7],R2}+{Acc[7],Acc};
R2 = temp[7:0];
end
2'b11:begin
temp = {R3[7],R3}+{Acc[7],Acc};
R3 = temp[7:0];
end
endcase
end
Sub:begin
//先求-Acc的补码,将补码减法变为补码加法 (x-y)补=x补+(-y)
//对于这里没有直接将-Acc的补码存在Acc寄存器里的解释:
//因为在时钟下降沿那个always块里有Acc的赋值,同一个寄存器的赋值不能出现在多个always语句里,会产生冲突
//虽然一个时钟上升沿一个时钟下降沿不会产生冲突,但是编译时仍会报错
//这也是为什么寄存器的清零一部分放在时钟上升沿时,一部分放在时钟下降沿时
temp[7:0] = ~Acc;
temp[7:0] = temp + 1'b1;
temp[8] = temp[7];
case(IR[11:10])
2'b00:begin
temp = {R0[7],R0}+temp;
R0 = temp[7:0];
end
2'b01:begin
temp = {R1[7],R1}+temp;
R1 = temp[7:0];
end
2'b10:begin
temp = {R2[7],R2}+temp;
R2 = temp[7:0];
end
2'b11:begin
temp = {R3[7],R3}+temp;
R3 = temp[7:0];
end
endcase
end
AND:begin
case(IR[11:10])
2'b00:R0 = R0 & Acc;
2'b01:R1 = R1 & Acc;
2'b10:R2 = R2 & Acc;
2'b11:R3 = R3 & Acc;
endcase
end
OR:begin
case(IR[11:10])
2'b00:R0 = R0 | Acc;
2'b01:R1 = R1 | Acc;
2'b10:R2 = R2 | Acc;
2'b11:R3 = R3 | Acc;
endcase
end
XOR:begin
case(IR[11:10])
2'b00:R0 = R0 ^ Acc;
2'b01:R1 = R1 ^ Acc;
2'b10:R2 = R2 ^ Acc;
2'b11:R3 = R3 ^ Acc;
endcase
end
Shr:begin
case(IR[11:10])
2'b00:R0 = R0 >>1;
2'b01:R1 = R1 >>1;
2'b10:R2 = R2 >>1;
2'b11:R3 = R3 >>1;
endcase
end
Shl:begin
case(IR[11:10])
2'b00:R0 = R0 <<1;
2'b01:R1 = R1 <<1;
2'b10:R2 = R2 <<1;
2'b11:R3 = R3 <<1;
endcase
end
Swap:begin
case(IR[9:8])
2'b00:case(IR[11:10])
2'b00:R0 = R0;
2'b01:R0 = R1;
2'b10:R0 = R2;
2'b11:R0 = R3;
endcase
2'b01:case(IR[11:10])
2'b00:R1 = R0;
2'b01:R1 = R1;
2'b10:R1 = R2;
2'b11:R1 = R3;
endcase
2'b10:case(IR[11:10])
2'b00:R2 = R0;
2'b01:R2 = R1;
2'b10:R2 = R2;
2'b11:R2 = R3;
endcase
2'b11:case(IR[11:10])
2'b00:R3 = R0;
2'b01:R3 = R1;
2'b10:R3 = R2;
2'b11:R3 = R3;
endcase
endcase
end
Jmp:begin end
Jz:begin end
Read:begin end
Write:begin end
Stop:begin end
endcase
end
st_2:
begin
case(IR[15:12])
Swap:
case(IR[11:10])
2'b00:R0 = Acc;
2'b01:R1 = Acc;
2'b10:R2 = Acc;
2'b11:R3 = Acc;
endcase
Jmp:begin
IR[7:0] = M_data_in;
PC = PC +1'b1;
end
Jz:begin
IR[7:0] = M_data_in;
PC = PC +1'b1;
end
Read:begin
IR[7:0] = M_data_in;
PC = PC +1'b1;
end
Write:begin
IR[7:0] = M_data_in;
PC = PC +1'b1;
MDR = R0;
end
endcase
end
st_3:
begin
case(IR[15:12])
Jmp:PC = IR[11:0];
Jz:begin
if(R0==4'b0000)
PC = IR[11:0];
end
Read:begin end
Write:begin end
endcase
end
st_4:
begin
case(IR[15:12])
Read:R0 = M_data_in;
Write:begin end
endcase
end
endcase
end
always @(negedge clk,negedge reset)
begin
if(reset == 1'b0)
begin
status = st_0;
Acc = 8'b0000_0000;
MAR = 8'b0000_0000;
end
else
case(status)
st_0:
begin
MAR = PC;
case(IR[9:8])
2'b00:Acc = R0;
2'b01:Acc = R1;
2'b10:Acc = R2;
2'b11:Acc = R3;
endcase
status = st_1;
end
st_1:
begin
case(IR[15:12])
Swap:status = st_2;
Jmp:status = st_2;
Jz:status = st_2;
Read:status = st_2;
Write:status = st_2;
default:status = st_0;
endcase
end
st_2:
begin
case(IR[15:12])
Jmp:begin
MAR = IR[11:0];
status = st_3;
end
Jz:begin
if(R0 == 4'b0000)
MAR = IR[11:0];
else
MAR = PC;
status = st_3;
end
Read:begin
MAR = IR[11:0];
status = st_3;
end
Write:begin
MAR = IR[11:0];
status = st_3;
end
default:status = st_0;
endcase
end
st_3:
begin
case(IR[15:12])
Read:begin
MAR = PC;
status = st_4;
end
Write:begin
MAR = PC;
status = st_4;
end
default:status = st_0;
endcase
end
st_4:status = st_0;
endcase
end
endmodule
波形图部分:
(上图Load为2节拍,我之前写错了。。。这里忘了改了)
文章来源:https://www.toymoban.com/news/detail-536427.html
文章来源地址https://www.toymoban.com/news/detail-536427.html
到了这里,关于西南交通大学 计算机组成原理实验课程设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!