Your IP : 216.73.217.88
// pipe2.v Verilog version using modules in this file
// basic five stage pipeline of just Instruction Register
// The 411 course pipeline has the same five stages
// IF Instruction Fetch includes PC and instruction memory
// ID Instruction Decode and registers
// EX Execution including the ALU Arithmetic Logic Unit
// MEM data Memory
// WB Write Back into registers
//
// This self contained Verilog file defines:
//
// a 32 bit adder module using behavioral code
// 32 and 5 bit register module with clock and clear inputs
// an instruction memory module using behavioral code
// a data memory module using behavioral code
// a general register module using behavioral code
// 32 and 5 bit multiplexor module using behavioral code
//
// a top level module, pipe2, test bench
// the wires for interconnecting the entities
// the modules instantiated to connect the wires
// printout that shows the registers in the pipeline each clock
//
`timescale 1ps/1ps // times in pico seconds
module add32(a, b, cin, sum, cout);
parameter n=31;
input [n:0] a; // a input
input [n:0] b; // b input
input cin; // carry-in
output [n:0] sum; // sum output
output cout; // carry-out
assign #250 {cout, sum} = a + b + cin;
endmodule // add32
module register_32(clk, clear, inp, out);
input clk; // accept inp on posedge
input clear; // clear when high
input [31:0] inp; // input data
output [31:0] out; // output of register
wire [31:0] inp;
wire [31:0] out;
reg [31:0] stored; // temporary variable
initial stored = 32'h00000000;
assign out = stored; // set output wire
always @(posedge clk) #200 stored <= inp;
endmodule // register_32
module register_5(clk, clear, inp, out);
input clk; // accept inp on posedge
input clear; // clear when high
input [4:0] inp; // input data
output [4:0] out; // output of register
wire [4:0] out;
reg [4:0] stored; // temporary variable
initial stored = 5'b00000;
assign out = stored; // set output wire
always @(posedge clk) #200 stored <= inp;
endmodule // register_5
module instruction_memory(addr, inst);
input [31:0] addr;
output [31:0] inst;
integer word_addr;
reg [31:0] memory [0:15];
reg [31:0] inst_word;
assign inst = inst_word;
function [31:0] to_integer;
input [31:0] argument;
to_integer = argument;
endfunction // to_integer
initial
begin
memory[0] = 32'b10001100000000010000000000000100; // lw
memory[1] = 32'b10001100000000100000000000001000; // lw
memory[2] = 32'b00000000000000000000000000000000; // nop
memory[3] = 32'b00000000000000000000000000000000; // nop
memory[4] = 32'b00000000001000100001100000100000; // add
memory[5] = 32'b00000000011000100010000000100010; // sub
memory[6] = 32'b00000000000000010010101111000001; // sll
memory[7] = 32'b00000000000000100011010000000010; // srl
memory[8] = 32'b00000000000000110011100000000100; // cmpl
memory[9] = 32'b10101100000000010000000000001000; // sw
memory[10]= 32'b00000000000000000000000000000000; // nop
memory[11]= 32'b00000000000000000000000000000000; // nop
memory[12]= 32'b00000000000000000000000000000000; // nop
memory[13]= 32'b00000000000000000000000000000000; // nop
memory[14]= 32'b00000000000000000000000000000000; // nop
memory[15]= 32'b00000000000000000000000000000000; // nop
end
always @(addr)
begin // behavior
word_addr = to_integer(addr)/4;
#250 inst_word = memory[word_addr];
end
endmodule // instruction_memory
module data_memory(address, write_data, read_enable, write_enable,
write_clk, read_data);
input [31:0] address;
input [31:0] write_data;
input read_enable;
input write_enable;
input write_clk;
output [31:0] read_data;
wire [31:0] read_data;
integer word_addr;
integer write_addr;
reg [31:0] memory [0:1000];
reg [31:0] data_word;
assign read_data = data_word;
function [31:0] to_integer;
input [31:0] argument;
to_integer = argument;
endfunction // to_integer
initial
begin
memory[0] = 32'b00010001000100010001000100010001; // h0
memory[1] = 32'b00100010001000100010001000100010; // h4
memory[2] = 32'b00110011001100110011001100110011; // h8
end // rest is XXXXXXXXXX
always @(address or posedge read_enable)
begin // behavior
word_addr = to_integer(address)/4;
if(read_enable==1)
#250 data_word <= memory[word_addr];
end
always @(negedge read_enable)
#200 data_word = 32'b00000000000000000000000000000000;
always @(posedge write_clk)
begin
if(write_enable==1)
begin
write_addr = to_integer(address)/4;
memory[write_addr] = write_data;
end
end
endmodule // data_memory
module registers(read_reg_1, read_reg_2, write_reg,
write_data, write_enable, write_clk,
read_data_1, read_data_2);
input [4:0] read_reg_1; // 5 bit register address to read data 1
input [4:0] read_reg_2; // 5 bit register address to read data 2
input [4:0] write_reg; // 5 bit register address to write
input [31:0] write_data; // 32 bit word to write into register
input write_enable; // rising clock and enable
input write_clk; // required to write
output [31:0] read_data_1; // register content of read_reg_1
output [31:0] read_data_2; // register content of read_reg_2
wire [31:0] read_data_1;
wire [31:0] read_data_2;
integer reg_addr_1;
integer reg_addr_2;
integer write_addr;
integer i;
reg [31:0] memory [0:31];
reg [31:0] reg_word_1;
reg [31:0] reg_word_2;
assign read_data_1 = reg_word_1;
assign read_data_2 = reg_word_2;
function [5:0] to_integer;
input [5:0] argument;
to_integer = argument;
endfunction // to_integer
initial
begin
for(i=0; i<32; i=i+1) memory[i] = 32'h00000000;
reg_word_1 = 32'h00000000;
reg_word_2 = 32'h00000000;
end
always @(read_reg_1)
begin
reg_addr_1 = to_integer(read_reg_1);
#50 reg_word_1 <= memory[reg_addr_1];
end
always @(read_reg_2)
begin
reg_addr_2 = to_integer(read_reg_2);
#50 reg_word_2 <= memory[reg_addr_2];
end
always @(posedge write_clk)
begin // behavior
write_addr = to_integer(write_reg);
if(write_enable==1)
begin
#100 memory[write_addr] = write_data;
if(write_reg==read_reg_1) reg_word_1 = write_data;
if(write_reg==read_reg_2) reg_word_2 = write_data;
end
end
endmodule // registers
module mux_32(in0, in1, ctl, result);
parameter n=31;
input [n:0] in0; // 0 input
input [n:0] in1; // 1 input
input ctl; // control
output [n:0] result; // output
assign result = (ctl==0) ? in0 : in1;
endmodule // mux_32
module mux_5(in0, in1, ctl, result);
parameter n=4;
input [n:0] in0; // 0 input
input [n:0] in1; // 1 input
input ctl; // control
output [n:0] result; // output
assign result = (ctl==0) ? in0 : in1;
endmodule // mux_5
module alu_32(inA, inB, inst, result);
input [31:0] inA;
input [31:0] inB;
input [31:0] inst;
output [31:0] result;
wire [31:0] result;
reg cin; //=0
wire cout;
initial cin=0;
add32 adder(inA, inB, cin, result, cout);
endmodule // alu_32
module pipe2; // test bench
// signals used in test bench (the interconnections)
reg [31:0] zero_32; // = 32'h00000000; // 32 bit zero
reg zero; // = 0; // one bit zero
reg [31:0] four_32; // = 32'h00000004; // four
reg clear; // = 1; // one shot clear
reg clk; // = 0; // master clock
wire clk_bar; // split phase for mem write
integer counter; // = 0; // master clock counter, raising edge
wire nc1; // a No-Connection for unused output
wire [31:0] PC_next; // next value of PC
wire [31:0] PC; // Program Counter
wire [31:0] inst; // instruction fetched
wire [31:0] ID_IR; // ID Instruction Register
wire [31:0] ID_read_data_1; // ID Register read data 1
wire [31:0] ID_read_data_2; // ID Register read data 2
wire [31:0] ID_sign_ext; // ID sign extension
wire [4:0] ID_rd; // ID register destination
wire [15:0] ID_addr; // ID_IR[15:0] address
wire RegDst; //=0 // ID selects destination register
wire S; // ID for sign extend
wire [31:0] EX_IR; // EX Instruction Register
wire [31:0] EX_A; // EX data A
wire [31:0] EX_B; // EX data B
wire [31:0] EX_C; // EX data C
wire [4:0] EX_rd; // EX register destination
wire [31:0] EX_aluB; // EX into ALU B
wire ALUSrc; //=1 // EX ALU B side source control
wire [31:0] EX_result; // EX ALU output
wire [31:0] MEM_IR; // MEM Instruction Register
wire [31:0] MEM_addr; // MEM address
wire [31:0] MEM_data; // MEM write data
wire [31:0] MEM_read_data; // MEM read data
wire [4:0] MEM_rd; // MEM register destination
wire MEMRead; // MEM enable read
wire MEMWrite; //=0; // MEM enable write
wire [31:0] WB_IR; // WB Instruction Register
wire [31:0] WB_read; // WB read data
wire [31:0] WB_pass; // WB pass data
wire [4:0] WB_rd; // WB register destination
wire MemtoReg; // WB mux control
wire [31:0] WB_result; // WB mux output
wire WB_write_enb; //=1 // WB enable register write
function [31:0] to_integer;
input [31:0] argument;
to_integer = argument;
endfunction // to_integer
initial
begin
zero_32 = 32'h00000000; // 32 bit zero
zero = 0; // one bit zero
four_32 = 32'h00000004; // four
clear = 1; // one shot clear
clk = 0; // master clock
counter = 0; // master clock counter, raising edge
#200 clear = 0; // clear time finished
forever #5000 clk = ~clk; // run clock 10ns period
end
initial #140000 $finish; // stop after 140 ns
assign ALUSrc = 1; // change to correct expression
assign RegDst = 0; // change to correct expression
assign MEMWrite = 0; // change to correct expression
assign WB_write_enb = 1; // change to correct expression
// schematic of pipe2, behavior and test bench
assign clk_bar = ~clk; // for split phase registers
// IF, Instruction Fetch pipeline stage
register_32 PC_reg(clk, clear, PC_next, PC);
add32 PC_incr(PC, four_32, zero, PC_next, nc1);
instruction_memory inst_mem(PC, inst);
// ID, Instruction Decode and register stack pipeline stage
register_32 ID_IR_reg(clk, clear, inst, ID_IR);
registers ID_regs(.read_reg_1(ID_IR[25:21]),
.read_reg_2(ID_IR[20:16]),
.write_reg(WB_rd),
.write_data(WB_result),
.write_enable(WB_write_enb),
.write_clk(clk_bar),
.read_data_1(ID_read_data_1),
.read_data_2(ID_read_data_2));
mux_5 ID_mux_rd(.in0(ID_IR[20:16]),
.in1(ID_IR[15:11]),
.ctl(RegDst),
.result(ID_rd));
assign ID_sign_ext[15:0] = ID_IR[15:0]; // just wiring
assign ID_sign_ext[31:16] =
{S,S,S,S,S,S,S,S,S,S,S,S,S,S,S,S};
assign S = ID_IR[15];
// EX, Execute pipeline stage
register_32 EX_IR_reg(clk, clear, ID_IR, EX_IR);
register_32 EX_A_reg(clk, clear, ID_read_data_1, EX_A);
register_32 EX_B_reg(clk, clear, ID_read_data_2, EX_B);
register_32 EX_C_reg(clk, clear, ID_sign_ext, EX_C);
register_5 EX_rd_reg(clk, clear, ID_rd, EX_rd);
mux_32 EX_mux1(.in0(EX_B), .in1(EX_C), .ctl(ALUSrc), .result(EX_aluB));
alu_32 ALU(.inA(EX_A),
.inB(EX_aluB),
.inst(EX_IR),
.result(EX_result));
// MEM Data Memory pipeline stage
register_32 MEM_IR_reg(clk, clear, EX_IR, MEM_IR);
register_32 MEM_addr_reg(clk, clear, EX_result, MEM_addr);
register_32 MEM_data_reg(clk, clear, EX_B, MEM_data);
register_5 MEM_rd_reg(clk, clear, EX_rd, MEM_rd);
assign MEMRead = (MEM_IR[31:26] == 6'b100011 );
data_memory data_mem(.address(MEM_addr),
.write_data(MEM_data),
.read_enable(MEMRead),
.write_enable(MEMWrite),
.write_clk(clk_bar),
.read_data(MEM_read_data));
// WB, Write Back pipeline stage
register_32 WB_IR_reg(clk, clear, MEM_IR, WB_IR);
register_32 WB_read_reg(clk, clear, MEM_read_data, WB_read);
register_32 WB_pass_reg(clk, clear, MEM_addr, WB_pass);
register_5 WB_rd_reg(clk, clear, MEM_rd, WB_rd);
assign MemtoReg = (WB_IR[31:26] == 6'b100011 );
mux_32 WB_mux(.in0(WB_pass),
.in1(WB_read),
.ctl(MemtoReg),
.result(WB_result));
always @(posedge clk) // to show state of registers in pipeline
begin
$write("clock %0d", counter);
$write(" inst=%h", inst);
$write(" PC =%h", PC);
$write(" PCnext=%h", PC_next);
$write("\n");
$write("ID stage IR=%h", ID_IR);
if((WB_write_enb==1)&&(WB_rd!=5'b00000))
begin
$write(" write=%h", WB_result);
$write(" into =000000%h", {3'b000,WB_rd});
$write(" ");
end
else
$write(" ");
$write(" rd=%b", ID_rd);
$write("\n");
$write("EX stage IR=%h", EX_IR);
$write(" EX_A =%h", EX_A);
$write(" EX_B =%h", EX_B);
$write(" EX_C =%h", EX_C);
$write(" rd=%b", EX_rd);
$write("\n");
$write("EX stage ");
$write("EX_aluB=%h", EX_aluB);
$write(" EX_res=%h", EX_result);
$write("\n");
$write("MEM stage IR=%h", MEM_IR);
$write(" addr =%h", MEM_addr);
$write(" data =%h", MEM_data);
if(MEMRead==1)
$write(" read =%h", MEM_read_data);
else if(MEMWrite==1)
$write(" wrote=%h", MEM_data);
else
$write(" ");
$write(" rd=%b", MEM_rd);
$write("\n");
$write("WB stage IR=%h", WB_IR);
$write(" read =%h", WB_read);
$write(" pass =%h", WB_pass);
$write(" result=%h", WB_result);
$write(" rd=%b", WB_rd);
$write("\n");
$write("control RegDst=%b", RegDst);
$write(" ALUSrc=%b", ALUSrc);
$write(" MemtoReg=%b", MemtoReg);
$write(" MEMRead=%b", MEMRead);
$write(" MEMWrite=%b", MEMWrite);
$write(" WB_write_enb=%b", WB_write_enb);
$write("\n");
$write("\n"); // blank line
counter = counter+1;
end
endmodule // pipe2