0% found this document useful (0 votes)
61 views16 pages

NEUMANN

Uploaded by

Patrascu Andrei
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
61 views16 pages

NEUMANN

Uploaded by

Patrascu Andrei
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 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