data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v
1: b'%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:53: Cannot find include file: jedro_1_defines.v\n`include "jedro_1_defines.v" \n         ^~~~~~~~~~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl,data/full_repos/permissive/522553437/jedro_1_defines.v\n             data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl,data/full_repos/permissive/522553437/jedro_1_defines.v.v\n             data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl,data/full_repos/permissive/522553437/jedro_1_defines.v.sv\n             jedro_1_defines.v\n             jedro_1_defines.v.v\n             jedro_1_defines.v.sv\n             obj_dir/jedro_1_defines.v\n             obj_dir/jedro_1_defines.v.v\n             obj_dir/jedro_1_defines.v.sv\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:65: Define or directive not defined: \'`DATA_WIDTH\'\n  input wire [`DATA_WIDTH-1:0] jmp_address_i,     \n              ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:68: Define or directive not defined: \'`DATA_WIDTH\'\n  output reg [`DATA_WIDTH-1:0] fault_addr_ro,  \n              ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:71: Define or directive not defined: \'`DATA_WIDTH\'\n  output wire [`DATA_WIDTH-1:0] instr_o,      \n               ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:72: Define or directive not defined: \'`DATA_WIDTH\'\n  output wire [`DATA_WIDTH-1:0] addr_o,       \n               ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:77: Define or directive not defined: \'`DATA_WIDTH\'\n  output wire [`DATA_WIDTH-1:0]  ram_addr,\n               ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:78: Define or directive not defined: \'`DATA_WIDTH\'\n  input wire  [`DATA_WIDTH-1:0]  ram_rdata\n               ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:93: Define or directive not defined: \'`DATA_WIDTH\'\nreg [`DATA_WIDTH-1:0] pc_shift_r0;\n     ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:94: Define or directive not defined: \'`DATA_WIDTH\'\nreg [`DATA_WIDTH-1:0] pc_shift_r1;\n     ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:95: Define or directive not defined: \'`DATA_WIDTH\'\nreg [`DATA_WIDTH-1:0] pc_shift_r2;\n     ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:98: Define or directive not defined: \'`DATA_WIDTH\'\nreg [`DATA_WIDTH-1:0] out_instr;  \n     ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:99: Define or directive not defined: \'`DATA_WIDTH\'\nreg [`DATA_WIDTH-1:0] out_addr;\n     ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:101: Define or directive not defined: \'`DATA_WIDTH\'\nreg [`DATA_WIDTH-1:0] dout_r_instr;   \n     ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:102: Define or directive not defined: \'`DATA_WIDTH\'\nreg [`DATA_WIDTH-1:0] dout_r_addr;\n     ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:104: Define or directive not defined: \'`DATA_WIDTH\'\nreg [`DATA_WIDTH-1:0] stall_r_instr;  \n     ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:105: Define or directive not defined: \'`DATA_WIDTH\'\nreg [`DATA_WIDTH-1:0] stall_r_addr;\n     ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:107: Define or directive not defined: \'`DATA_WIDTH\'\nreg [`DATA_WIDTH-1:0] after_stall_r0_instr;  \n     ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:108: Define or directive not defined: \'`DATA_WIDTH\'\nreg [`DATA_WIDTH-1:0] after_stall_r0_addr;\n     ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:110: Define or directive not defined: \'`DATA_WIDTH\'\nreg [`DATA_WIDTH-1:0] after_stall_r1_instr;  \n     ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:111: Define or directive not defined: \'`DATA_WIDTH\'\nreg [`DATA_WIDTH-1:0] after_stall_r1_addr;\n     ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:120: Define or directive not defined: \'`DATA_WIDTH\'\nreg  [`DATA_WIDTH-1:0] after_stall_addr;   \n      ^~~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:204: Define or directive not defined: \'`NOP_INSTR\'\n    {dout_r_instr, dout_r_addr} <= {`NOP_INSTR, 32\'b0};  \n                                    ^~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:204: syntax error, unexpected \',\', expecting TYPE-IDENTIFIER\n    {dout_r_instr, dout_r_addr} <= {`NOP_INSTR, 32\'b0};  \n                                              ^\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:349: Define or directive not defined: \'`NOP_INSTR\'\n    {out_instr, out_addr}  = {`NOP_INSTR, 32\'b0};\n                              ^~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:349: syntax error, unexpected \',\', expecting TYPE-IDENTIFIER\n    {out_instr, out_addr}  = {`NOP_INSTR, 32\'b0};\n                                        ^\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:351: Define or directive not defined: \'`NOP_INSTR\'\n        NV:                                  {out_instr, out_addr} = {`NOP_INSTR, 32\'b0};\n                                                                      ^~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:351: syntax error, unexpected \',\', expecting TYPE-IDENTIFIER\n        NV:                                  {out_instr, out_addr} = {`NOP_INSTR, 32\'b0};\n                                                                                ^\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:364: Define or directive not defined: \'`NOP_INSTR\'\n                     stall_in_stall == 1\'b1) {out_instr, out_addr} = {`NOP_INSTR, 32\'b0};\n                                                                      ^~~~~~~~~~\n%Error: data/full_repos/permissive/522553437/verilog/rtl/riscv-jedro-1/rtl/jedro_1_ifu.v:364: syntax error, unexpected \',\', expecting TYPE-IDENTIFIER\n                     stall_in_stall == 1\'b1) {out_instr, out_addr} = {`NOP_INSTR, 32\'b0};\n                                                                                ^\n%Error: Exiting due to 29 error(s)\n'
module jedro_1_ifu #(
    parameter BOOT_ADDR = 32'h8000_0000
) 
(
  input wire clk_i,
  input wire rstn_i,

  input wire jmp_instr_i,

  
  input wire [`DATA_WIDTH-1:0] jmp_address_i,

  output reg                   exception_ro,
  output reg [`DATA_WIDTH-1:0] fault_addr_ro,


  output wire [`DATA_WIDTH-1:0] instr_o,
  output wire [`DATA_WIDTH-1:0] addr_o,
  output reg                    valid_o,
  input  wire                   ready_i,
  

  output wire [`DATA_WIDTH-1:0]  ram_addr,
  input wire  [`DATA_WIDTH-1:0]  ram_rdata
);

localparam INSTR_SHIFTREG_DEPTH = 3;
localparam NV  = 6'b000001;
localparam DV  = 6'b000010;
localparam S0  = 6'b000100;
localparam S1  = 6'b001000;
localparam S2  = 6'b010000;
localparam EX  = 6'b100000;
localparam XXX = 6'b000000;

reg [5:0] state, next;


reg [`DATA_WIDTH-1:0] pc_shift_r0;
reg [`DATA_WIDTH-1:0] pc_shift_r1;
reg [`DATA_WIDTH-1:0] pc_shift_r2;
reg [INSTR_SHIFTREG_DEPTH-1:0] instr_valid_shift_r;

reg [`DATA_WIDTH-1:0] out_instr;
reg [`DATA_WIDTH-1:0] out_addr;

reg [`DATA_WIDTH-1:0] dout_r_instr;
reg [`DATA_WIDTH-1:0] dout_r_addr;

reg [`DATA_WIDTH-1:0] stall_r_instr;
reg [`DATA_WIDTH-1:0] stall_r_addr;

reg [`DATA_WIDTH-1:0] after_stall_r0_instr;
reg [`DATA_WIDTH-1:0] after_stall_r0_addr;

reg [`DATA_WIDTH-1:0] after_stall_r1_instr;
reg [`DATA_WIDTH-1:0] after_stall_r1_addr;

wire stall_begin_pulse;
reg  stall_begin_pulse_r;
reg  prev_ready;

wire stall_in_stall;
reg  stall_in_stall_r;
wire stall_in_stall_pulse;
reg  [`DATA_WIDTH-1:0] after_stall_addr;

reg jmp_instr;
reg is_exception;


always@(*) begin
    if (jmp_instr_i == 1'b1) begin
        if (jmp_address_i[1:0] == 2'b00) begin
            jmp_instr = 1'b1;
            is_exception = 1'b0;
        end
        else begin
            jmp_instr = 1'b0;
            is_exception = 1'b1;
        end
    end
    else begin
        jmp_instr = 1'b0;
        is_exception = 1'b0;
    end 
end

always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        exception_ro <= 0;
        fault_addr_ro <= 0;       
    end 
    else begin
        exception_ro <= is_exception;
        fault_addr_ro <= jmp_address_i;
    end
end


assign ram_addr = pc_shift_r0;

always @(posedge clk_i) begin
  if (rstn_i == 1'b0) begin
     pc_shift_r0 <= BOOT_ADDR;
     pc_shift_r1 <= BOOT_ADDR;
     pc_shift_r2 <= BOOT_ADDR;
     instr_valid_shift_r <= 3'b001;
  end
  else begin
    if (jmp_instr == 1'b1) begin
        pc_shift_r0 <= jmp_address_i;
        pc_shift_r1 <= jmp_address_i;
        pc_shift_r2 <= jmp_address_i;
        instr_valid_shift_r <= 3'b001;
    end
    else if (stall_in_stall_pulse == 1'b1) begin
        pc_shift_r0 <= after_stall_addr;
        pc_shift_r1 <= after_stall_addr;
        pc_shift_r2 <= after_stall_addr;
        instr_valid_shift_r <= 3'b001;
    end
    else if ((stall_in_stall_r == 1'b1) ||
             (stall_in_stall_r == 1'b0 && ready_i == 1'b0)) begin
        pc_shift_r0 <= pc_shift_r0;
        pc_shift_r1 <= pc_shift_r1;
        pc_shift_r2 <= pc_shift_r2;
        instr_valid_shift_r <= instr_valid_shift_r;
    end
    else begin
        pc_shift_r0 <= pc_shift_r0 + 4;
        pc_shift_r1 <= pc_shift_r0;
        pc_shift_r2 <= pc_shift_r1;
        instr_valid_shift_r <= instr_valid_shift_r << 1;
        instr_valid_shift_r[0] <= 1'b1;
    end
  end
end



always @(posedge clk_i) begin
  if (rstn_i == 1'b0) begin
    {dout_r_instr, dout_r_addr} <= {`NOP_INSTR, 32'b0};
  end
  else begin
    {dout_r_instr, dout_r_addr} <= {ram_rdata, pc_shift_r1};
  end
end

always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        {stall_r_instr, stall_r_addr} <= {32'b0, 32'b0};
    end
    else begin
        if (ready_i == 1'b1) begin
            {stall_r_instr, stall_r_addr} <= {dout_r_instr, dout_r_addr}; 
        end
        else begin
            {stall_r_instr, stall_r_addr} <= {stall_r_instr, stall_r_addr};
        end
    end
end

always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        {after_stall_r0_instr, after_stall_r0_addr} <= 0;
    end
    else begin
        if (stall_begin_pulse == 1'b1 && state == DV) begin
            {after_stall_r0_instr, after_stall_r0_addr} <= {dout_r_instr, dout_r_addr};
        end
        else begin
            {after_stall_r0_instr, after_stall_r0_addr} <= {after_stall_r0_instr, after_stall_r0_addr};
        end
    end
end

always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        {after_stall_r1_instr, after_stall_r1_addr} <= {32'b0, 32'b0};
    end
    else begin
        if (stall_begin_pulse_r == 1'b1 && state == S0) begin
            {after_stall_r1_instr, after_stall_r1_addr} <= {dout_r_instr, dout_r_addr};
        end
        else begin
            {after_stall_r1_instr, after_stall_r1_addr} <= {after_stall_r1_instr, after_stall_r1_addr};
        end
    end
end

always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        after_stall_addr <= 0;
    end
    else begin
        if (state == DV && ready_i == 1'b0) begin
            after_stall_addr <= pc_shift_r0;
        end
        else begin
            after_stall_addr <= after_stall_addr;
        end
    end
end


always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        prev_ready <= 1'b0;
    end
    else begin
        prev_ready <= ready_i;
    end
end

assign stall_begin_pulse = prev_ready  & (~ready_i) & valid_o;
always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        stall_begin_pulse_r <= 1'b0;
    end
    else begin
        stall_begin_pulse_r <= stall_begin_pulse;
    end
end

assign stall_in_stall = stall_in_stall_r || stall_in_stall_pulse;
assign stall_in_stall_pulse = prev_ready & (~ready_i) & (state == S1 || state == S2) & (~stall_in_stall_r);
always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        stall_in_stall_r <= 0;
    end
    else begin
        if (stall_in_stall_pulse == 1'b1) stall_in_stall_r <= 1'b1;
        else if (next == NV)              stall_in_stall_r <= 1'b0;
        else                              stall_in_stall_r <= stall_in_stall_r;
    end
end


assign instr_o = out_instr;
assign addr_o  = out_addr;

always @(posedge clk_i) begin
    if (rstn_i == 1'b0) state <= NV;
    else                state <= next;
end

always@(*) begin
    next = XXX;
    case (state)
        NV : if (instr_valid_shift_r[1] == 1'b1) next = DV;
             else                                next = NV;

        DV : if      (is_exception)              next = EX;
             else if (jmp_instr == 1'b1)         next = NV;
             else if (ready_i == 1'b1)           next = DV;
             else                                next = S0;
                
        S0 : if      (is_exception)              next = EX;
             else if (jmp_instr == 1'b1)         next = NV;
             else if (ready_i == 1'b0)           next = S0;
             else                                next = S1;

        S1 : if      (is_exception)              next = EX;
             else if (jmp_instr == 1'b1)         next = NV;
             else if (ready_i == 1'b0)           next = S1;
             else                                next = S2;

        S2 : if      (is_exception)              next = EX;
             else if (jmp_instr == 1'b1)         next = NV;
             else if (ready_i == 1'b0)           next = S2;
             else if (ready_i == 1'b1 && 
                      stall_in_stall == 1'b1)    next = NV;
             else                                next = DV;
        
        EX : if    (jmp_instr)                   next = NV;
             else                                next = EX;
        
        default :                                next = XXX;
    endcase 
end

always@(*) begin
    {out_instr, out_addr}  = {`NOP_INSTR, 32'b0};
    case (state)
        NV:                                  {out_instr, out_addr} = {`NOP_INSTR, 32'b0};

        DV: if (ready_i == 1'b1)             {out_instr, out_addr} = {dout_r_instr, dout_r_addr};
            else                             {out_instr, out_addr} = {stall_r_instr, stall_r_addr};

        S0: if (ready_i == 1'b0)             {out_instr, out_addr} = {stall_r_instr, stall_r_addr};
            else                             {out_instr, out_addr} = {after_stall_r0_instr, after_stall_r0_addr};

        S1: if (ready_i == 1'b0)             {out_instr, out_addr} = {after_stall_r0_instr, after_stall_r0_addr};
            else                             {out_instr, out_addr} = {after_stall_r1_instr, after_stall_r1_addr};

        S2: if (ready_i == 1'b0)             {out_instr, out_addr} = {after_stall_r1_instr, after_stall_r1_addr};
            else if (ready_i == 1'b1 &&
                     stall_in_stall == 1'b1) {out_instr, out_addr} = {`NOP_INSTR, 32'b0};
            else                             {out_instr, out_addr} = {dout_r_instr, dout_r_addr};

        EX:                                  {out_instr, out_addr} = {dout_r_instr, dout_r_addr};

        default:                             {out_instr, out_addr} = {32'b0, 32'b0};
    endcase
end

always@(*) begin
    if ((state == NV) || 
        (jmp_instr == 1'b1) ||
        (state == S2 && ready_i == 1'b1 && 
         stall_in_stall == 1'b1) ||
        (state == EX))                                             valid_o = 1'b0;
    else                                                           valid_o = 1'b1;
end

endmodule
module jedro_1_ifu #(
    parameter BOOT_ADDR = 32'h8000_0000
) 
(
  input wire clk_i,
  input wire rstn_i,

  input wire jmp_instr_i,

  
  input wire [`DATA_WIDTH-1:0] jmp_address_i,

  output reg                   exception_ro,
  output reg [`DATA_WIDTH-1:0] fault_addr_ro,


  output wire [`DATA_WIDTH-1:0] instr_o,
  output wire [`DATA_WIDTH-1:0] addr_o,
  output reg                    valid_o,
  input  wire                   ready_i,
  

  output wire [`DATA_WIDTH-1:0]  ram_addr,
  input wire  [`DATA_WIDTH-1:0]  ram_rdata
);


localparam INSTR_SHIFTREG_DEPTH = 3;
localparam NV  = 6'b000001;
localparam DV  = 6'b000010;
localparam S0  = 6'b000100;
localparam S1  = 6'b001000;
localparam S2  = 6'b010000;
localparam EX  = 6'b100000;
localparam XXX = 6'b000000;

reg [5:0] state, next;


reg [`DATA_WIDTH-1:0] pc_shift_r0;
reg [`DATA_WIDTH-1:0] pc_shift_r1;
reg [`DATA_WIDTH-1:0] pc_shift_r2;
reg [INSTR_SHIFTREG_DEPTH-1:0] instr_valid_shift_r;

reg [`DATA_WIDTH-1:0] out_instr;
reg [`DATA_WIDTH-1:0] out_addr;

reg [`DATA_WIDTH-1:0] dout_r_instr;
reg [`DATA_WIDTH-1:0] dout_r_addr;

reg [`DATA_WIDTH-1:0] stall_r_instr;
reg [`DATA_WIDTH-1:0] stall_r_addr;

reg [`DATA_WIDTH-1:0] after_stall_r0_instr;
reg [`DATA_WIDTH-1:0] after_stall_r0_addr;

reg [`DATA_WIDTH-1:0] after_stall_r1_instr;
reg [`DATA_WIDTH-1:0] after_stall_r1_addr;

wire stall_begin_pulse;
reg  stall_begin_pulse_r;
reg  prev_ready;

wire stall_in_stall;
reg  stall_in_stall_r;
wire stall_in_stall_pulse;
reg  [`DATA_WIDTH-1:0] after_stall_addr;

reg jmp_instr;
reg is_exception;


always@(*) begin
    if (jmp_instr_i == 1'b1) begin
        if (jmp_address_i[1:0] == 2'b00) begin
            jmp_instr = 1'b1;
            is_exception = 1'b0;
        end
        else begin
            jmp_instr = 1'b0;
            is_exception = 1'b1;
        end
    end
    else begin
        jmp_instr = 1'b0;
        is_exception = 1'b0;
    end 
end

always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        exception_ro <= 0;
        fault_addr_ro <= 0;       
    end 
    else begin
        exception_ro <= is_exception;
        fault_addr_ro <= jmp_address_i;
    end
end


assign ram_addr = pc_shift_r0;

always @(posedge clk_i) begin
  if (rstn_i == 1'b0) begin
     pc_shift_r0 <= BOOT_ADDR;
     pc_shift_r1 <= BOOT_ADDR;
     pc_shift_r2 <= BOOT_ADDR;
     instr_valid_shift_r <= 3'b001;
  end
  else begin
    if (jmp_instr == 1'b1) begin
        pc_shift_r0 <= jmp_address_i;
        pc_shift_r1 <= jmp_address_i;
        pc_shift_r2 <= jmp_address_i;
        instr_valid_shift_r <= 3'b001;
    end
    else if (stall_in_stall_pulse == 1'b1) begin
        pc_shift_r0 <= after_stall_addr;
        pc_shift_r1 <= after_stall_addr;
        pc_shift_r2 <= after_stall_addr;
        instr_valid_shift_r <= 3'b001;
    end
    else if ((stall_in_stall_r == 1'b1) ||
             (stall_in_stall_r == 1'b0 && ready_i == 1'b0)) begin
        pc_shift_r0 <= pc_shift_r0;
        pc_shift_r1 <= pc_shift_r1;
        pc_shift_r2 <= pc_shift_r2;
        instr_valid_shift_r <= instr_valid_shift_r;
    end
    else begin
        pc_shift_r0 <= pc_shift_r0 + 4;
        pc_shift_r1 <= pc_shift_r0;
        pc_shift_r2 <= pc_shift_r1;
        instr_valid_shift_r <= instr_valid_shift_r << 1;
        instr_valid_shift_r[0] <= 1'b1;
    end
  end
end



always @(posedge clk_i) begin
  if (rstn_i == 1'b0) begin
    {dout_r_instr, dout_r_addr} <= {`NOP_INSTR, 32'b0};
  end
  else begin
    {dout_r_instr, dout_r_addr} <= {ram_rdata, pc_shift_r1};
  end
end

always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        {stall_r_instr, stall_r_addr} <= {32'b0, 32'b0};
    end
    else begin
        if (ready_i == 1'b1) begin
            {stall_r_instr, stall_r_addr} <= {dout_r_instr, dout_r_addr}; 
        end
        else begin
            {stall_r_instr, stall_r_addr} <= {stall_r_instr, stall_r_addr};
        end
    end
end

always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        {after_stall_r0_instr, after_stall_r0_addr} <= 0;
    end
    else begin
        if (stall_begin_pulse == 1'b1 && state == DV) begin
            {after_stall_r0_instr, after_stall_r0_addr} <= {dout_r_instr, dout_r_addr};
        end
        else begin
            {after_stall_r0_instr, after_stall_r0_addr} <= {after_stall_r0_instr, after_stall_r0_addr};
        end
    end
end

always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        {after_stall_r1_instr, after_stall_r1_addr} <= {32'b0, 32'b0};
    end
    else begin
        if (stall_begin_pulse_r == 1'b1 && state == S0) begin
            {after_stall_r1_instr, after_stall_r1_addr} <= {dout_r_instr, dout_r_addr};
        end
        else begin
            {after_stall_r1_instr, after_stall_r1_addr} <= {after_stall_r1_instr, after_stall_r1_addr};
        end
    end
end

always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        after_stall_addr <= 0;
    end
    else begin
        if (state == DV && ready_i == 1'b0) begin
            after_stall_addr <= pc_shift_r0;
        end
        else begin
            after_stall_addr <= after_stall_addr;
        end
    end
end


always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        prev_ready <= 1'b0;
    end
    else begin
        prev_ready <= ready_i;
    end
end

assign stall_begin_pulse = prev_ready  & (~ready_i) & valid_o;
always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        stall_begin_pulse_r <= 1'b0;
    end
    else begin
        stall_begin_pulse_r <= stall_begin_pulse;
    end
end

assign stall_in_stall = stall_in_stall_r || stall_in_stall_pulse;
assign stall_in_stall_pulse = prev_ready & (~ready_i) & (state == S1 || state == S2) & (~stall_in_stall_r);
always @(posedge clk_i) begin
    if (rstn_i == 1'b0) begin
        stall_in_stall_r <= 0;
    end
    else begin
        if (stall_in_stall_pulse == 1'b1) stall_in_stall_r <= 1'b1;
        else if (next == NV)              stall_in_stall_r <= 1'b0;
        else                              stall_in_stall_r <= stall_in_stall_r;
    end
end


assign instr_o = out_instr;
assign addr_o  = out_addr;

always @(posedge clk_i) begin
    if (rstn_i == 1'b0) state <= NV;
    else                state <= next;
end

always@(*) begin
    next = XXX;
    case (state)
        NV : if (instr_valid_shift_r[1] == 1'b1) next = DV;
             else                                next = NV;

        DV : if      (is_exception)              next = EX;
             else if (jmp_instr == 1'b1)         next = NV;
             else if (ready_i == 1'b1)           next = DV;
             else                                next = S0;
                
        S0 : if      (is_exception)              next = EX;
             else if (jmp_instr == 1'b1)         next = NV;
             else if (ready_i == 1'b0)           next = S0;
             else                                next = S1;

        S1 : if      (is_exception)              next = EX;
             else if (jmp_instr == 1'b1)         next = NV;
             else if (ready_i == 1'b0)           next = S1;
             else                                next = S2;

        S2 : if      (is_exception)              next = EX;
             else if (jmp_instr == 1'b1)         next = NV;
             else if (ready_i == 1'b0)           next = S2;
             else if (ready_i == 1'b1 && 
                      stall_in_stall == 1'b1)    next = NV;
             else                                next = DV;
        
        EX : if    (jmp_instr)                   next = NV;
             else                                next = EX;
        
        default :                                next = XXX;
    endcase 
end

always@(*) begin
    {out_instr, out_addr}  = {`NOP_INSTR, 32'b0};
    case (state)
        NV:                                  {out_instr, out_addr} = {`NOP_INSTR, 32'b0};

        DV: if (ready_i == 1'b1)             {out_instr, out_addr} = {dout_r_instr, dout_r_addr};
            else                             {out_instr, out_addr} = {stall_r_instr, stall_r_addr};

        S0: if (ready_i == 1'b0)             {out_instr, out_addr} = {stall_r_instr, stall_r_addr};
            else                             {out_instr, out_addr} = {after_stall_r0_instr, after_stall_r0_addr};

        S1: if (ready_i == 1'b0)             {out_instr, out_addr} = {after_stall_r0_instr, after_stall_r0_addr};
            else                             {out_instr, out_addr} = {after_stall_r1_instr, after_stall_r1_addr};

        S2: if (ready_i == 1'b0)             {out_instr, out_addr} = {after_stall_r1_instr, after_stall_r1_addr};
            else if (ready_i == 1'b1 &&
                     stall_in_stall == 1'b1) {out_instr, out_addr} = {`NOP_INSTR, 32'b0};
            else                             {out_instr, out_addr} = {dout_r_instr, dout_r_addr};

        EX:                                  {out_instr, out_addr} = {dout_r_instr, dout_r_addr};

        default:                             {out_instr, out_addr} = {32'b0, 32'b0};
    endcase
end

always@(*) begin
    if ((state == NV) || 
        (jmp_instr == 1'b1) ||
        (state == S2 && ready_i == 1'b1 && 
         stall_in_stall == 1'b1) ||
        (state == EX))                                             valid_o = 1'b0;
    else                                                           valid_o = 1'b1;
end

endmodule