miércoles, 30 de octubre de 2013

Microprogram based microprocessor

This is a very simple microprocesor written in Verilog:

The alu.v:
module alu( a, b,  c, F2, F1, F0);
input [7:0] a;
input [7:0] b;
input F2,F1,F0;
output reg[7:0] c;

always@(*)
 begin
   if(F2==0 && F1==0 && F0==0)
c=a;
   if(F2==0 && F1==0 && F0==1)
c=b;
   if(F2==0 && F1==1 && F0==0)
c=a+1;
   if(F2==0 && F1==1 && F0==1)
c=b+1;
   if(F2==1 && F1==0 && F0==0)
c=a+b;
   if(F2==1 && F1==0 && F0==1)
c=a-b;
if(F2==1 && F1==1 && F0==0)
c=(a & b);
   if(F2==1 && F1==1 && F0==1)
c=(a | b);
 end
endmodule

module mux( b,mbr, pc,outmux,pins,F1,F0);

input [7:0] b,mbr,pc,pins;
input F1,F0;
output reg [7:0] outmux;


always@(*)
 begin
   if( F1==0 && F0==0)
outmux=b;
   if( F1==0 && F0==1)
outmux=mbr;
   if( F1==1 && F0==0)
outmux=pc;
   if(F1==1 && F0==1)
outmux=pins;
 end



endmodule

module mux2(  mbr, address,JMPC,out_mux2);
input clk;
input [4:0] mbr;
input [4:0] address;
input JMPC;

output reg [4:0] out_mux2;


always@(*)
 begin
   if( JMPC==0)
out_mux2=address;
   if( JMPC==1 )
out_mux2=mbr;
   end



endmodule


module ROM(romaddr,clk,romdout);
parameter size=2;
input clk;
input [4:0] romaddr;
output reg [15:0] romdout;
always @(*)
            case (romaddr)
                0                : romdout = 16'b0000100000000100;//804 Fetch MBR
                1                : romdout = 16'b0001000111000000;//11C0 PC=PC+1
                2                : romdout = 16'b0001100111001000;//19C8 Store PC
                3                : romdout = 16'b0000010000000000;//0400 Goto MBR
                5                : romdout = 16'b0011000000000100;//3004 LOAD A,#0 // Load MBR with MEM
                6                : romdout = 16'b0000000010100001;//00A1 LOAD A
                7                : romdout = 16'b0000000100100001;//40A4 INC A // Load MBRA with MEM
                8                : romdout = 16'b000000100100001;//0020 INC A
default      : romdout = 16'b0000000000000000;//0020 NOP
        endcase          
endmodule


module RAM(ramaddr,clk,ramdout);
parameter size=2;
input clk;
input [7:0] ramaddr;
output reg [7:0] ramdout;
always @(*)
            case (ramaddr)
                        0                : ramdout = 16'b00000000;// NOP
                        1                : ramdout = 16'b00000000;// NOP
                        2                : ramdout = 16'b00000101;//05 Load A,#A6
3  : ramdout = 16'b10100110;//#A6
                        4                : ramdout = 16'b00000111;//07 INC A
5                : ramdout = 16'b00000111;//07 INC A
                        default          : ramdout = 16'b00000000;//00
        endcase          
endmodule

module main;
reg reset=0;
reg[7:0] A;
reg[7:0] B;
reg[4:0] MPC;
reg[7:0] pins;
reg[7:0] MBR;
reg[7:0] OUT,pc;
reg[15:0] MIR;
wire[15:0] bus_MIR;


wire [7:0]bus_pc,bus_out_b,bus_pins;
wire [4:0]muxout;
wire [7:0]bus_data;
always @(posedge MIR[3])
pc=C;
always @(posedge MIR[4])
OUT=C;
always @( MIR[0])
A=C;
always @(posedge MIR[1])
B=C;
always @(posedge clk)
MPC=muxout;
always @(negedge clk )
 if(reset==0)
MIR=bus_MIR;
always @(posedge MIR[2])
  MBR=bus_data;
 initial
 begin
    $dumpfile("main.vcd");
    $dumpvars(0,main);
    reset=1;
    MPC=0;
    pc<=0;
    MBR<=0;
    A<=0;
B<=0;
    pins=10;
#2;
reset=0;
    #3;


#100;
$finish;
 end
  reg clk=0;
  wire [7:0] C;
  mux mux(  B,MBR, pc,bus_out_b,bus_pins,MIR[6],MIR[5]);
  mux2 MUX2( MBR[4:0],MIR[15:11],MIR[10],muxout);
  alu ALU(A,bus_out_b,C,MIR[9],MIR[8],MIR[7]);
  ROM rom (MPC,clk,bus_MIR);
  RAM ram (pc,clk,bus_data);

  always #1 clk = !clk;
endmodule

The command to compile:

iverilog -o dsn alu.v
vvp dsn
gtkwave main.vcd &


It is based on this document http://db.grinnell.edu/sigcse/sigcse2013/Program/viewAcceptedProposal.pdf?sessionType=paper&sessionNumber=39. Only the logical diagram is given so I did the verilog part.

I put additional microcode and registers to enhance the functionality.It  works in a Altera Stratix kit.


No hay comentarios:

Publicar un comentario