NEUMANN

Download as pdf or txt
Download as pdf or txt
You are on page 1of 16

ALU

module alu(
input [3:0] opcode,
input [7:0] operand1,
input [7:0] operand2,
output reg [7:0] result,
output [1:0] flags
);

always @(*) begin


case(opcode)
4'b0001: result = operand1 + operand2;
4'b0010: result = operand1 - operand2;
4'b1000,
4'b1001,
4'b1010: result = operand2;
// urmeaza implementarea altor operatii
default: result = 8'd0; // ramura default este obligatorie pentru a ne asigura ca blocul este combinational
endcase
end

assign flags[0] = (result == 0);


assign flags[1] = result[7]; // In complement fata de 2 bitul MSB este bit de semn

endmodule

REGS
module regs(
input clk,
// portul de scriere
input wen,
input [3:0] waddr,
input [7:0] wdata,
// porturile de citire
input [3:0] raddr1,
input [3:0] raddr2,
output [7:0] rdata1,
output [7:0] rdata2
);

reg [7:0] registru [0:15]; // set de 16 registre a câte 8 bi?i fiecare

// portul de scriere
always @(posedge clk) begin
if(wen) registru[waddr] <= wdata; // scriere sincron? - pe ceas - a rezultatului în registrul destina?ie
end

// portul 1 de citire
assign rdata1 = registru[raddr1]; // ie?irea rdata1 este valoarea din registrul cu num?rul raddr1
// portul 2 de citire
assign rdata2 = registru[raddr2]; // ie?irea rdata2 este valoarea din registrul cu num?rul raddr2

endmodule

RALU
module ralu(
input clk,
input rst,
input [3:0] opcode,
input wen,
input [3:0] dest,
input [7:0] wdata,
input [3:0] sursa1,
input [3:0] sursa2,
output [7:0] result,
output reg [1:0] flags
);

wire [7:0] operand1;


wire [7:0] operand2;
wire [1:0] flags_alu;

//-----------------------------------------------------------------------------
regs regs(
.clk (clk ),
.wen (wen ),
.waddr (dest ),
.wdata (wdata ),
.raddr1 (sursa1 ),
.raddr2 (sursa2 ),
.rdata1 (operand1 ),
.rdata2 (operand2 )
);

//-----------------------------------------------------------------------------
alu alu(
.opcode (opcode ),
.operand1 (operand1 ),
.operand2 (operand2 ),
.result (result ),
.flags (flags_alu)
);

//-----------------------------------------------------------------------------
always @(posedge clk) begin
if(rst)
flags <= 2'b00;
else
flags <= flags_alu;
end

endmodule

UCP
module ucp(
input clk,
input rst,
input [3:0] opcode,
input [1:0] flags,
// control signals
output pc_incr,
output pc_load,
output addr_load,
output sel_addr,
output sel_mem_data,
output sel_instr_data,
output ir_load_high,
output ir_load_low,
output regs_wen,
output write
);

localparam FETCH1 = 3'd0;


localparam FETCH2 = 3'd1;
localparam EXECUTE = 3'd2;
localparam LDADDR = 3'd3;
localparam LDCONST = 3'd4;
localparam LD_DATA = 3'd5;
localparam ST_DATA = 3'd6;
localparam HALT = 3'd7;

reg [2:0] state;


reg [9:0] control_vector;

assign pc_incr = control_vector[9];


assign pc_load = control_vector[8];
assign addr_load = control_vector[7];
assign sel_addr = control_vector[6];
assign sel_mem_data = control_vector[5];
assign sel_instr_data = control_vector[4];
assign ir_load_high = control_vector[3];
assign ir_load_low = control_vector[2];
assign regs_wen = control_vector[1];
assign write = control_vector[0];

always @(posedge clk) begin


if(rst) begin
state <= FETCH1;
end
else begin
case(state)

FETCH1: state <= FETCH2;

FETCH2: begin
case(opcode)
4'b0000: state <= FETCH1; // NOP
4'b0001: state <= EXECUTE; // ADD
4'b1000: state <= LDCONST; // LOADC
4'b1001: state <= LDADDR; // LOAD
4'b1010: state <= LDADDR; // STORE
4'b1111: state <= HALT; // HALT
endcase
end

LDCONST: state <= FETCH1;

LDADDR : begin
if(opcode == 4'b1001)
state <= LD_DATA;
if(opcode == 4'b1010)
state <= ST_DATA;
end
LD_DATA: state <= FETCH1;

ST_DATA: state <= FETCH1;

EXECUTE: state <= FETCH1;

HALT : state <= HALT;

default: state <= HALT;


endcase
end
end

always @(*) begin


case(state)
FETCH1 : control_vector = 10'b10_0010_1000; // PC <- PC + 1, IRH <- data_from_mem
FETCH2 : control_vector = 10'b10_0010_0100; // PC <- PC + 1, IRL <- data_from_mem
LDCONST: control_vector = 10'b00_0001_0010; // R[dest] <- instrdata
LDADDR : control_vector = 10'b00_1000_0000; // ADDR <- result,
EXECUTE: control_vector = 10'b00_0000_0010; // R[dest] <- result
LD_DATA: control_vector = 10'b00_0110_0010; // addr = ADDR, R[dest] <- data_from_mem
ST_DATA: control_vector = 10'b00_0100_0001; // addr = ADDR, write
HALT : control_vector = 10'b00_0000_0000; // nothing to do
endcase
end

endmodule
PROCESOR
module processor(
input clk,
input rst,
input [7:0] data_in, // data from memory
output [7:0] data_out, // data to memory
output [7:0] addr, // memory address
output write // memory write enable
);

reg [7:0] pc; // program counter


reg [7:0] data_addr; // address for data in memory
reg [15:0] instruction; // instruction register
reg [7:0] common_data;
wire [3:0] opcode;
wire [3:0] dest;
wire [3:0] sursa1;
wire [3:0] sursa2;
wire [7:0] instr_data;
wire [7:0] result;
wire [1:0] flags;
wire pc_incr;
wire pc_load;
wire addr_load;
wire sel_addr;
wire sel_mem_data;
wire sel_instr_data;
wire ir_load_high;
wire ir_load_low;
wire regs_wen;

//-----------------------------------------------------------------------------
// address mux
assign addr = sel_addr ? data_addr : pc;

//-----------------------------------------------------------------------------
// PC
always @(posedge clk) begin
if(rst)
pc <= 0;
else begin
if(pc_load)
pc <= common_data;
else if(pc_incr)
pc <= pc + 1;
else
pc <= pc;
end
end

//-----------------------------------------------------------------------------
// ADDR
always @(posedge clk) begin
if(rst)
data_addr <= 0;
else begin
if(addr_load)
data_addr <= common_data;
else
data_addr <= data_addr;
end
end

//-----------------------------------------------------------------------------
// IR
always @(posedge clk) begin
if(rst)
instruction <= 0;
else begin
if(ir_load_high)
instruction[15:8] <= common_data;
else if(ir_load_low)
instruction[ 7:0] <= common_data;
else
instruction <= instruction;
end
end
//-----------------------------------------------------------------------------
// decode
assign opcode = instruction[15:12];
assign dest = instruction[11: 8];
assign sursa1 = instruction[ 7: 4];
assign sursa2 = addr_load ? instruction[ 7: 4] : instruction[ 3: 0];
assign instr_data = instruction[ 7: 0];

//-----------------------------------------------------------------------------
// common data mux
always @(*) begin
if(sel_mem_data)
common_data = data_in; // se selecteaz? data dinspre memorie
else if(sel_instr_data)
common_data = instr_data; // se selecteaz? constanta
else
common_data = result; // se selecteaz? rezultatul de la ALU
end

//-----------------------------------------------------------------------------
ralu ralu(
.clk (clk ),
.rst (rst ),
.opcode (opcode ),
.wen (regs_wen ),
.dest (dest ),
.wdata (common_data),
.sursa1 (sursa1 ),
.sursa2 (sursa2 ),
.result (result ),
.flags (flags )
);

//-----------------------------------------------------------------------------

assign data_out = result;

//-----------------------------------------------------------------------------
ucp ucp(
.clk (clk ),
.rst (rst ),
.opcode (opcode ),
.flags (flags ),
.pc_incr (pc_incr ),
.pc_load (pc_load ),
.addr_load (addr_load ),
.sel_addr (sel_addr ),
.sel_mem_data (sel_mem_data ),
.sel_instr_data (sel_instr_data),
.ir_load_high (ir_load_high ),
.ir_load_low (ir_load_low ),
.regs_wen (regs_wen ),
.write (write )
);

Endmodule
MEMORIE
module memory(
input clk,
input write,
input [7:0] addr,
input [7:0] din,
output [7:0] dout
);

reg [7:0] memory [0:255];


// citire din memorie
assign dout = memory[addr];
// scriere in memorie
always @(posedge clk) if(write) memory[addr] <= din;

// program
initial begin
{memory[00], memory[01]} = 16'b1000_0000_1111_1111; // LOADC R0 #255
{memory[02], memory[03]} = 16'b1000_0001_1111_1110; // LOADC R1 #254
{memory[04], memory[05]} = 16'b1000_0010_1111_1101; // LOADC R2 #253
{memory[06], memory[07]} = 16'b1001_0100_0000_0000; // LOAD R4 R0
{memory[08], memory[09]} = 16'b1001_0101_0001_0000; // LOAD R5 R1
{memory[10], memory[11]} = 16'b0001_0110_0101_0100; // ADD R6 R5 R4
{memory[12], memory[13]} = 16'b1010_0000_0010_0110; // STORE R2 R6
{memory[14], memory[15]} = 16'b1111_1111_1111_1111; // HALT
end
// date initiale
initial begin
memory[254] = 17;
memory[255] = 23;
end

endmodule

NEUMANN
module neumann(
input clk,
input rst
);

wire write;
wire [7:0] addr;
wire [7:0] data_from_mem;
wire [7:0] data_to_mem;

processor procesor(
.clk (clk ),
.rst (rst ),
.data_in (data_from_mem),
.data_out(data_to_mem ),
.addr (addr ),
.write (write )
);
memory memorie(
.clk (clk ),
.write (write ),
.addr (addr ),
.din (data_to_mem ),
.dout (data_from_mem)
);

Endmodule

NEUMANN_TB
module neumann_tb;

// declara?ii de variable
reg clk;
reg rst;

// instan?ierea calculatorului
neumann dut(
.clk (clk),
.rst (rst)
);

// generarea semnalului de ceas


initial begin
clk = 0;
forever #10 clk = ~clk;
end

// generarea semnalului de reset


initial begin
rst = 0;
#13 rst = 1; // reset activ în 1 logic
#20 rst = 0;
end

// un bloc initial pentru oprirea simularii


initial begin
repeat (100) @(posedge clk);
$stop;
end

endmodule

You might also like