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.


Simple file loading and display in assembler.

This program let's you load a file and display it in the STDOUT

#nasm -f elf tiny.asm
#gcc -Wall -s -nostdlib tiny.o

It uses some linux calls to load the file. 

This is intended to be a small description on how the .text, .data and .bss sections work. The code is in the .text section of the ELF file format while the other sections are basically the data zones.

;tiny.asm
BITS 32
GLOBAL _start
SECTION .text
_start:
pop ebx ;argc
pop ebx ;argv[0]
pop ebx ;the file name
mov eax,5 ;the syscall number for open()
;the name is in ebx
mov ecx,0   ;O_RDONLY as in fcntl
int 0x80
test eax,eax  ;it is not NULL
jns file_function
mov ebx,eax ;any error goes to ebx
mov eax,1   ;exit syscall
int 0x80
file_function:
mov ebx,eax ;file descriptor
mov eax,3 ;sys read
mov ecx,buf ;*buf
mov edx,bufsize ;*bufsize
int 0x80
write:
mov edx,eax
mov eax,4
mov ebx,1
int 0x80
exit: ;exit(0)
mov eax,1
mov ebx,0
int 0x80
section .data
   bufsize dw      1024

section .bss
   buf     resb    1024

check this site http://leto.net/writing/nasm.php