step1 分析命令:

 这十条命令为:CLA、COM、SHR、CSL、STP、ADD、STA、LDA、JMP、BAN
 实现这些命令所需的模块有:PC、ACC、ALU、CU、ROM、RAM

step2 分析模块:

 PC
由于PC需要增加停机功能和跳转功能,所以PC应该增加接口来实现停机与跳转指令。
 ACC
新增模块ACC,ACC为累加器,CLA、COM、SHR、CSL这四条指令直接操作ACC中的数据,ADD指令将ACC作为操作数,所以ACC应该有一个读数据、一个写数据、使写数据能的接口。(后期实验发现忘记给ACC加一个时钟控制信号了,不加时钟控制信号的话ACC中的数据会出错,一个时钟周期内可能被写两次。)
 CU
由于CU要控制ACC和PC完成指令,所以CU应该增加输出来控制ACC和PC。
 ALU
ALU需要完成对ACC最高位的判断,并将判断结果传送给PC以便PC完成BAN指令。
 其余模块无需改变

step3 新增模块图示:


step4 cpu数据通路设计:


除了图中画红线的其余名字一样的连到一起。

Step5 指令设计:

这次实验我将指令的位数更改为13位,[12:9]为操作码,[8:0]为立即数或地址。

Step6 模块设计:

PC:

1.   module PC(
2.      input clk,
3.      input rst,
4.      input stop,
5.      input ban,
6.      input p_wr_en,
7.      input wire [12:0] jmp,
8.      output reg [12:0] pc
9.      );
10.     reg state;
11.     initial begin
12.         pc=8'd0;
13.         state=1;
14.     end
15.     always@* begin
16.         if(stop==1)
17.             state<=0;
18.         if(rst==1)
19.             pc<=0;
20.     end
21.     always@(posedge clk) begin
22.         if(state==1)
23.             pc<=pc+1'd1;
24.     end
25.     always@(negedge clk) begin
26.         if(p_wr_en==1)
27.             pc<=jmp-1;
28.         if(ban==1)
29.             pc<=pc+jmp-1;
30.     end
31. endmodule

ROM:

1.   module ROM(
2.      input wire [12:0] pc,
3.      output reg [15:0] ins
4.      );
5.
6.      reg [15:0] ROM_data [255:0];
7.      integer i;
8.
9.      initial $readmemb("D:/vivadowork/TEN-CPU/ONE_CPU.srcs/sources_1/new/ROM_initial.txt",ROM_data);
10.
11.     always@(pc) begin
12.         ins<=ROM_data[pc];
13.     end
14. endmodule

RAM:

1.   module RAM(
2.      input clk,
3.      input m_wr_en,
4.      input wire [15:0] in_data,
5.      input wire [8:0] index,
6.      output wire [15:0] out_data
7.      );
8.
9.      reg [15:0] initdata [1023:0];
10.     integer i;
11.     initial $readmemb("D:/vivadowork/TEN-CPU/ONE_CPU.srcs/sources_1/new/RAM_initial.txt",initdata);
12.
13.     always@(posedge clk ) begin
14.         begin if (m_wr_en==0)
15.             initdata[index]<=in_data;
16.         end
17.     end
18.
19.     assign out_data=initdata[index];
20. endmodule

CU:

根据不同指令输出不同的数据来控制各个模块来完成指令。

1.   module CU(
2.      input wire [3:0] opcode,
3.      output reg p_wr_en,
4.      output reg m_wr_en,
5.      output reg a_wr_en,
6.
7.      output reg stop,
8.      output reg [3:0] alu_op
9.      );
10.     always@(opcode)begin
11.         case(opcode)
12.         4'b0001: begin //cla
13.             p_wr_en<=0;
14.             stop<=0;
15.             m_wr_en<=1;
16.             a_wr_en<=1;
17.             alu_op<=4'b0111;
18.         end
19.         4'b0010: begin//com
20.             p_wr_en<=0;
21.             stop<=0;
22.             m_wr_en<=1;
23.             a_wr_en<=1;
24.             alu_op<=4'b1000;
25.         end
26.         4'b0011: begin //shr
27.             p_wr_en<=0;
28.             stop<=0;
29.             m_wr_en<=1;
30.             a_wr_en<=1;
31.             alu_op<=4'b1001;
32.         end
33.         4'b0100: begin //csl
34.             p_wr_en<=0;
35.             stop<=0;
36.             m_wr_en<=1;
37.             a_wr_en<=1;
38.             alu_op<=4'b1010;
39.         end
40.         4'b0101: begin //stp
41.             p_wr_en<=0;
42.             stop<=1;
43.             m_wr_en<=1;
44.             a_wr_en<=0;
45.         end
46.         4'b0110: begin //add
47.             p_wr_en<=0;
48.             stop<=0;
49.             m_wr_en<=1;
50.             a_wr_en<=1;
51.             alu_op<=4'b0001;
52.         end
53.         4'b0111: begin //sta
54.             p_wr_en<=0;
55.             stop<=0;
56.             m_wr_en<=0;
57.             a_wr_en<=0;
58.
59.         end
60.         4'b1000: begin //lda
61.             p_wr_en<=0;
62.             stop<=0;
63.             m_wr_en<=1;
64.             a_wr_en<=1;
65.             alu_op<=4'b1011;
66.         end
67.         4'b1001: begin //jmp
68.             p_wr_en<=1;
69.             stop<=0;
70.             m_wr_en<=1;
71.             a_wr_en<=0;
72.         end
73.         4'b1010: begin //ban
74.             p_wr_en<=1;
75.             stop<=0;
76.             m_wr_en<=1;
77.             a_wr_en<=0;
78.             alu_op<=4'b1100;
79.         end
80.         endcase
81.     end
82. endmodule

ALU:

1.   module ALU(
2.      input wire[15:0] in1,
3.      input wire[15:0] in2,
4.      input wire[3:0] alu_op,
5.      output reg ban,
6.      output reg[15:0] z
7.      );
8.      always @(*)
9.      begin
10.     case(alu_op)
11.     4'b0001: z<=in1+in2;
12.     4'b0010: z<=in1-in2;
13.     4'b0011: z<=in1&in2;
14.     4'b0100: z<=in1|in2;
15.     4'b0101: z<=in1<<in2;
16.     4'b0110: z<=in1>>in2;
17.     4'b0111: z<=0; //cla
18.     4'b1000: z<=~in1; //com
19.     4'b1001: z<={{in1[15]},in1[15:1]}; //shr
20.     4'b1010: z<={{in1[14:0]},in1[15]}; //csl
21.     4'b1011: z<=in2;
22.     4'b1100: ban<=in1[15]==1 ? 1 : 0;
23. //    4'b0111: z<={{6{imm[8]}},imm}+in1;
24. //    4'b1000: z<=out_data;
25.     endcase
26.     end
27. endmodule

ACC:

1.   module ACC(
2.      input a_wr_en,
3.      input clk,
4.      input wire [15:0]in_data,
5.      output wire [15:0]acc_data
6.      );
7.      reg [0:15]acc;
8.      initial begin
9.          acc=16'd0;
10.     end
11.     assign acc_data=acc;
12.     always@( posedge clk)
13.     begin
14.         if(a_wr_en==1)
15.             acc=in_data;
16.     end
17.
18.
19. endmodule

顶层封装:

1.   module CPU(
2.      input clk,
3.      input rst,
4.      output stop,
5.      output ban,
6.      output p_wr_en,
7.      output a_wr_en,
8.      output wire [12:0] pc,
9.      output wire [15:0] ins,
10.     output wire [3:0] alu_op,
11.     output m_wr_en,
12.     output wire [15:0] z,
13.     output wire [15:0]acc_data,
14.     output wire [15:0]out_data
15.     );
16.
17.
18.     PC f_pc(
19.         .clk(clk),
20.         .rst(rst),
21.         .pc(pc),
22.         .stop(stop),
23.         .ban(ban),
24.         .p_wr_en(p_wr_en),
25.         .jmp({{4{ins[8]}},ins[8:0]}));
26.
27.     ROM f_rom(
28.         .pc(pc),
29.         .ins(ins));
30.
31.     RAM f_ram(
32.         .clk(clk),
33.         .m_wr_en(m_wr_en),
34.         .in_data(acc_data),
35.         .index(ins[8:0]),
36.         .out_data(out_data)
37.         );
38.
39.     CU f_cu(
40.         .opcode(ins[12:9]),
41.         .p_wr_en(p_wr_en),
42.         .a_wr_en(a_wr_en),
43.         .stop(stop),
44.         .alu_op(alu_op),
45.         .m_wr_en(m_wr_en) //
46.         );
47.
48.     ALU f_alu(
49.         .ban(ban),
50.         .in1(acc_data),
51.         .in2(out_data),
52.         .alu_op(alu_op),
53.         .z(z)
54.         );
55.
56.     ACC f_acc(
57.         .a_wr_en(a_wr_en),
58.         .clk(clk),
59.         .in_data(z),
60.         .acc_data(acc_data)
61.         );
62. endmodule

Step6 模拟仿真

1. 仿真文件


1.  module test_CPU;
2.      reg clk;
3.      reg rst;
4.      wire stop;
5.      wire ban;
6.      wire p_wr_en;
7.      wire a_wr_en;
8.      wire [12:0] pc;
9.      wire [12:0] ins;
10.     wire m_wr_en;
11.     wire [3:0] alu_op;
12.     wire [15:0] z;
13.     wire [15:0] out_data;
14.     wire [15:0] acc_data;
15.
16.     initial begin
17.         clk=1'd0;
18.         forever #10 clk=~clk;
19.     end
20.
21.     initial begin
22.         rst=1'd0;
23.         #120 $stop;
24.     end
25.
26.     CPU test(
27.         .clk(clk),
28.         .rst(rst),
29.         .stop(stop),
30.         .ban(ban),
31.         .p_wr_en(p_wr_en),
32.         .acc_data(acc_data),
33.         .z(z),
34.         .pc(pc),
35.         .ins(ins),
36.         .a_wr_en(a_wr_en),
37.         .alu_op(alu_op),
38.         .m_wr_en(m_wr_en),
39.         .out_data(out_data)
40.         );
41. endmodule

2. 仿真:

(一)第一次仿真

ROM初始化数据为:

1000000000001    //lda
0010000000000   //com
0011000000000   //shr
0001000000000   //cla
0101000000000   //stp

RAM初始化数据为:

1010001111010100
0000110101110011

仿真结果:

(二)第二次仿真

ROM初始化数据为:

1000000000000    //lda
0110000000001   //add
0111000000000   //sta
1000000000011   //lda
1010000000010   //ban
0101000000000   //stp
1001000001000   //jmp
0101000000000   //stp

RAM初始化数据为:

1010001111010100
0000110101110011
0000000000000010
1111111111111111
0001000000000000

在执行这些指令的过程中我发现了一些错误所以将代码修改了一下:
修改如下:
一.当执行ban指令跳转后,ban值一直为1,所以pc一直在执行ban操作,所以要在ALU的其他操作中增加ban输出为0的操作防止出错。同时cu中有一些操作没有对应的ALU操作为防止执行ban指令后出错,更改cu和ALU。

1.   module ALU(
2.      input wire[15:0] in1,
3.      input wire[15:0] in2,
4.      input wire[3:0] alu_op,
5.      output reg ban,
6.      output reg[15:0] z
7.      );
8.      always @(*)
9.      begin
10.     case(alu_op)
11.     4'b0001: begin z<=in1+in2;ban<=0; end
12.     4'b0010: begin z<=in1-in2;ban<=0; end
13.     4'b0011: begin z<=in1&in2;ban<=0; end
14.     4'b0100: begin z<=in1|in2;ban<=0; end
15.     4'b0101: begin z<=in1<<in2;ban<=0; end
16.     4'b0110: begin z<=in1>>in2;ban<=0; end
17.     4'b0111: begin z<=0; ban<=0; end//cla
18.     4'b1000: begin z<=~in1; ban<=0; end//com
19.     4'b1001: begin z<={{in1[15]},in1[15:1]};ban<=0; end //shr
20.     4'b1010: begin z<={{in1[14:0]},in1[15]}; ban<=0; end//csl
21.     4'b1011: begin z<=in2;ban<=0; end
22.     4'b1100: ban<=in1[15]==1 ? 1 : 0;
23.     4'b1101: ban<=0;
24. //    4'b0111: z<={{6{imm[8]}},imm}+in1;
25. //    4'b1000: z<=out_data;
26.     endcase
27.     end
28. endmodule

CU

1.   module CU(
2.      input wire [3:0] opcode,
3.      output reg p_wr_en,
4.      output reg m_wr_en,
5.      output reg a_wr_en,
6.
7.      output reg stop,
8.      output reg [3:0] alu_op
9.      );
10.     always@(opcode)begin
11.         case(opcode)
12.         4'b0001: begin //cla
13.             p_wr_en<=0;
14.             stop<=0;
15.             m_wr_en<=1;
16.             a_wr_en<=1;
17.             alu_op<=4'b0111;
18.         end
19.         4'b0010: begin//com
20.             p_wr_en<=0;
21.             stop<=0;
22.             m_wr_en<=1;
23.             a_wr_en<=1;
24.             alu_op<=4'b1000;
25.         end
26.         4'b0011: begin //shr
27.             p_wr_en<=0;
28.             stop<=0;
29.             m_wr_en<=1;
30.             a_wr_en<=1;
31.             alu_op<=4'b1001;
32.         end
33.         4'b0100: begin //csl
34.             p_wr_en<=0;
35.             stop<=0;
36.             m_wr_en<=1;
37.             a_wr_en<=1;
38.             alu_op<=4'b1010;
39.         end
40.         4'b0101: begin //stp
41.             p_wr_en<=0;
42.             stop<=1;
43.             m_wr_en<=1;
44.             a_wr_en<=0;
45.             alu_op<=4'b1101;
46.         end
47.         4'b0110: begin //add
48.             p_wr_en<=0;
49.             stop<=0;
50.             m_wr_en<=1;
51.             a_wr_en<=1;
52.             alu_op<=4'b0001;
53.         end
54.         4'b0111: begin //sta
55.             p_wr_en<=0;
56.             stop<=0;
57.             m_wr_en<=0;
58.             a_wr_en<=0;
59.             alu_op<=4'b1101;
60.         end
61.         4'b1000: begin //lda
62.             p_wr_en<=0;
63.             stop<=0;
64.             m_wr_en<=1;
65.             a_wr_en<=1;
66.             alu_op<=4'b1011;
67.         end
68.         4'b1001: begin //jmp
69.             p_wr_en<=1;
70.             stop<=0;
71.             m_wr_en<=1;
72.             a_wr_en<=0;
73.             alu_op<=4'b1101;
74.         end
75.         4'b1010: begin //ban
76.             p_wr_en<=1;
77.             stop<=0;
78.             m_wr_en<=1;
79.             a_wr_en<=0;
80.             alu_op<=4'b1100;
81.         end
82.         endcase
83.     end
84. endmodule

二.Pc执行停机指令时是在任何一个时钟周期内都可以进行,这样会使jmp或ban指令出错,所以我将器更改为仅在时钟周期上沿时可以停机。
PC

1.   module PC(
2.      input clk,
3.      input rst,
4.      input stop,
5.      input ban,
6.      input p_wr_en,
7.      input wire [12:0] jmp,
8.      output reg [12:0] pc
9.      );
10.     reg state;
11.     initial begin
12.         pc=8'd0;
13.         state=1;
14.     end
15.     always@(posedge clk) begin
16.         if(stop==1)
17.             state<=0;
18.         if(rst==1)
19.             pc<=0;
20.     end
21.     always@(posedge clk) begin
22.         if(state==1)
23.             pc<=pc+1'd1;
24.     end
25.     always@(negedge clk) begin
26.         if(p_wr_en==1)
27.             pc<=jmp-1;
28.         if(ban==1)
29.             pc<=pc+jmp-1;
30.     end
31. endmodule

仿真结果:

合肥工业大学计组实验五相关推荐

  1. 合肥工业大学计组实验四

    实验目的 通过设计并实现支持一条指令的CPU,理解和掌握CPU设计的基本原理和过程. 实验内容 设计和实现一个支持加法指令的单周期CPU.要求该加法指令(表示为add r1,r2,r3)格式约定如下: ...

  2. 合肥工业大学机器人技术实验五十六题

    注:非原创,仅仅做了整理工作. //PlayerTeams.cpp130行到138行是PlayOn模式开球后拿球到决策 //把原来到soc注释,在后面添加代码;每次修改后构建之后才能看到效果 在 pl ...

  3. logisim计组实验五 CRC校验电路

    文章目录 CRC(7,3)串行编码电路 CRC(21,16)并行编码电路 CRC(21,16)并行解码电路 CRC校验电路的logisim设计,有什么问题就提出来吧~ 电路文件已经托管至Github, ...

  4. 西电计组实验一 存储器实验

    FPGA中LPM_ROM定制与读出实验 一.实验目的   1.掌握FPGA中lpm_ROM的设置,作为只读存储器ROM的工作特性和配置方法:   2.用文本编辑器编辑mif文件配置ROM,学习将程序代 ...

  5. 超前进位加法器实验报告_北科大第二次计组实验报告超前进位加法器.doc

    北科大第二次计组实验报告超前进位加法器 北京科技大学 计算机与通信工程学院 实 验 报 告 实验名称: 超前进位加法器 学生姓名: 专 业: 计算机科学与技术 班 级: 学 号: 指导教师: 实验成绩 ...

  6. 超前进位加法器实验报告_北科大第二次计组实验报告超前进位加法器

    北科大第二次计组实验报告超前进位加法器 北京科技大学 计算机与通信工程学院实 验 报 告实验名称: 超前进位加法器 学生姓名: 专 业: 计算机科学与技术 班 级: 学 号: 指导教师: 实验成绩: ...

  7. 编译原理上机实习c语言小子集编译程序的实现报告,合肥工业大学编译原理实验报告(完整代码版)...

    <合肥工业大学编译原理实验报告(完整代码版)>由会员分享,可在线阅读,更多相关<合肥工业大学编译原理实验报告(完整代码版)(58页珍藏版)>请在人人文库网上搜索. 1.计算机与 ...

  8. 计算机组成实验六MIPS汇编器,杭电计组实验6-MIPS汇编器与模拟器实验.doc

    <杭电计组实验6-MIPS汇编器与模拟器实验.doc>由会员分享,提供在线免费全文阅读可下载,此文档格式为doc,更多相关<杭电计组实验6-MIPS汇编器与模拟器实验.doc> ...

  9. 计算机组成原理fc和fz,合肥工业大学计算机组成原理实验报告(DOC)

    合肥工业大学计算机组成原理实验报告(DOC),合肥工业大学计算机组成原理,合肥工业大学计算机组成原理试卷,计算机组成原理实验pdf,计算机组成原理微程序,计算机组成原理实验报告,计算机组成原理知识点, ...

最新文章

  1. 魔与道的反复较量 反垃圾邮件技术
  2. [C#基础知识系列]专题十:全面解析可空类型
  3. 也许开发需要的只是一份简单明了的表格
  4. 【笔记】An explainable deep machine vision framework for plant stress phenotyping
  5. Handler 基本用法--线程间传值
  6. python基础(part4)--语句
  7. 数据库单表千万行 LIKE 搜索优化手记
  8. 将一个数组拼接成一个指定字符串返回
  9. 常见的mysql集群
  10. 【纯干货】4年前想解决的事情,今天才实验成功
  11. Sqlserver自动优化
  12. 亮风台AR眼镜震撼发布 HiAR 产品全面升级
  13. ppt模板免费下载的网站有哪些?这个宝藏网站必须make
  14. 分享5个国外较好的图片网站
  15. java.lang.reflect.Field常用方法
  16. assets文件使用
  17. Blackhat2017:如何利用PostScript语言入侵打印机
  18. 数据库原理 封锁的粒度
  19. MobileNetV2: Inverted Residuals and Linear Bottlenecks论文解读
  20. DSP28335 CAN模块例程

热门文章

  1. Android SD卡多级目录的创建
  2. 【OJ每日一练】1074 - 振兴中华
  3. ThinkPHP6之数据库操作下
  4. 让我们一起共同“秉烛夜读”好吗?
  5. 《增强现实:原理、算法与应用》读书笔记(7)稠密深度估计
  6. 瑞波(XRP)钱包对接
  7. 64位WIN7下虚拟机安装winxp
  8. format()函数的用法
  9. 关于 打印机可打印无法扫描报错“使用该设备需要WIA驱动程序,请从安装CS或从...” 的解决方法
  10. 2020-08-20商汤科技笔试A卷