P1
// a simple processor
//可以实现 4 种指令。
module Part1_processor(DIN,Resetn,Clock,Run,Done,BusWires);
input [15:0] DIN; //16-bit 数据输入
input Resetn,Clock,Run;
output Done;
output [15:0] BusWires;
//declare variables
reg [15:0] BusWires;
reg [0:7] Rin,Rout; //8 个 16-bit 寄存器的输入/出控制
reg [15:0] Sum;
reg IRin,Done,DINout,Ain,Gin,Gout,AddSub;
wire [1:0] Tstep_Q; //4 个阶段计数输出
wire [2:0] I; //3-bit 指令码
wire [0:7] Xreg,Yreg; //2 个 8-bit 寄存器
wire [15:0] R0,R1,R2,R3,R4,R5,R6,R7,A,G; //9 个 16-bit 寄存器
wire [1:9] IR; //IIIXXXYYY
wire [1:10] Sel; //多路器的选择位
wire Clear=~Resetn | Done | (~Run & ~Tstep_Q[1] & ~Tstep_Q[0]);
//clear
upcount Tstep(Clear,Clock,Tstep_Q); //T0-T3 4 个阶段
assign I=IR[1:3]; //指令位
dec3to8 decX(IR[4:6],1'b1,Xreg); //译码,用于选择 R0-R7
dec3to8 decY(IR[7:9],1'b1,Yreg);
//指令列表:
//000: mv
//001: mvi
//010: add
//011: sub
always @(Tstep_Q or I or Xreg or Yreg)
begin
//specify initial values
Done=1'b0;
Ain=1'b0;
Gin=1'b0;
Gout=1'b0;
AddSub=1'b0;
IRin=1'b0;
DINout=1'b0;
Rin=8'b0;
Rout=8'b0;
case(Tstep_Q)
2'b00: //store DIN in IR in time step 0
begin
IRin=1'b1;
end
2'b01: //define signals in time step 1
case(I)
3'b000: //mv Rx,Ry
begin
Rout=Yreg;
Rin=Xreg;
Done=1'b1;
end
3'b001: //mvi Rx,#D
begin
DINout=1'b1;
Rin=Xreg;
Done=1'b1;
end
3'b010,2'b011: //add,sub
begin
Rout=Xreg;
Ain=1'b1;
end
default: ;
endcase
2'b10: //define signals in time step 2
case(I)
3'b010: //add
begin
Rout=Yreg;
Gin=1'b1;
end
3'b011: //sub
begin
Rout=Yreg;
AddSub=1'b1;
Gin=1'b1;
end
default: ;
endcase
2'b11: //define signals in time step 3
case(I)
3'b010,3'b011: //add,sub
begin
Gout=1'b1;
Rin=Xreg;
Done=1'b1;
end
default: ;
endcase
endcase
end
regn reg_0(BusWires,Rin[0],Clock,R0);
//instantiate other registers and the adder/subtracter unit
regn reg_1(BusWires,Rin[1],Clock,R1);
regn reg_2(BusWires,Rin[2],Clock,R2);
regn reg_3(BusWires,Rin[3],Clock,R3);
regn reg_4(BusWires,Rin[4],Clock,R4);
regn reg_5(BusWires,Rin[5],Clock,R5);
regn reg_6(BusWires,Rin[6],Clock,R6);
regn reg_7(BusWires,Rin[7],Clock,R7);
regn reg_A(BusWires,Ain,Clock,A);
regn #(.n(9)) reg_IR(DIN[15:7],IRin,Clock,IR);
//alu
always @(AddSub or A or BusWires)
begin
if(!AddSub)
Sum=A+BusWires;
else
Sum=A-BusWires;
end
regn reg_G(Sum,Gin,Clock,G);
//define the bus
assign Sel={Rout,Gout,DINout};
always @(*)
begin
if(Sel==10'b10_0000_0000)
BusWires=R0;
else if(Sel==10'b01_0000_0000)
BusWires=R1;
else if(Sel==10'b00_1000_0000)
BusWires=R2;
else if(Sel==10'b00_0100_0000)
BusWires=R3;
else if(Sel==10'b00_0010_0000)
BusWires=R4;
else if(Sel==10'b00_0001_0000)
BusWires=R5;
else if(Sel==10'b00_0000_1000)
BusWires=R6;
else if(Sel==10'b00_0000_0100)
BusWires=R7;
else if(Sel==10'b00_0000_0010)
BusWires=G;
else
BusWires=DIN;
end
endmodule
module upcount(Clear,Clock,Q);
input Clear,Clock;
output [1:0] Q;
reg [1:0] Q;
always @(posedge Clock)
if(Clear)
Q<=2'b0;
else
Q<=Q+1'b1;
endmodule
module dec3to8(W,En,Y);
input [2:0] W;
input En;
output [0:7] Y;
reg [0:7] Y;
always @(W or En)
begin
if(En==1)
case(W)
3'b000: Y=8'b1000_0000;
3'b001: Y=8'b0100_0000;
3'b010: Y=8'b0010_0000;
3'b011: Y=8'b0001_0000;
3'b100: Y=8'b0000_1000;
3'b101: Y=8'b0000_0100;
3'b110: Y=8'b0000_0010;
3'b111: Y=8'b0000_0001;
endcase
else
Y=8'b0000_0000;
end
endmodule
module regn(R,Rin,Clock,Q);
parameter n=16;
input [n-1:0] R;
input Rin,Clock;
output [n-1:0] Q;
reg [n-1:0] Q;
always @(posedge Clock)
if(Rin)
Q<=R;
endmodule
P1_tb
`timescale 1ns/1ps
module tb_proc;
reg [15:0] DIN;
reg Resetn, Clock, Run;
wire Done;
wire [15:0] BusWires;
// Instantiate the processor
Part1_processor uut (
.DIN(DIN),
.Resetn(Resetn),
.Clock(Clock),
.Run(Run),
.Done(Done),
.BusWires(BusWires)
);
// Internal signal access
wire [8:0] IR = [Link];
wire [1:0] Tstep_Q = uut.Tstep_Q;
wire [15:0] Sum = [Link];
wire [15:0] A = uut.A;
wire [15:0] G = uut.G;
wire [0:7] Rin = [Link];
wire [0:7] Rout = [Link];
wire IRin = [Link];
wire DINout = [Link];
wire Ain = [Link];
wire Gin = [Link];
wire Gout = [Link];
wire AddSub = [Link];
wire [15:0] R0 = uut.R0;
wire [15:0] R1 = uut.R1;
wire [15:0] R2 = uut.R2;
wire [15:0] R3 = uut.R3;
wire [15:0] R4 = uut.R4;
wire [15:0] R5 = uut.R5;
wire [15:0] R6 = uut.R6;
wire [15:0] R7 = uut.R7;
wire [0:7] Xreg = [Link];
wire [0:7] Yreg = [Link];
wire [1:10] Sel = [Link];
// Clock generation
initial begin
Clock = 0;
forever #5 Clock = ~Clock;
end
// Dump waveform
initial begin
$dumpfile("[Link]");
$dumpvars(0, tb_proc);
end
// Monitor internal signals
initial begin
$monitor("Time=%0t | Clock=%b | Resetn=%b | Run=%b | Done=%b |
Tstep_Q=%b | IR=%b | BusWires=%h | Sum=%h | A=%h | G=%h | IRin=%b |
DINout=%b | Ain=%b | Gin=%b | Gout=%b | AddSub=%b | Rin=%b | Rout=%b |
R0=%h | R1=%h | R2=%h | R3=%h | R4=%h | R5=%h | R6=%h | R7=%h | Xreg=
%b | Yreg=%b | Sel=%b",
$time, Clock, Resetn, Run, Done, Tstep_Q, IR, BusWires, Sum, A,
G,
IRin, DINout, Ain, Gin, Gout, AddSub,
Rin, Rout,
R0, R1, R2, R3, R4, R5, R6, R7,
Xreg, Yreg, Sel);
end
initial begin
// Reset
Resetn = 0; Run = 0; DIN = 0;
#10 Resetn = 1;
// Test mvi R0, #5
DIN = 16'h101c; // 001_000_000_0000101;
Run = 1;
#10 Run = 0;
wait(Done);
#20;
// Test mvi R1, #3
DIN = 16'h32ff; // b001_001_000_0000011;
Run = 1;
#10 Run = 0;
wait(Done);
#20;
// Test add R0, R1
DIN = 16'h52ff; // b010_000_001_0000000;
Run = 1;
#10 Run = 0;
wait(Done);
#20;
// Test sub R0, R1
DIN = 16'h6200; //b011_000_001_0000000;
Run = 1;
#10 Run = 0;
wait(Done);
#20;
// Test mv R2, R0
DIN = 16'h0800;// b000_010_000_0000000;
Run = 1;
#10 Run = 0;
wait(Done);
#20;
$stop;
end
endmodule
P2
//part 2 top module
//加上外部存储器的处理器
//引脚说明:
//--------------------------------------------------------
// SW17-Run KEY0-Resetn KEY1-MClock
// KEY2-PClock LEDR15-0-BusWires LEDR17-Done
module part2(
input [2:0] KEY,
input [17:17] SW,
output [17:0] LEDR
);
wire Done,Resetn,PClock,MClock,Run;
wire [15:0] DIN,BusWires;
wire [4:0] pc; //计数输出,srom 的地址 0-31
assign Resetn=KEY[0];
assign PClock=KEY[0]; //processor 的时钟
assign MClock=KEY[2]; //srom 的时钟
assign Run=SW[17];
proc m0(DIN,Resetn,PClock,Run,Done,Buswires);
assign LEDR[15:0] =BusWires;
assign LEDR[17]=Done;
sromlpm m1(pc,MClock,DIN);
count5 m2(Resetn,MClock,pc);
endmodule
//count5
module count5(Resetn,Clock,Q);
input Resetn,Clock;
output reg [4:0] Q;
always @(posedge Clock)
if(Resetn==0)
Q<=5'b0;
else
Q<=Q+1'b1;
endmodule
Part2 có Debounce
module part2 (
input CLOCK_50, // Clock hệ thống
input [1:0] KEY, // Nút nhấn
input [9:0] SW, // Switch
output [9:0] LEDR, // LED hiển thị
output [15:0] DIN_out, // Dữ liệu từ bộ nhớ
output [4:0] pc_out // Địa chỉ lệnh hiện tại
);
wire Done, Resetn, Run;
wire MClock_raw, PClock_raw;
wire MClock_debounced, PClock_debounced;
reg MClock_prev, PClock_prev;
wire MClock_pulse, PClock_pulse;
wire [15:0] DIN;
wire [4:0] pc;
assign Resetn = SW[0];
assign Run = SW[9];
assign MClock_raw = KEY[0];
assign PClock_raw = KEY[1];
// Chống dính phím
debounce db_mclock (
.clk(CLOCK_50),
.btn_in(MClock_raw),
.btn_out(MClock_debounced)
);
debounce db_pclock (
.clk(CLOCK_50),
.btn_in(PClock_raw),
.btn_out(PClock_debounced)
);
// Phát hiện cạnh lên để tạo xung clock
always @(posedge CLOCK_50) begin
MClock_prev <= MClock_debounced;
PClock_prev <= PClock_debounced;
end
assign MClock_pulse = MClock_debounced & ~MClock_prev;
assign PClock_pulse = PClock_debounced & ~PClock_prev;
// Instantiate processor
proc U1 (
.DIN(DIN),
.Resetn(Resetn),
.PClock(PClock_pulse),
.Run(Run),
.Done(Done)
);
// Instantiate instruction memory
inst_mem U2 (
.address(pc),
.clock(MClock_pulse),
.q(DIN)
);
// Instantiate program counter
count5 U3 (
.Resetn(Resetn),
.Clock(MClock_pulse),
.Q(pc)
);
// Output assignments
assign LEDR[9] = Run;
assign LEDR[0] = Done;
assign LEDR[8:4] = pc;
assign LEDR[1] = DIN[0];
assign LEDR[3:2] = 2'b00;
assign DIN_out = DIN;
assign pc_out = pc;
endmodule