Verilog建模的方式有三种:
在进行这个仿真实验的时候我将三种建模方式都尝试了一遍,但是都与老师给的波形图不符合,这一定是哪里出错了
M是为了区分算数运算和逻辑运算的一个标志,当M为0的时候进行算术运算,当M为1的时候进行逻辑运算
CN是由ALU产生的向高位的进位,这里采用的是负逻辑,当CN为0的时候才表示向高位的进位,当然这里的进位应该这样理解:当我们进行加法的时候,进位是向上+1,减法的时候是向高位借1
当我们将一个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
以8位数据为例:
逻辑0为8’h00;
逻辑1为8’hff;
并且这时候应该保证进位为逻辑值
由于rst为1情况下,为清零,否则运行,以及整个程序的同步性,当整个程序开始运行的时候(即rst为0的一瞬间)这时候并不能读出正确的ProgMem中的微指令。
目前采取将微指令程序中的0号指令设为00
该问题在完成了整个仿真流程后未复现,应该为程序bug
当进行程序转移指令的时候upc未置为0,这会导致某些情况下的微指令触发问题,比如跳过了第一条
暂时没有进行解决,目前采取对upc置之不理的态度
这个问题是由于没有非常好的理解PC和当前指令的关系,PC指向的是下一条要取的指令的地址,所以这里的upc不需要设置为0
转移指令应该和set acc配合使用,这样才可以正确跳转。
指令修改:
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 |
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 |
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!