Comment briser toujours bloquer en Verilog?
Je suis en train de simuler un simple processeur MIPS à l'aide de code de comportement en Verilog. J'ai fini d'écrire le code mais j'ai une dernière étape où j'ai envie de casser la bloque toujours après avoir fait avec de l'exécution de la MIPS instructions. Voici mon code:
module MIPS_Processor(output reg[7:0] LEDs, input[7:0] Switches);
reg [31:0] memory[0:4095]; //4K memory cells that are 8 bits wide
reg [31:0] code[0:1023]; //1K memory cells that are 8 bits wide
reg [31:0] registers[0:31]; //32 registers that are 32 bits wide
reg [31:0] PC; //The program counter
reg [31:0] instruction;
reg [5 :0] op;
reg [4 :0] rs;
reg [4 :0] rt;
reg [4 :0] rd;
reg [4 :0] shamt;
reg [5 :0] funct;
reg signed [15:0] immediate_offset;
reg [25:0] target;
reg [1:0] instruction_type; //00 --> R | 01 --> I | 10 --> J | 11 --> EXTRA
reg [31:0] rs_value;
reg [31:0] rt_value;
reg [31:0] rd_value;
reg done = 0;
/*
Here we insert the code in the code array
*/
initial
begin
PC = 0;
end
always
begin
//1. Fetch an instruction from memory
instruction = code[PC];
//2. Increment the program counter register (by the instruction length)
PC = PC + 1;
//3. Decode the instruction
/*
The instructions are:
6 5 5 5 5 6
_____________________________
or rd, rs, rt | 0 | rs | rt | rd | 0 | 0x25 |
6 5 5 16
_____________________________
ori rt, rs, immediate | 0xd | rs | rt | immediate |
6 5 5 5 5 6
_____________________________
and rd, rs, rt | 0 | rs | rt | rd | 0 | 0x24 |
6 5 5 16
_____________________________
andi rt, rs, immediate | 0xc | rs | rt | immediate |
6 5 5 16
_____________________________
beq rs, rt, offset | 4 | rs | rt | offset |
6 5 5 5 5 6
_____________________________
sub rd, rs, rt | 0 | rs | rt | rd | 0 | 0x22 |
6 5 5 5 5 6
_____________________________
add rd, rs, rt | 0 | rs | rt | rd | 0 | 0x20 |
6 5 5 16
_____________________________
addi rt, rs, immediate | 8 | rs | rt | immediate |
6 26
_____________________________
j target | 2 | target |
6 5 5 5 5 6
_____________________________
slt rd, rs, rt | 0 | rs | rt | rd | 0 | 0x2a |
6 5 5 16
_____________________________
lw rt, rs[offset] | 0x23 | rs | rt | offset |
6 5 5 16
_____________________________
sw rt, rs[offset] | 0x2b | rs | rt | offset |
::EXTRA INSTRUCTIONS::
6 5 21
_____________________________
input rs | 4 | rs | 0 |
6 5 21
_____________________________
output rs | 4 | rs | 1 |
*/
op[5:0] = instruction[31:26];
case(op)
0: /* R-type */
begin
rs = instruction[25:21];
rt = instruction[20:16];
rd = instruction[15:11];
shamt = instruction[10:6];
funct = instruction[5:0];
instruction_type = 2'b00;
end
1: /* END OF CODE */
begin
//$finish;
end
2: /* J-type */
begin
target = instruction[25:0];
instruction_type = 2'b10;
end
4: /* EXTRA */
begin
rs = instruction[25:21];
funct = instruction[20:0];
instruction_type = 2'b11;
end
default: /* I-type */
begin
rs = instruction[25:21];
rt = instruction[20:16];
immediate_offset = instruction[15:0];
instruction_type = 2'b01;
end
endcase
//4. Fetch operands, if any, usually from registers
case(instruction_type)
2'b00: /* R-type */
begin
rs_value = registers[rs];
rt_value = registers[rt];
end
2'b01: /* I-type */
begin
rs_value = registers[rs];
end
2'b11: /* EXTRA */
begin
if(funct == 1) rs_value = registers[rs];
end
endcase
//5. Perform the operation
case(instruction_type)
2'b00: /* R-type */
begin
case(funct)
2'h20: /* add rd, rs, rt */
begin
rd_value = rs_value + rt_value;
end
2'h22: /* sub rd, rs, rt */
begin
rd_value = rs_value - rt_value;
end
2'h24: /* and rd, rs, rt */
begin
rd_value = rs_value & rt_value;
end
2'h25: /* or rd, rs, rt */
begin
rd_value = rs_value | rt_value;
end
2'h2a: /* slt rd, rs, rt */
begin
rd_value = rs_value < rt_value? 1 : 0;
end
endcase
end
2'b01: /* I-type */
begin
case(op)
4: /* beq rs, rt, offset */
begin
if(rs_value < rt_value) PC = immediate_offset;
end
8: /* addi rt, rs, immediate */
begin
rt_value = rs_value + immediate_offset;
end
1'hc: /* andi rt, rs, immediate */
begin
rt_value = rs_value & immediate_offset;
end
1'hd: /* ori rt, rs, immediate */
begin
rt_value = rs_value | immediate_offset;
end
2'h23: /* lw rt, rs[offset] */
begin
rt_value = memory[rs + immediate_offset];
end
2'h2b: /* sw rt, rs[offset] */
begin
memory[rs + immediate_offset] = rt_value;
end
endcase
end
2'b10: /* J-type */
begin
case(op)
2: /* j target */
begin
PC = target;
end
endcase
end
2'b11: /* EXTRA */
begin
case(funct)
0: /* input rs */
begin
rs_value[7:0] = Switches;
end
1: /* output rs */
begin
LEDs = rs_value[7:0];
end
endcase
if(funct == 1) rs_value = registers[rs];
end
endcase
//6. Store the results
case(instruction_type)
2'b00: /* R-type */
begin
registers[rd] = rd_value;
end
2'b01: /* I-type */
begin
case(op)
8: /* addi rt, rs, immediate */
begin
registers[rt] = rt_value;
end
1'hc: /* andi rt, rs, immediate */
begin
registers[rt] = rt_value;
end
1'hd: /* ori rt, rs, immediate */
begin
registers[rt] = rt_value;
end
2'h23: /* lw rt, rs[offset] */
begin
registers[rt] = rt_value;
end
endcase
end
2'b11: /* EXTRA */
begin
if(funct == 0) registers[rs] = rs_value;
end
endcase
end
endmodule
J'ai essayé $finir, mais ça ne fonctionne pas:
1: /* END OF CODE */
begin
//$finish;
end
Alors, comment puis-je rompre le always
bloc? ou dois-je utiliser autre chose à la place?
OriginalL'auteur Eng.Fouad | 2012-03-27
Vous devez vous connecter pour publier un commentaire.
Pouvez-vous utiliser un registre de contrôle de la toujours bloquer avec une instruction if?
Le désactiver les causes de la commencer déclaration intitulée "loop_block de" briser, et le permis drapeau empêche la rentrée.
OriginalL'auteur Tim
always
n'est pas unwhile
boucle. Voir wikipedia inscription sur verilog. Puisque vous n'avez pas tout temporelles de consommer des déclarations comme#10
il sera en permanence l'exécution de votre code dans un accidentwhile 1
bloc dans C. Soit ça, ou le compilateur peut simplement drapeau de votre code comme une erreur. Cependant, l'utilisation de#10
dans votre code est juste un hack. Vous voulez vraiment faire de votrealways
bloquer seulement d'exécuter à chaqueposedge clk
ou la création d'un pipline. Ainsi, vous aurez besoin d'un signal d'activation et vous avez besoin pour faire de votre bloquer toujours être@(posedge clk)
pour programmer le bloc à arriver chaque tic d'horloge au lieu de toujours, sans avancer de temps de simulation.Adam, je suis d'accord que syntaxe cela peut être légal dans la grammaire de Verilog, mais un compilateur peut avoir les vérifications sémantiques. Surtout si le compilateur voit qu'une ligne droite, "Bloc de Base" qui revient en boucle sur lui-même avec aucun autre graphe des arcs de différents blocs de base ou d'un sous-graphe des blocs de base ont les mêmes propriétés.
OriginalL'auteur Ross Rogers