***** 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.
|
---|
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..
//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. |