Para fines de aprendizaje, estoy tratando de implementar un procesador muy simple en verilog. La idea es que en cada ciclo de reloj, la máquina extraiga las siguientes 4 instrucciones de la memoria (cada instrucción es de 8 bits) o ejecute una instrucción. Sin embargo, estoy teniendo muchos problemas con la PC (yo lo llamo iptr). Mi iptr es un flip-flop disparado por flanco, creo que cuando hay un flanco ascendente del reloj y la señal de habilitación es alta, el iptr debería cambiar el valor. Además, este nuevo valor debe propagarse inmediatamente (a través de un cable) a la unidad de recuperación para decidir si ya está cargado o si debe forzar una búsqueda de instrucciones. El problema es que la unidad de recuperación ve el valor anterior del iptr y no el nuevo valor (o al menos eso creo que es el problema), es como el nuevo valor que se almacena en el iptr en el archivo de registro es No se propaga lo suficientemente rápido. No estoy seguro de cómo solucionar este problema, pero la ayuda es muy apreciada. Esta es la clave de código relevante:
Nota: El procesador es una máquina de pila. He copiado las partes relevantes del código y he revisado un poco las definiciones del módulo porque son un poco largas.
regfile.v:
module regfile(input wareg, wbreg, wcreg, woreg, wwptr, wiptr,
input enareg, enbreg, encreg, enoreg, enwptr, eniptr,
input clk,
output rareg, rbreg, rcreg, roreg, rwptr, riptr);
....
// drive the outputs
assign rareg = areg;
assign rbreg = breg;
assign rcreg = creg;
assign roreg = oreg;
assign rwptr = wptr;
assign riptr = iptr;
initial begin
areg = 32'b0;
breg = 32'b0;
creg = 32'b0;
oreg = 32'b0;
wptr = 32'b0;
iptr = 32'b0;
end
always @ (posedge clk) begin
// If any of the registers are enabled then write
if (enareg) begin
areg <= wareg;
end
if (enbreg) begin
breg <= wbreg;
end
if (encreg) begin
creg <= wcreg;
end
if (enoreg) begin
oreg <= woreg;
end
if (enwptr) begin
wptr <= wwptr;
end
if (eniptr) begin
iptr <= wiptr;
end
end
fetch.v:
module fetch(input iptr, data, clear_buff, clk,
output reg instr, exec_stat, ack_clear);
....
initial begin
// Initially the buffer is empty
// when exec_stat == 1 then we are fetching an instruction
// when exec_stat == 0 then we are executing the instruction at address iptr
empty_instr = 4'b1111;
exec_stat = 1'b1;
end
always @ (posedge clk) begin
// NOTE: in this block is where the problem occurs. The processor fetched the instruction
// just fine when the buffer is empty, then it executed the instruction at 'iptr[1:0] == 0', the
// iptr is incremented correctly. However, in this module the condition 'iptr[1:0] == 0' is still
//true in the next clock cycle and causes theprocessor to go into a fetch, which is clearly wrong
//since I expected "iptr[1:0] == 2'b1"
if (exec_stat == 1'b1) begin
// If we are fetching, store the instruction in the 'data' buffer and set exec_stat low
exec_stat <= 1'b0;
empty_instr[3:0] <= 4'b0000;
instr0 <= data[7:0];
instr1 <= data[15:8];
instr2 <= data[23:16];
instr3 <= data[31:24];
end else if (iptr[1:0] == 2'b00) begin
// the last two bits of the iptr address define which 8-bits from the buffer we need to use as instruction
if (empty_instr[0]) begin
// if there is no instruction at this address then
// go to fetch state
exec_stat <= 1'b1;
end else begin
instr <= instr0;
empty_instr[0] <= 1'b1;
end
end else if (iptr[1:0] == 2'b01) begin
if (empty_instr[1]) begin
exec_stat <= 1'b1;
end else begin
instr <= instr1;
empty_instr[1] <= 1'b1;
end
end else if (iptr[1:0] == 2'b10) begin
if (empty_instr[2]) begin
exec_stat <= 1'b1;
end else begin
instr <= instr2;
empty_instr[2] <= 1'b1;
end
end else if (iptr[1:0] == 2'b11) begin
if (empty_instr[3]) begin
exec_stat <= 1'b1;
end else begin
instr <= instr3;
empty_instr[3] <= 1'b1;
end
end
end
datapath.v:
module datapath(clk);
//this seems a bit odd to me because the iptr input to the nextpc is the same than that to fetch,
//which is connected to the read port of the regfile. I was hoping that the value that fetch would
//see is the updated one and not the old one, but maybe that is too much to hope for. i.e. the value in the regfile is not propagated quickly enough...
// This is the module that increments the iptr, there is also some other
// logic that handles adding offsets for jumps, but that is not being used
// at the momment.
nextpc nextpc(ack_clear, riptr, instr_oreg, jump_type, alu_bool, clk, wiptr, clear_buff);
regfile regfile(wareg, wbreg, wcreg, woreg, wwptr, wiptr,
mux_enareg, mux_enbreg, encreg, enoreg, enwptr, eniptr,
clk,
rareg, rbreg, rcreg, roreg, rwptr, riptr);
// Input iptr is the ouutput from read port of the regfile
fetch fetch(riptr, mem_rdata, clear_buff, clk, instr, exec_stat, ack_clear);
....
¡Gracias!