1.Plasma (most MIPS I (TM))


***** translated.v
  115:                     #(500* `ns) {reset}<=1'b0;
  116:         end//end initial
***** TRANSLATED_W_2.V
  115:                     #(500* `ns) {reset}<=1'b0;
  116:                          #(5000000 *`ns) $finish;//TAK Mar.19.2005
  117:         end//end initial
*****

***** translated.v
  696:     
  697:     
  698:     generate
***** TRANSLATED_W_2.V
  697:     
  698:      parameter ram_proc__mem_size = (2<< (address_width-1));//Mar.19.2005
  699:     generate
*****

***** translated.v
  699:         if ((memory_type === "GENERIC"))begin//generate if 
  700:                     integer ram_proc__mem_size = (2<< (address_width-1));
  701:      reg [31:0] ram_proc__data;
***** TRANSLATED_W_2.V
  700:         if ((memory_type === "GENERIC"))begin//generate if 
  701:                   
  702:      reg [31:0] ram_proc__data;
*****

***** translated.v
  705:     initial begin
  706:             ram_proc__load_file=$fopen("code.txt","r+");
  707:     end
***** TRANSLATED_W_2.V
  706:     initial begin
  707:             ram_proc__load_file=$fopen("code_org.txt","r+");//TAK Mar.19.2005
  708:     end
*****

1.2 RTL simulation
1.2.1 "output.txt"

Only running single file "translated_w_2.v" with Veritak, we can get "output.txt" as follows.

Mult by 3
0000000003: three
0000000009: nine
0000000027: twenty seven
0000000081: eighty one
0000000243: two hundred forty three
0000000729: seven hundred twenty nine
0000002187: two thousand one hundred eighty seven
0000006561: six thousand five hundred sixty one
0000019683: nineteen thousand six hundred eighty three
0000059049: fifty nine thousand forty nine
0000177147: one hundred seventy seven thousand one hundred forty seven
0000531441: five hundred thirty one thousand four hundred forty one
0001594323: one million five hundred ninety four thousand three hundred twenty three
0004782969: four million seven hundred eighty two thousand nine hundred sixty nine
0014348907: fourteen million three hundred forty eight thousand nine hundred seven
0043046721: forty three million forty six thousand seven hundred twenty one
0129140163: one hundred twenty nine million one hundred forty thousand one hundred sixty three
0387420489: three hundred eighty seven million four hundred twenty thousand four hundred eighty nine
1162261467: one billion one hundred sixty two million two hundred sixty one thousand four hundred sixty seven
3486784401: three billion four hundred eighty six million seven hundred eighty four thousand four hundred one
1870418611: one billion eight hundred seventy million four hundred eighteen thousand six hundred eleven
1316288537: one billion three hundred sixteen million two hundred eighty eight thousand five hundred thirty seven
3948865611: three billion nine hundred forty eight million eight hundred sixty five thousand six hundred eleven
3256662241: three billion two hundred fifty six million six hundred sixty two thousand two hundred forty one
1180052131: one billion one hundred eighty million fifty two thousand one hundred thirty one
3540156393: three billion five hundred forty million one hundred fifty six thousand three hundred ninety three
2030534587: two billion thirty million five hundred thirty four thousand five hundred eighty seven
1796636465: one billion seven hundred ninety six million six hundred thirty six thousand four hundred sixty five
1094942099: one billion ninety four million nine hundred forty two thousand ninety nine
3284826297: three billion two hundred eighty four million eight hundred twenty six thousand two hundred ninety seven

This program source is following C code by Steve Rhoads-san.

/*count.c*/
void putchar(int);
int puts(const char*);

char *name[]={
   "","one","two","three","four","five","six","seven","eight","nine",
   "ten","eleven","twelve","thirteen","fourteen","fifteen",
      "sixteen","seventeen","eighteen","nineteen",
   "","ten","twenty","thirty","forty","fifty","sixty","seventy",
      "eighty","ninety"
};

#ifndef MLITE
int puts(const char *ptr)
{
   while(*ptr) {
      putchar(*ptr++);
   }
   return 0;
}
#endif

#if 0
char *xtoa(unsigned long num)
{
   static char buf[12];
   int i,digit;
   buf[8]=0;
   for(i=7;i>=0;--i) {
      digit=num&0xf;
      buf[i]=digit+(digit<10?'0':'A'-10);
      num>>=4;
   }
   return buf;
}
#endif

char *itoa(unsigned long num)
{
   static char buf[12];
   int i;
   buf[10]=0;
   for(i=9;i>=0;--i) {
      buf[i]=(char)((num%10)+'0');
      num/=10;
   }
   return buf;
}

void number_text(unsigned long number)
{
   int digit;
   puts(itoa(number));
   puts(": ");
   if(number>=1000000000) {
      digit=number/1000000000;
      puts(name[digit]);
      puts(" billion ");
      number%=1000000000;
   }
   if(number>=100000000) {
      digit=number/100000000;
      puts(name[digit]);
      puts(" hundred ");
      number%=100000000;
      if(number<1000000) {
         puts("million ");
      }
   }
   if(number>=20000000) {
      digit=number/10000000;
      puts(name[digit+20]);
      putchar(' ');
      number%=10000000;
      if(number<1000000) {
         puts("million ");
      }
   }
   if(number>=1000000) {
      digit=number/1000000;
      puts(name[digit]);
      puts(" million ");
      number%=1000000;
   }
   if(number>=100000) {
      digit=number/100000;
      puts(name[digit]);
      puts(" hundred ");
      number%=100000;
      if(number<1000) {
         puts("thousand ");
      }
   }
   if(number>=20000) {
      digit=number/10000;
      puts(name[digit+20]);
      putchar(' ');
      number%=10000;
      if(number<1000) {
         puts("thousand ");
      }
   }
   if(number>=1000) {
      digit=number/1000;
      puts(name[digit]);
      puts(" thousand ");
      number%=1000;
   }
   if(number>=100) {
      digit=number/100;
      puts(name[digit]);
      puts(" hundred ");
      number%=100;
   }
   if(number>=20) {
      digit=number/10;
      puts(name[digit+20]);
      putchar(' ');
      number%=10;
   }
   puts(name[number]);
   putchar('\r');
   putchar('\n');
}

void main()
{
   unsigned long number,i;
   puts("Mult by 3\r\n");
   number=3;
   for(i=0;;++i) {
      number_text(number);
      number*=3;
   }
}

1.2.3 Print as debugger

It will be convenient if "print"in C is impremented.
With this implemented, you can see like below. You can confirm the simulation is running properly by console at simulation run-time..


C source is ;
//count_tak.c
#define print_port          0x0ff0
#define print_char_port 0x0ff1
#define print_int_port  0x0ff2
#define print_long_port 0x0ff4/*count.c*/


char *name[]={
   "","one","two","three","four","five","six","seven","eight","nine",
   "ten","eleven","twelve","thirteen","fourteen","fifteen",
      "sixteen","seventeen","eighteen","nineteen",
   "","ten","twenty","thirty","forty","fifty","sixty","seventy",
      "eighty","ninety"
};

void print(unsigned char* ptr)//Verilog Test Bench Use 
{

        while (*ptr) {
        
                *(volatile unsigned char*)print_port=*(ptr++);
        }

        *(volatile unsigned char*)print_port=0x00;//Write Done

}
void print_char(unsigned char val)//Little Endian write out 16bit number 
{
        *(volatile unsigned char*)print_port=(unsigned char)val ;

}

1.2.2 Disassembler

It will be convenient for analysis of source code or study of CPU architecture if disassembler is built in. HDL simulator as below.

This can be easily implemented using Verilog-2001 $sformat ($sprintf in C) as below.
This source was added in decoder module. Since MIPS-I has simple 32bit Reduced Instruction Set,it is far simpler than CISC's..

`ifdef Veritak
//Disassemblar
        reg [30*8:1] inst;
        wire [31:0] IR=opcode;//TAK Mar.15.2005
        wire [31:0] PC=pc;//Tak Mar.15.2005
        wire [5:0] op=IR[31:26];
        wire [25:0] bra=PC+{{10{IR[15]}},IR[15:0]}*4;//+4;
        wire [4:0] rs=IR[25:21];
        wire [4:0] rt=IR[20:16];
        wire [4:0] rd=IR[15:11];
        wire [4:0] sh=IR[10:6];
        reg [5*8:1] reg_name="abcd";

    

        function [4*8:1] get_reg_name;
                input [4:0] field;
                begin
                        case (field)
                                0: get_reg_name="$z0";
                                1: get_reg_name="$at";
                                2: get_reg_name="$v0";
                                3: get_reg_name="$v1";
                                4: get_reg_name="$a0";
                                5: get_reg_name="$a1";
                                6: get_reg_name="$a2";
                                7: get_reg_name="$a3";
                                8,9,10,11,12,13,14,15:
                                   $sprintf(get_reg_name,"$t%1d",field-8);
                                16,17,18,19,20,21,22,23,24,25: $sprintf(get_reg_name,"$s%1d",field-16);
                                26:get_reg_name="$k0";
                                27:get_reg_name="$k1";
                                28:get_reg_name="$gp";
                                29:get_reg_name="$sp";
                                30:get_reg_name="$s8";
                                31:get_reg_name="$ra";
                        endcase
                end
        endfunction



        always @*begin:sprintf //Jan.20.2005  @ (IR,op,bra,rs,rt,rd,sh) begin :sprintf
          reg [4*8:1] rdn;//
          reg [4*8:1] rsn;
          reg [4*8:1] rtn;
          rdn=get_reg_name(rd); 
          rsn=get_reg_name(rs);
          rtn=get_reg_name(rt);
          case (op)
           0:   
                case (IR[5:0])
                        0: if (rd==0 && rt==0 && rs==0 ) $sprintf(inst,"nop");
                           else $sprintf(inst,"tsll %s,%s,%2d\n",rdn,rtn,sh);
                        2:
                                $sprintf(inst," srl %s,%s,%2d\n",rdn,rtn,sh);
                        
                      3:
                                $sprintf(inst," sra %s,%s,%2d\n",rdn,rtn,sh);
                        
                       4:
                                $sprintf(inst," sllv %s,%s,%s\n",rdn,rtn,rsn);
                        
                       6:
                                $sprintf(inst," srlv %s,%s,%s\n",rdn,rtn,rsn);
                        
                 7:
                        $sprintf(inst," srav %s,%s,%s\n",rdn,rtn,rsn);
                        
                 8:
                        $sprintf(inst," jr %s\n",rsn);
                        
                 9:
                        $sprintf(inst," jalr %s\n",rsn);
                        
                 12:
                        $sprintf(inst," syscall\n");
                        
                 13:
                        $sprintf(inst," break");
                        
                 16:
                        $sprintf(inst," mfhi %s\n",rdn);
                        
                 17:
                        $sprintf(inst," mthi %s\n",rsn);
                        
                 18:
                        $sprintf(inst," mflo %s\n",rdn);
                        
                 19:
                        $sprintf(inst," mtlo %s\n",rsn);
                        
                 24:
                        $sprintf(inst," mult %s,%s\n",rsn,rtn);
                        
                 25:
                        $sprintf(inst," multu %s,%s\n",rsn,rtn);
                        
                 26:
                        $sprintf(inst," div %s,%s\n",rsn,rtn);
                        
                 27:
                        $sprintf(inst," divu %s,%s\n",rsn,rtn);
                        
                 32:
                        
                        $sprintf(inst," add %s,%s,%s",rdn,rsn,rtn);
                        
                 33:
                        if(rt==0)
                                $sprintf(inst," move %s,%s\n",rdn,rsn);
                        else
                                $sprintf(inst," addu %s,%s,%s\n",rdn,rsn,rtn);
                        
                 34:
                        $sprintf(inst," sub %s,%s,%s\n",rdn,rsn,rtn);
                        
                 35:
                        $sprintf(inst," subu %s,%s,%s\n",rdn,rsn,rtn);
                        
                 36:
                        $sprintf(inst," and %s,%s,%s\n",rdn,rsn,rtn);
                        
                 37:
                        if(rt==0) 
                                $sprintf(inst," move %s,%s\n",rdn,rsn);
                         else
                                $sprintf(inst," or %s,%s,%s\n",rdn,rsn,rtn);
                        
                 38:
                        $sprintf(inst," xor %s,%s,%s\n",rdn,rsn,rtn);
                        
                 39:
                        $sprintf(inst," nor %s,%s,%s\n",rdn,rsn,rtn);
                        
                 42:
                        $sprintf(inst," slt %s,%s,%s\n",rdn,rsn,rtn);
                        
                 43:
                        $sprintf(inst," sltu %s,%s,%s\n",rdn,rsn,rtn);
                        
                default:
                        $sprintf(inst,"Unknown Func. %08h\n",IR);
                        
                
                

                endcase
            1:
                case (IR[20:16])
                 0:
                        $sprintf(inst," bltz %s,$%08h\n",rsn,bra);
                        
                 1:
                        $sprintf(inst," bgez %s,$%08h\n",rsn,bra);
                        
                 16:
                        $sprintf(inst," bltzal %s,$%08h\n",rsn,bra);
                        
                 17:
                        $sprintf(inst," bgezal %s,$%08h\n",rsn,bra);
                        
                default:
                        $sprintf(inst,"Unknown1 %08h\n",IR);
                        
                endcase
                
         2:
                $sprintf(inst," j $%08h\n",((IR*4)&32'h0ffffffc)+(PC&32'hf0000000));
                
         3:
                $sprintf(inst," jal $%08h\n",((IR*4)&32'h0ffffffc)+(PC&32'hf0000000));
                
         4:
                if(rs==0 && rt==0)
                        $sprintf(inst," bra $%08h\n",bra);
                else
                        $sprintf(inst," beq %s,%s,$%08h\n",rsn,rtn,bra);
                
         5:
                $sprintf(inst," bne %s,%s,$%08h\n",rsn,rtn,bra);
                
         6:
                $sprintf(inst," blez %s,$%08h\n",rsn,bra);
                
         7:
                $sprintf(inst," bgtz %s,$%08h\n",rsn,bra);
                
         8:
                $sprintf(inst," addi %s,%s,#$%04h\n",rtn,rsn,IR[15:0]);
                
         9:
                if(rs==0)
                        $sprintf(inst," li %s,#$%08h\n",rtn,IR[15:0]);
                else
                        $sprintf(inst," addiu %s,%s,#$%04h\n",rtn,rsn,IR[15:0]);
                
         10:
                $sprintf(inst," slti %s,%s,#$%04h\n",rtn,rsn,IR[15:0]);
                
         11:
                $sprintf(inst," sltiu %s,%s,#$%04h\n",rtn,rsn,IR[15:0]);
                
         12:
                $sprintf(inst," andi %s,%s,#$%04h\n",rtn,rsn,IR[15:0]);
                
         13:
                if(rs==0)
                        $sprintf(inst," li %s,#$%08h\n",rtn,IR[15:0]);
                else
                        $sprintf(inst," ori %s,%s,#$%04h\n",rtn,rsn,IR[15:0]);
                
         14:
                $sprintf(inst," xori %s,%s,#$%04h\n",rtn,rsn,IR[15:0]);
                
         15://load upper immediate

                        $sprintf(inst," lui %s,#$%04h",rtn,IR[15:0]);
                
         16, 17, 18, 19: begin
                if(rs>=16)
                        $sprintf(inst," cop%d $%08h\n",op&3,IR[25:0]);
                 else
                case(rsn)
                 0:
                        $sprintf(inst," mfc%d %s,%s\n",op&3,rtn,rdn);
                        
                 2:
                        $sprintf(inst," cfc%d %s,%s\n",op&3,rtn,rdn);
                        
                 4:
                        $sprintf(inst," mtc%d %s,%s\n",op&3,rtn,rdn);
                        
                 6:
                        $sprintf(inst," ctc%d %s,%s\n",op&3,rtn,rdn);
                        
                 8, 12:
                        if(rt&1)
                                $sprintf(inst," bc%dt %d,%08h\n",op&3,rs*32+rt,bra);
                         else 
                                $sprintf(inst," bc%df %d,%08h\n",op&3,rs*32+rt,bra);
                        
                        
                 default:
                        $sprintf(inst,"Unknown16 %08h\n",IR);
                 endcase
                end
         32:
                $sprintf(inst," lb %s,$%04h(%s)\n",rtn,IR[15:0],rsn);
                
         33:
                $sprintf(inst," lh %s,$%04h(%s)\n",rtn,IR[15:0],rsn);
                
         34:
                $sprintf(inst," lwl %s,$%04h(%s)\n",IR[15:0],rsn);
                
         35:
                $sprintf(inst," lw %s,$%04h(%s)\n",rtn,IR[15:0],rsn);
                
         36:
                $sprintf(inst," lbu %s,$%04h(%s)\n",rtn,IR[15:0],rsn);
                
         37:
                $sprintf(inst," lhu %s,$%04h(%s)\n",rtn,IR[15:0],rsn);
                
         38:
                $sprintf(inst," lwr %s,$%04h(%s)\n",rtn,IR[15:0],rsn);
                
         40:
                $sprintf(inst," sb %s,$%04h(%s)\n",rtn,IR[15:0],rsn);
                
         41:
                $sprintf(inst," sh %s,$%04h(%s)\n",rtn,IR[15:0],rsn);
                
         42:
                $sprintf(inst," swl %s,$%04h(%s)\n",rtn,IR[15:0],rsn);
                
         43:
                $sprintf(inst," sw %s,$%04h(%s)\n",rtn,IR[15:0],rsn);
                
         46:
                $sprintf(inst," swr %s,$%04h(%s)\n",rtn,IR[15:0],rsn);
                
         48, 49, 50, 51:
                $sprintf(inst," lwc%d %s,$%04h(%s)\n",op&3,rtn,IR[15:0],rsn);
                
         56, 57, 58, 59:
                $sprintf(inst," swc%d %s,$%04h(%s)\n",op&3,rtn,IR[15:0],rsn);
                
        default:
                $sprintf(inst,"UnknownOp %08h\n",IR);
                
        

         
        endcase
   end


`endif

Verilog source is;

  `define RTL_SIM
`ifdef RTL_SIM
    //TAK                             
      `define Print_Port_Address 32'h0000_0ff0  //ATMEL Little Endian
      `define Print_CAHR_Port_Address 32'h0000_0ff1
      `define Print_INT_Port_Address  (32'h0000_0ff2)  //First ADDRESS
      `define Print_LONG_Port_Address (32'h0000_0ff4)  //First ADDRESS

        task Cprint;// String OUT until the byte 00 or xx detected with least Byte first and justified.
                integer i;
                begin :Block
                        i=0;
                        while (1) begin
                                if (char_buffer[i*8 +:8] ===8'h00 || char_buffer[i*8 +:8]===8'hxx) begin
                                                disable Block;
                                end     
                                $write("%c",char_buffer[i*8 +:8]);
                                i=i+1;  
                        end
                end
        endtask

   reg [0:639] char_buffer;
   integer  counter=0;    
   always @ (posedge clk ) begin
            if ((mem_write === 1'b1)) begin 
//                 if (mem_data_w==32'h0101_0101) $stop;     
                   if (mem_address==`Print_Port_Address) begin
                                if (mem_data_w[7:0]===8'h00) begin
                                        char_buffer[counter*8 +:8]=mem_data_w[7:0];
                                        if (char_buffer[0  +:8*7]==="$finish") begin
                                                        $stop;                          
                                                        
                                        end else if (char_buffer[0  +:8*5]==="$time") begin
                                                        $display("Current Time on Simulation=%d",$time);                                
                                                        
                                        end else  Cprint;//$write("%s",char_buffer);

                                        for (counter=0; counter< 80; counter=counter+1) begin
                                                char_buffer[counter*8 +:8]=8'h00;
                                        end
                                        counter=0;
                                
                                end else begin
                                        char_buffer[counter*8 +:8]=mem_data_w[7:0];
                                        counter=counter+1;
                                end
                   end
           else if (mem_address==`Print_CAHR_Port_Address) begin
                                $write("%h ",mem_data_w[7:0]);
                   end else if (mem_address==`Print_INT_Port_Address) begin
                                $write("%h ",mem_data_w[15:0]);//Little Endian 
                   end else if (mem_address==`Print_LONG_Port_Address) begin
                                $write("%h ",mem_data_w[31:0]);//Big Endian
                   end 
        end //if
   end //always

1.2.4 How to compile your C program

Here is my batch file for compiling C source code..
This file should be modified depending on environment. conver_mips.exe is EXE file generates Hex File for Altera/coe file for Xilinx (Derived work to Steve Rhoads-san)

as -o boot.o  ..\tools\boot.asm
gcc  -O2 -O -DMLITE -Dmain=main2 -Wall -S  ..\tak_test_source\count_tak.c
gcc  -O2 -O -DMLITE -Dmain=main2 -Wall -c -s ..\tak_test_source\count_tak.c
ld.exe -Ttext 0 -eentry -Map test.map -s -N -o test.exe boot.o count_tak.o 
objdump.exe --disassemble test.exe > list.txt
copy test.map ..\vhdl\*.*
copy count_tak.s ..\vhdl\*.*
copy list.txt ..\vhdl*.*
convert_mips.exe 
copy code0.hex ..\vhdl\*.*
copy code1.hex ..\vhdl\*.*
copy code2.hex ..\vhdl\*.*
copy code3.hex ..\vhdl\*.*
copy code0.coe ..\vhdl\*.*
copy code1.coe ..\vhdl\*.*
copy code2.coe ..\vhdl\*.*
copy code3.coe ..\vhdl\*.*
copy code.txt ..\vhdl\*.*

1.2.5 Alera /Xilinx RTL simulation

In RTL stage, let's replace generic ram to  specific vendor RAM.
By using Altera MegaWizard/Xilinx Coregen memory file can be generated.
Here is Altera RTL simulation. 8bitx8KByte RAM is generated. (Note: altera_mf.v is not attached in archive)

Here is Xilinx Simulation ( Note XilinxCorelib is not attached in archive.)


1.2.6 Logic Synthesis
 Synthesizer complains many. Revise source file.
 Final Synthesis result is below.

1.2.7 Post Layout Gate Simulation

 Both Altera/Xilinx had the same result of console as RTL.( Ignore SDF timing check message at power on in Veritak. In post layout gate simulation, Clock Period is set at the maximum frequency which synthesizer reported.)

1.1 Translate and Revise
After Veritak Translation,I revised 3 portions. Following is result of "File Compare" before and  after I revised.

"Translated.v " is automatically generated file and "translated_w_2.v" is manually revised file.

First item is to add $finish. This is necessary for closing file operation. "translated.v" generates "output.txt" in virtual UART port. To view "output.txt", closing file is needed
Second item is due to Verilog syntax error. This example shows translators limitation..
Third item is just changing file name for "code.txt", which is initial memory context.

Altera Device is EP1C20F400C6.

1.28 Archive Download(2.7MB)

No File Name Description Veritak Project File Remarks
1 translated.v Automatically Generated File by translator
2 translated_w_2.v Manually Revised File for Veritak RTL Simulation simple_modified_translated.vtakprj
3 demo2.v Added disassembler verilog_mlite_w_disassem.vtakprj
4 demo.v Revised File for Altera Synthesis synthesized_mlite_altera.vtakprj altera_mf.v is not attached.
5 demo_xilinx.v Revised File for Xilinx Synthesis synthesized_mlite_xilinx.vtakprj Xilinxcorelib is not attached.
6 count_tak.c C source for items 3-5
7 convert_tak1.c source file for convert_mips.exe
8 plasma_test2.bat Batch file for c-source compilation and generating memory initialization files.