组成原理模型机

组成原理模型机

1. 运算器

Verilog建模的方式有三种:

  1. 行为级
  2. 门级(逻辑级)
  3. 数据流建模

在进行这个仿真实验的时候我将三种建模方式都尝试了一遍,但是都与老师给的波形图不符合,这一定是哪里出错了

M的作用

M是为了区分算数运算和逻辑运算的一个标志,当M为0的时候进行算术运算,当M为1的时候进行逻辑运算

CN的作用

CN是由ALU产生的向高位的进位,这里采用的是负逻辑,当CN为0的时候才表示向高位的进位,当然这里的进位应该这样理解:当我们进行加法的时候,进位是向上+1,减法的时候是向高位借1

Verilog中的位提升

当我们将一个4位的运算式赋值给一个5位的结果的时候,运算式中的变量数值都会进行位提升,补齐位数,即

reg[3:0] A = 4'h5;
reg[3:0] B = 4'h7;
wire[4:0] F = A|~B;
F = 5'b11101而不是5'b01101

逻辑0和逻辑1

以8位数据为例:

逻辑0为8’h00;

逻辑1为8’hff;

并且这时候应该保证进位为逻辑值

2. clk时钟信号与rst以及upc

问题描述

由于rst为1情况下,为清零,否则运行,以及整个程序的同步性,当整个程序开始运行的时候(即rst为0的一瞬间)这时候并不能读出正确的ProgMem中的微指令。

解决办法

目前采取将微指令程序中的0号指令设为00

问题后续

该问题在完成了整个仿真流程后未复现,应该为程序bug

3. 程序转移指令

问题描述

当进行程序转移指令的时候upc未置为0,这会导致某些情况下的微指令触发问题,比如跳过了第一条

问题解决

暂时没有进行解决,目前采取对upc置之不理的态度

问题后续

这个问题是由于没有非常好的理解PC和当前指令的关系,PC指向的是下一条要取的指令的地址,所以这里的upc不需要设置为0

4. 转移指令问题

转移指令应该和set acc配合使用,这样才可以正确跳转。

5.在ACC和寄存器之间执行算术模式运算:6r

指令修改:

upc 原微指令 修改指令
00 0000_0111_0101_0000 0000_0111_0001_0000
01 0000_0111_0001_0000 0000_0111_0101_0000
10 0000_0111_1010_1001 0000_0111_1010_1001
11 0000_0111_0000_1001 0000_0111_0000_1001

6.指令修改:4p

upc 原微指令 修改指令
00 0000_0111_0000_1001 0000_0111_0000_1001
01 0001_0111_0000_1001 0000_0111_0000_1001
10 0000_0111_0000_1001 0000_0111_0000_1001
11 0000_0111_0000_1001 0001_0111_0000_1001

7. 修改连线图:将Func即运算控制锁存器的连线从instr[3:0]换接RamRegister中,即将4p修改为将利用寄存器锁存

组成原理模型机_第1张图片

8.简单的ModelCPU

module ModelCPU8Bit(
    input clk,
    input rst,
    inout [3:0] port7,
    inout [3:0] port8,
    inout [3:0] port9,
    inout [3:0] portA,
    output [7:0] display
);
    wire [3:0] addr;
    wire [3:0] data;
    wire [7:0] instruction;
    wire CF, ZF;    
    wire [7:0] PC;
    wire [1:0] upc;
    wire PC_Load;
    wire [3:0] S, aluS;
    wire [3:0] A, B, F;
    wire C0, C4, M, AequB;
    wire [15:0] f;
    wire [3:0] genReg;
    wire [3:0] porti;  
    wire P;
    wire G;
    reg [7:0]outTemp = 8'h00;

  ProgramCounter ut_PC(.clk(clk),
          .rst(rst),
          .PC_Load(PC_Load),
          .instrAddr({instruction[3:0], data}),
          .PC(PC),
          .upc(upc));

  ProgramMem ut_ProgramMem(.clk(clk),
          .rst(rst),
          .PC(PC),
          .upc(upc),
          .instruction(instruction),
          .control(port9)
          );

  ControlMem ut_ControlMem(.upc(upc),
          .op(instruction[7:4]),
          .f(f));

  PSW ut_PSW(.C4(C4),
          .AequB(AequB),
          .clk(clk),
          .rst(rst),
          .we(f[6]),
          .rd(f[7]),
          .CF(CF),
          .ZF(ZF));

    RamRegister ut_ram (
    .clka(clk),
    .ena(1), 
    .wea(f[10]),
    .addra(addr),
    .dina(data),
    .douta(genReg) 
  );                

  aluFuncS ut_aluFuncS(.instrL4(genReg),
          .clk(clk),
          .rst(rst),
          .we(f[12]),
          .aluFuncS(aluS));


    ALU181 ut_ALU181(.A(A), 
                     .B(B),
                     .C0(C0),
                     .M(f[2]),
                     .S(S),
                     .F(F),
                     .C4(C4),
                     .AequB(AequB),
                     .P(P),
                     .G(G)
                     );                         
    ACCReg ut_ACCReg(.F(F),
                     .clk(clk),
                     .rst(rst),
                     .we(f[6]),    
                     .rd(f[5]),
                     .ACC(data)
                     );

    IOPort ut_IOPort(.data(data),
                     .addr(addr),
                     .clk(clk),
                     .rst(rst),
                     .wd(f[8]),
                     .cs(f[9]),
                     .porti(porti),
                     .port7(port7),
                     .port8(port8),
                     .port9(port9),
                     .portA(portA)
                     );    

    assign PC_Load = f[15:14] == 00 ?  0 :
                     f[15:14] == 01 ?  ZF:
                     f[15:14] == 10 ? ~CF:1;

  assign S = f[0] == 0 ? aluS : {~f[11], f[11], f[1], ~f[1]};

  assign C0 = f[13] == 0 ? CF : S[2]|data[0];

  assign B = f[3] == 0 ? genReg :
         (f[4] == 0 ? instruction[3:0] :
         (f[8] == 0 ? porti : 4'b0000));

  assign A = data;

  assign addr = instruction[3:0];
    assign M = f[2];
  assign display = outTemp;
  always@(posedge clk or negedge rst)
  begin
      if(rst)
        outTemp = 8'h00;
      else if(instruction == 8'h60 && upc == 2'b11)
        outTemp = {3'b000, ~CF, F};
  end
endmodule

在进行简单的模型机设计的时候首先应该完成各个模块的功能实现,之后进行整体的功能测试,毕竟路要一步一步的走!

再放出一个ALU的verilog代码:

module ALU181(
  input [3:0] A,
  input [3:0] B,
  input C0,
  input M,  
  input [3:0] S,
  output reg C4,
  output reg [3:0] F,
  output AequB,
  output P,
  output G
  );
    always@(A or B or S or M or C0)
    begin
      case({S,M,C0})
        6'b0000_0_1: {C4, F} = A;
        6'b0000_0_0: {C4, F} = A+1;        
        6'b0000_1_1, 
        6'b0000_1_0: {C4, F} = {~A[3], ~A[2], ~A[1], ~A[0]};       

        6'b0001_0_1: {C4, F} = A|B;
        6'b0001_0_0: {C4, F} = (A|B)+1;        
        6'b0001_1_1, 
        6'b0001_1_0: {C4, F} = ~(A|B);        

        6'b0010_0_1: {C4, F} = A|({~B[3], ~B[2], ~B[1], ~B[0]});
        6'b0010_0_0: {C4, F} = (A|({~B[3], ~B[2], ~B[1], ~B[0]}))+1;        
        6'b0010_1_1, 
        6'b0010_1_0: {C4, F} = ({~A[3], ~A[2], ~A[1], ~A[0]})&B;        

        6'b0011_0_1: {C4, F} = 5'b01111;
        6'b0011_0_0: {C4, F} = 5'b10000;        
        6'b0011_1_1, 
        6'b0011_1_0: {C4, F} = 5'b10000;        

        6'b0100_0_1: {C4, F} = A+(A&({~B[3], ~B[2], ~B[1], ~B[0]}));
        6'b0100_0_0: {C4, F} = (A+(A&({~B[3], ~B[2], ~B[1], ~B[0]})))+1;        
        6'b0100_1_1, 
        6'b0100_1_0: {C4, F} = ~(A&B);        

        6'b0101_0_1: {C4, F} = (A&({~B[3], ~B[2], ~B[1], ~B[0]}))+(A|B);
        6'b0101_0_0: {C4, F} = ((A&({~B[3], ~B[2], ~B[1], ~B[0]}))+(A|B))+1;        
        6'b0101_1_1, 
        6'b0101_1_0: {C4, F} = {~B[3], ~B[2], ~B[1], ~B[0]};        

        6'b0110_0_1: begin
                        {C4, F} = A-B+5'b11111;
                        C4=~C4;
                     end
        6'b0110_0_0: begin
                        {C4, F} = A-B;
                        C4=~C4; 
                     end
        6'b0110_1_1, 
        6'b0110_1_0: {C4, F} = A^B;        

        6'b0111_0_1: begin
                        {C4, F} = (A&({~B[3], ~B[2], ~B[1], ~B[0]}))+5'b11111;
                        C4 = ~C4;
                     end
        6'b0111_0_0: begin
                        {C4, F} = (A&({~B[3], ~B[2], ~B[1], ~B[0]}));
                        C4 = ~C4;
                     end
        6'b0111_1_1, 
        6'b0111_1_0: {C4, F} = (A&({~B[3], ~B[2], ~B[1], ~B[0]}));        

        6'b1000_0_1: {C4, F} = A+(A&B);
        6'b1000_0_0: {C4, F} = A+(A&B)+1;        
        6'b1000_1_1, 
        6'b1000_1_0: {C4, F} = ({~A[3], ~A[2], ~A[1], ~A[0]}|B);        

        6'b1001_0_1: {C4, F} = A+B;
        6'b1001_0_0: {C4, F} = A+B+1;        
        6'b1001_1_1, 
        6'b1001_1_0: {C4, F} = ~(A^B);        

        6'b1010_0_1: {C4, F} = (A&B)+(A|({~B[3], ~B[2], ~B[1], ~B[0]}));
        6'b1010_0_0: {C4, F} = (A&B)+(A|({~B[3], ~B[2], ~B[1], ~B[0]}))+1;        
        6'b1010_1_1, 
        6'b1010_1_0: {C4, F} = B;        

        6'b1011_0_1: begin
                        {C4, F} = A&B+5'b11111;
                        C4 = ~C4;
                     end
        6'b1011_0_0: begin
                        {C4, F} = A&B; 
                        C4 = ~C4;
                     end
        6'b1011_1_1, 
        6'b1011_1_0: {C4, F} = A&B;        

        6'b1100_0_1: {C4, F} = A+A;
        6'b1100_0_0: {C4, F} = A+A+1;        
        6'b1100_1_1, 
        6'b1100_1_0: {C4, F} = 5'b01111; //逻辑1       

        6'b1101_0_1: {C4, F} = A+(A|B);
        6'b1101_0_0: {C4, F} = A+(A|B)+1;        
        6'b1101_1_1, 
        6'b1101_1_0: {C4, F} = A|({~B[3], ~B[2], ~B[1], ~B[0]});        

        6'b1110_0_1: {C4, F} = A+(A|({~B[3], ~B[2], ~B[1], ~B[0]}));
        6'b1110_0_0: {C4, F} = A+(A|({~B[3], ~B[2], ~B[1], ~B[0]}))+1;        
        6'b1110_1_1, 
        6'b1110_1_0: {C4, F} = A|B;        

        6'b1111_0_1: begin
                        {C4, F} = A+5'b11111;
                        C4 = ~C4;
                     end
        6'b1111_0_0: begin
                        {C4, F} = A;
                        C4 = ~C4;
                     end
        6'b1111_1_1, 
        6'b1111_1_0: {C4, F} = A;        
      endcase
      C4 = ~C4;
    end
    assign AequB = F[0]&F[1]&F[2]&F[3];
    assign P=(A[0]^B[0])&(A[1]^B[1])&(A[2]^B[2])&(A[3]^B[3]);
    assign G=(A[3]&B[3])+(A[2]&B[2])&(A[3]^B[3])+(A[1]&B[1])&(A[2]^B[2])&(A[3]^B[3])+(A[0]&B[0])&(A[1]^B[1])&(A[2]^B[2])&(A[3]^B[3]); 
endmodule

controlMem的代码:

module ControlMem(    
    input [1:0] upc,
    input [3:0] op,
    output reg [15:0] f  
);
    always@(op or upc)
        case({op, upc})
            //0n:跳转指令,jump n<<4 + ACC, 即PC = ACC + n<<4
            6'b0000_00: f <= 16'b0000_0111_0000_1001;
            6'b0000_01: f <= 16'b1100_0111_0000_1001;
            6'b0000_10: f <= 16'b0000_0111_0000_1001;
            6'b0000_11: f <= 16'b0000_0111_0000_1001;
            //1n: 赋�指令,将立即数送给累加器,ACC <- n
            6'b0001_00: f <= 16'b0000_0111_0100_1111;
            6'b0001_01: f <= 16'b0000_0111_0000_1111;
            6'b0001_10: f <= 16'b0000_0111_0010_1001;
            6'b0001_11: f <= 16'b0000_0111_0000_1001;
            //2r: 赋�指�,将累加器的��给通用寄存�, r <- ACC
            6'b0010_00: f <= 16'b0000_0111_0000_1001;
            6'b0010_01: f <= 16'b0000_0011_0000_1001;
            6'b0010_10: f <= 16'b0000_0111_0000_1001;
            6'b0010_11: f <= 16'b0000_0111_0000_1001;
            //3r: 赋�指�,将�用寄存器的值�给累加�, ACC <- r
            6'b0011_00: f <= 16'b0000_0111_0101_0111;
            6'b0011_01: f <= 16'b0000_0111_0001_0111;
            6'b0011_10: f <= 16'b0000_0111_0010_1001;
            6'b0011_11: f <= 16'b0000_0111_0000_1001;
            //4p: 设置运算器的运算类型,例:p=0100,则 s3,s2,s1,s0 = 0100
            6'b0100_00: f <= 16'b0000_0111_0000_1001;
            6'b0100_01: f <= 16'b0000_0111_0000_1001;
            6'b0100_10: f <= 16'b0000_0111_0000_1001;
            6'b0100_11: f <= 16'b0001_0111_0000_1001;
            //5n: 在ACC和立即数之间执行算术模式运算
            6'b0101_00: f <= 16'b0000_0111_0100_1000;
            6'b0101_01: f <= 16'b0000_0111_0000_1000;
            6'b0101_10: f <= 16'b0000_0111_1010_1001;
            6'b0101_11: f <= 16'b0000_0111_0000_1001;
            //6r: 在ACC和寄存器之间执行算术模式运算
            6'b0110_00: f <= 16'b0000_0111_0001_0000;
            6'b0110_01: f <= 16'b0000_0111_0101_0000;
            6'b0110_10: f <= 16'b0000_0111_1010_1001;
            6'b0110_11: f <= 16'b0000_0111_0000_1001;
            //7n: 在ACC和立即数之间执行逻辑模式运算
            6'b0111_00: f <= 16'b0000_0111_0100_1100;
            6'b0111_01: f <= 16'b0000_0111_0000_1100;
            6'b0111_10: f <= 16'b0000_0111_0010_1001;
            6'b0111_11: f <= 16'b0000_0111_0000_1001;
            //8r: 在ACC和寄存器之间执行逻辑模式运算
            6'b1000_00: f <= 16'b0000_0111_0101_0100;
            6'b1000_01: f <= 16'b0000_0111_0001_0100;
            6'b1000_10: f <= 16'b0000_0111_0010_1001;
            6'b1000_11: f <= 16'b0000_0111_0000_1001;
            //9s: 设置进位符,s=0000时,没有进位,即CF =1; s=1111时,有进�,� CF=0(用这条指令之前,需确保ACC�1110�
            6'b1001_00: f <= 16'b0010_0111_0100_1001;
            6'b1001_01: f <= 16'b0010_0111_0000_1001;
            6'b1001_10: f <= 16'b0000_0111_1000_1001;
            6'b1001_11: f <= 16'b0000_0111_0000_1001;
            //An: 比较ACC和立即数的�大小�若ACC>n,则设置进位标志CF = 0;若ACC=n时,则置零标志位ZF=1
            6'b1010_00: f <= 16'b0010_1111_0100_1011;
            6'b1010_01: f <= 16'b0010_1111_0000_1011;
            6'b1010_10: f <= 16'b0000_0111_1000_1001;
            6'b1010_11: f <= 16'b0000_0111_0000_1001;
            //Br: 比较ACC和寄存器的�大小�若ACC>r,则设置进位标志CF=0;若ACC=r时,则置零标志位ZF=1
            6'b1011_00: f <= 16'b0010_1111_0101_0011;
            6'b1011_01: f <= 16'b0010_1111_0001_0011;
            6'b1011_10: f <= 16'b0000_0111_1000_1001;
            6'b1011_11: f <= 16'b0000_0111_0000_1001;
            //Cn: 如果零标志位ZF==1,则跳转,即PC = ACC + n<<4
            6'b1100_00: f <= 16'b0000_0111_0000_1001;
            6'b1100_01: f <= 16'b0100_0111_0000_1001;
            6'b1100_10: f <= 16'b0000_0111_0000_1001;
            6'b1100_11: f <= 16'b0000_0111_0000_1001;
            //Dn: 如果进位标志CF==0,则跳转,即PC = ACC + n<<4
            6'b1101_00: f <= 16'b0000_0111_0000_1001;
            6'b1101_01: f <= 16'b1000_0111_0000_1001;
            6'b1101_10: f <= 16'b0000_0111_0000_1001;
            6'b1101_11: f <= 16'b0000_0111_0000_1001;
            //En: 把端口n的数据输入到ACC,即ACC <- Port(n)
            6'b1110_00: f <= 16'b0000_0110_0001_1001;
            6'b1110_01: f <= 16'b0000_0100_0101_1111;
            6'b1110_10: f <= 16'b0000_0100_0001_1111;
            6'b1110_11: f <= 16'b0000_0110_0011_1001;
            //Fn: 把ACC上的值输出到端口n,即 Port(n) <- ACC
            6'b1111_00: f <= 16'b0000_0111_0000_1001;
            6'b1111_01: f <= 16'b0000_0101_0000_1001;
            6'b1111_10: f <= 16'b0000_0111_0000_1001;
            6'b1111_11: f <= 16'b0000_0111_0000_1001;
        endcase     
endmodule

编码乱码了,我也很无奈!//wq

整个项目的代码之后会在文章底部附录,大概一周后吧,毕竟现在还不能open!

你可能感兴趣的:(硬件仿真)