OpenCores
URL https://opencores.org/ocsvn/zap/zap/trunk

Subversion Repositories zap

[/] [zap/] [trunk/] [src/] [rtl/] [cpu/] [zap_writeback.v] - Diff between revs 26 and 43

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 26 Rev 43
Line 35... Line 35...
        // Shelve output.
        // Shelve output.
        output wire                          o_shelve,
        output wire                          o_shelve,
 
 
        // Clock and reset.
        // Clock and reset.
        input wire                           i_clk,
        input wire                           i_clk,
 
        input wire                           i_reset,
 
 
        input wire                           i_reset,   // ZAP reset.
 
 
 
        // Inputs from memory unit valid signal.
        // Inputs from memory unit valid signal.
        input wire                           i_valid,
        input wire                           i_valid,
 
 
        // The PC can either be frozen in place or changed based on signals
        // The PC can either be frozen in place or changed based on signals
Line 86... Line 84...
        // stage and is buffered all the way through.
        // stage and is buffered all the way through.
        input   wire    [31:0]               i_pc_buf_ff,
        input   wire    [31:0]               i_pc_buf_ff,
 
 
        // Coprocessor.
        // Coprocessor.
        input wire                              i_copro_reg_en,
        input wire                              i_copro_reg_en,
 
 
        input wire      [$clog2(PHY_REGS)-1:0]  i_copro_reg_wr_index,
        input wire      [$clog2(PHY_REGS)-1:0]  i_copro_reg_wr_index,
        input wire      [$clog2(PHY_REGS)-1:0]  i_copro_reg_rd_index,
        input wire      [$clog2(PHY_REGS)-1:0]  i_copro_reg_rd_index,
 
 
        input wire      [31:0]                  i_copro_reg_wr_data,
        input wire      [31:0]                  i_copro_reg_wr_data,
 
 
        output reg      [31:0]                  o_copro_reg_rd_data_ff,
        output reg      [31:0]                  o_copro_reg_rd_data_ff,
 
 
        // Read data from the register file.
        // Read data from the register file.
        output wire     [31:0]               o_rd_data_0,
        output wire     [31:0]               o_rd_data_0,
        output wire     [31:0]               o_rd_data_1,
        output wire     [31:0]               o_rd_data_1,
        output wire     [31:0]               o_rd_data_2,
        output wire     [31:0]               o_rd_data_2,
        output wire     [31:0]               o_rd_data_3,
        output wire     [31:0]               o_rd_data_3,
 
 
        // Program counter (dedicated port).
        // Program counter (dedicated port).
        output reg      [31:0]               o_pc,
        output wire     [31:0]               o_pc,
        output reg      [31:0]               o_pc_nxt,
        output wire     [31:0]               o_pc_nxt,
 
 
        // CPSR output
        // CPSR output
        output reg       [31:0]              o_cpsr_nxt,
        output wire      [31:0]              o_cpsr_nxt,
 
 
        // Clear from writeback
        // Clear from writeback
        output reg                           o_clear_from_writeback,
        output reg                           o_clear_from_writeback,
 
 
        // Hijack I/F
        // Hijack I/F
Line 118... Line 113...
        output reg                            o_hijack_cin,
        output reg                            o_hijack_cin,
        output reg                            o_hijack,
        output reg                            o_hijack,
        input wire     [31:0]                 i_hijack_sum
        input wire     [31:0]                 i_hijack_sum
);
);
 
 
///////////////////////////////////////////////////////////////////////////////
`include "zap_defines.vh"
 
`include "zap_localparams.vh"
 
`include "zap_functions.vh"
 
 
 
// ----------------------------------------------
 
// Localparams
 
// ----------------------------------------------
 
 
`ifndef SYNTHESIS
`ifndef ARM_MODE
 
        `define ARM_MODE (cpsr_ff[T] == 1'd0)
 
`endif
 
 
 
localparam RST_VECTOR   = 32'h00000000;
 
localparam UND_VECTOR   = 32'h00000004;
 
localparam SWI_VECTOR   = 32'h00000008;
 
localparam PABT_VECTOR  = 32'h0000000C;
 
localparam DABT_VECTOR  = 32'h00000010;
 
localparam IRQ_VECTOR   = 32'h00000018;
 
localparam FIQ_VECTOR   = 32'h0000001C;
 
 
 
// ----------------------------------------------
 
// Variables
 
// ----------------------------------------------
 
 
 
// assertions_start
reg fiq_ack;
reg fiq_ack;
reg irq_ack;
reg irq_ack;
reg und_ack;
reg und_ack;
reg dabt_ack;
reg dabt_ack;
reg iabt_ack;
reg iabt_ack;
reg swi_ack;
reg swi_ack;
 
        integer irq_addr = 0;
 
        reg temp_set = 0;
 
        reg error = 0;
 
// assertions_end
 
 
`endif
 
 
 
// PC and CPSR are separate registers.
 
reg     [31:0]  cpsr_ff, cpsr_nxt;
reg     [31:0]  cpsr_ff, cpsr_nxt;
reg     [31:0]  pc_ff, pc_nxt;
reg     [31:0]  pc_ff, pc_nxt;
 
 
reg [$clog2(PHY_REGS)-1:0]     wa1, wa2;
reg [$clog2(PHY_REGS)-1:0]     wa1, wa2;
reg [31:0]                     wdata1, wdata2;
reg [31:0]                     wdata1, wdata2;
reg                            wen;
reg                            wen;
 
 
reg [31:0] pc_shelve_ff, pc_shelve_nxt;
reg [31:0] pc_shelve_ff, pc_shelve_nxt;
reg shelve_ff, shelve_nxt;
reg shelve_ff, shelve_nxt;
 
 
 
assign  o_shelve        = shelve_ff; // Shelve the PC until it is needed.
assign o_shelve = shelve_ff;
assign  o_pc            = pc_ff;
 
assign  o_pc_nxt        = pc_nxt & 32'hfffffffe;
`ifndef SYNTHESIS
assign  o_cpsr_nxt      = cpsr_nxt;
integer irq_addr = 0;
 
`endif
// ----------------------------------------------
 
// Register file
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------
 
 
// Coprocessor accesses.
 
always @ (posedge i_clk)
 
begin
 
        o_copro_reg_rd_data_ff <= i_reset ? 0 : o_rd_data_0;
 
end
 
 
 
///////////////////////////////////////////////////////////////////////////////
 
 
 
localparam RST_VECTOR   = 32'h00000000;
 
localparam UND_VECTOR   = 32'h00000004;
 
localparam SWI_VECTOR   = 32'h00000008;
 
localparam PABT_VECTOR  = 32'h0000000C;
 
localparam DABT_VECTOR  = 32'h00000010;
 
localparam IRQ_VECTOR   = 32'h00000018;
 
localparam FIQ_VECTOR   = 32'h0000001C;
 
 
 
///////////////////////////////////////////////////////////////////////////////
 
 
 
`include "zap_defines.vh"
 
`include "zap_localparams.vh"
 
`include "zap_functions.vh"
 
 
 
///////////////////////////////////////////////////////////////////////////////
 
 
 
// CPSR dedicated output.
 
always @*
 
begin
 
        o_pc            = pc_ff;
 
        o_pc_nxt        = pc_nxt & 32'hfffffffe;
 
        o_cpsr_nxt      = cpsr_nxt;
 
end
 
 
 
///////////////////////////////////////////////////////////////////////////////
 
 
 
zap_register_file u_zap_register_file
zap_register_file u_zap_register_file
(
(
.i_clk(i_clk),
.i_clk(i_clk),
 .i_reset        (       i_reset         ),
 .i_reset        (       i_reset         ),
Line 210... Line 190...
 .o_rd_data_b    (       o_rd_data_1     ),
 .o_rd_data_b    (       o_rd_data_1     ),
 .o_rd_data_c    (       o_rd_data_2     ),
 .o_rd_data_c    (       o_rd_data_2     ),
 .o_rd_data_d    (       o_rd_data_3     )
 .o_rd_data_d    (       o_rd_data_3     )
);
);
 
 
///////////////////////////////////////////////////////////////////////////////
// ---------------------------------------------
 
// Combinational Logic
`define ARM_MODE (cpsr_ff[T] == 1'd0)
// ---------------------------------------------
 
 
`ifndef SYNTHESIS
 
reg temp_set;
 
reg error;
 
initial error = 0;
 
initial temp_set = 0;
 
`endif
 
 
 
// The register file function.
always @ (*)
always @*
 
begin: blk1
begin: blk1
 
 
        integer i;
        integer i;
 
 
        shelve_nxt = shelve_ff;
        shelve_nxt = shelve_ff;
        pc_shelve_nxt = pc_shelve_ff;
        pc_shelve_nxt = pc_shelve_ff;
 
 
 
        // assertions_start
 
 
        `ifndef SYNTHESIS
 
                fiq_ack = 0;
                fiq_ack = 0;
                irq_ack = 0;
                irq_ack = 0;
                und_ack = 0;
                und_ack = 0;
                dabt_ack = 0;
                dabt_ack = 0;
                iabt_ack = 0;
                iabt_ack = 0;
                swi_ack = 0;
                swi_ack = 0;
        `endif
        // assertions_end
 
 
        o_hijack    =  0;
        o_hijack    =  0;
        o_hijack_op1 = 0;
        o_hijack_op1 = 0;
        o_hijack_op2 = 0;
        o_hijack_op2 = 0;
        o_hijack_cin = 0;
        o_hijack_cin = 0;
Line 258... Line 228...
 
 
        pc_nxt = pc_ff;
        pc_nxt = pc_ff;
        cpsr_nxt = cpsr_ff;
        cpsr_nxt = cpsr_ff;
 
 
 
 
        // PC control sequence.
        // Low priority PC control tree.
 
 
 
 
        if ( i_clear_from_alu )
        if ( i_clear_from_alu )
        begin
        begin
                pc_shelve(i_pc_from_alu);
                pc_shelve(i_pc_from_alu);
        end
        end
Line 304... Line 273...
                o_clear_from_writeback  = 1'd1;
                o_clear_from_writeback  = 1'd1;
                cpsr_nxt[I]      = 1'd1; // Mask interrupts.
                cpsr_nxt[I]      = 1'd1; // Mask interrupts.
                cpsr_nxt[T]      = 1'd0; // Go to ARM mode.
                cpsr_nxt[T]      = 1'd0; // Go to ARM mode.
        end
        end
 
 
 
 
        if ( i_data_abt )
        if ( i_data_abt )
        begin
        begin
                o_hijack    =  1'd1;
                o_hijack    =  1'd1;
                o_hijack_op1 = i_pc_buf_ff;
                o_hijack_op1 = i_pc_buf_ff;
                o_hijack_op2 = 32'd4;
                o_hijack_op2 = 32'd4;
                o_hijack_cin = 1'd0;
                o_hijack_cin = 1'd0;
 
 
                // Returns do LR - 8 to get back to the same instruction.
                // Returns do LR - 8 to get back to the same instruction.
                pc_shelve( DABT_VECTOR );
                pc_shelve( DABT_VECTOR );
 
 
                wen    = 1;
                wen    = 1;
                wdata1 = `ARM_MODE ? i_pc_buf_ff : i_hijack_sum[31:0];
                wdata1 = `ARM_MODE ? i_pc_buf_ff : i_hijack_sum[31:0];
                wa1    = PHY_ABT_R14;
                wa1    = PHY_ABT_R14;
                wa2    = PHY_ABT_SPSR;
                wa2    = PHY_ABT_SPSR;
                wdata2 = cpsr_ff;
                wdata2 = cpsr_ff;
                cpsr_nxt[`CPSR_MODE]  = ABT;
                cpsr_nxt[`CPSR_MODE]  = ABT;
 
 
                `ifndef SYNTHESIS
                // assertions_start
                        dabt_ack = 1'd1;
                        dabt_ack = 1'd1;
                `endif
                // assertions_end
 
 
        end
        end
        else if ( i_fiq )
        else if ( i_fiq )
        begin
        begin
 
                $display($time, " - %m :: FIQ detected.");
 
 
                // Returns do LR - 4 to get back to the same instruction.
                // Returns do LR - 4 to get back to the same instruction.
                pc_shelve ( FIQ_VECTOR );
                pc_shelve ( FIQ_VECTOR );
 
 
                wen    = 1;
                wen    = 1;
                wdata1 = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
                wdata1 = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
                wa1    = PHY_FIQ_R14;
                wa1    = PHY_FIQ_R14;
                wa2    = PHY_FIQ_SPSR;
                wa2    = PHY_FIQ_SPSR;
                wdata2 = cpsr_ff;
                wdata2 = cpsr_ff;
                cpsr_nxt[`CPSR_MODE]  = FIQ;
                cpsr_nxt[`CPSR_MODE]  = FIQ;
                cpsr_nxt[F] = 1'd1;
                cpsr_nxt[F] = 1'd1;
 
 
                `ifndef SYNTHESIS
                // assertions_start
                        fiq_ack = 1'd1;
                        fiq_ack = 1'd1;
                `endif
                // assertions_end
        end
        end
        else if ( i_irq )
        else if ( i_irq )
        begin
        begin
 
                $display($time, " - %m :: IRQ detected.");
 
 
                pc_shelve (IRQ_VECTOR);
                pc_shelve (IRQ_VECTOR);
 
 
                wen    = 1;
                wen    = 1;
                wdata1 = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
                wdata1 = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
 
 
                `ifndef SYNTHESIS
 
                irq_addr = wdata1;
 
                `endif
 
 
 
                wa1    = PHY_IRQ_R14;
                wa1    = PHY_IRQ_R14;
                wa2    = PHY_IRQ_SPSR;
                wa2    = PHY_IRQ_SPSR;
                wdata2 = cpsr_ff;
                wdata2 = cpsr_ff;
                cpsr_nxt[`CPSR_MODE]  = IRQ;
                cpsr_nxt[`CPSR_MODE]  = IRQ;
                // Returns do LR - 4 to get back to the same instruction.
                // Returns do LR - 4 to get back to the same instruction.
 
 
                `ifndef SYNTHESIS
                // assertions_start
 
                        irq_addr = wdata1;
                irq_ack = 1'd1;
                irq_ack = 1'd1;
                `endif
                // assertions_end
        end
        end
        else if ( i_instr_abt )
        else if ( i_instr_abt )
        begin
        begin
                // Returns do LR - 4 to get back to the same instruction.
                // Returns do LR - 4 to get back to the same instruction.
                pc_shelve (PABT_VECTOR);
                pc_shelve (PABT_VECTOR);
 
 
                wen    = 1;
                wen    = 1;
                wdata1 = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
                wdata1 = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
                wa1    = PHY_ABT_R14;
                wa1    = PHY_ABT_R14;
                wa2    = PHY_ABT_SPSR;
                wa2    = PHY_ABT_SPSR;
                wdata2 = cpsr_ff;
                wdata2 = cpsr_ff;
                cpsr_nxt[`CPSR_MODE]  = ABT;
                cpsr_nxt[`CPSR_MODE]  = ABT;
 
 
                `ifndef SYNTHESIS
                // assertions_start
                        iabt_ack = 1'd1;
                        iabt_ack = 1'd1;
                `endif
                // assertions_end
        end
        end
        else if ( i_swi )
        else if ( i_swi )
        begin
        begin
                // Returns do LR to return to the next instruction.
                // Returns do LR to return to the next instruction.
                pc_shelve(SWI_VECTOR);
                pc_shelve(SWI_VECTOR);
 
 
                wen    = 1;
                wen    = 1;
                wdata1 = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
                wdata1 = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
                wa1    = PHY_SVC_R14;
                wa1    = PHY_SVC_R14;
                wa2    = PHY_SVC_SPSR;
                wa2    = PHY_SVC_SPSR;
                wdata2 = cpsr_ff;
                wdata2 = cpsr_ff;
                cpsr_nxt[`CPSR_MODE]  = SVC;
                cpsr_nxt[`CPSR_MODE]  = SVC;
 
 
                `ifndef SYNTHESIS
                // assertions_start
                        swi_ack = 1'd1;
                        swi_ack = 1'd1;
                `endif
                // assertions_end
        end
        end
        else if ( i_und )
        else if ( i_und )
        begin
        begin
                // Returns do LR to return to the next instruction.
                // Returns do LR to return to the next instruction.
                pc_shelve(UND_VECTOR);
                pc_shelve(UND_VECTOR);
 
 
                wen    = 1;
                wen    = 1;
                wdata1 = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
                wdata1 = `ARM_MODE ? i_wr_data : i_pc_buf_ff ;
                wa1    = PHY_UND_R14;
                wa1    = PHY_UND_R14;
                wa2    = PHY_UND_SPSR;
                wa2    = PHY_UND_SPSR;
                wdata2 = cpsr_ff;
                wdata2 = cpsr_ff;
                cpsr_nxt[`CPSR_MODE]  = UND;
                cpsr_nxt[`CPSR_MODE]  = UND;
 
 
                `ifndef SYNTHESIS
                // assertions_start
                        und_ack = 1'd1;
                        und_ack = 1'd1;
                `endif
                // assertions_end
        end
        end
        else if ( i_copro_reg_en )
        else if ( i_copro_reg_en )
        begin
        begin
               // Write to register.
               // Write to register (Coprocessor command).
               wen      = 1;
               wen      = 1;
               wa1      = i_copro_reg_wr_index;
               wa1      = i_copro_reg_wr_index;
               wdata1   = i_copro_reg_wr_data;
               wdata1   = i_copro_reg_wr_data;
        end
        end
        else if ( i_valid )
        else if ( i_valid ) // If valid,
        begin
        begin
                // Only then execute the instruction at hand...
                // Only then execute the instruction at hand...
                cpsr_nxt                =   i_flags;
                cpsr_nxt                =   i_flags;
 
 
                // Dual write port.
                // Dual write port.
Line 434... Line 407...
                wdata2 = i_wr_data_1;
                wdata2 = i_wr_data_1;
 
 
                // Load to PC will trigger from writeback.
                // Load to PC will trigger from writeback.
                if ( i_mem_load_ff && i_wr_index_1 == ARCH_PC)
                if ( i_mem_load_ff && i_wr_index_1 == ARCH_PC)
                begin
                begin
 
                        $display($time, " - %m :: Detected load to PC. Trigger a writeback.");
 
 
                        pc_shelve (i_wr_data_1);
                        pc_shelve (i_wr_data_1);
                        o_clear_from_writeback  = 1'd1;
                        o_clear_from_writeback  = 1'd1;
                end
                end
        end
        end
 
 
 
        // Ensure lower 2 bits of PC are always tied to VSS.
        pc_nxt = pc_nxt & 32'hffff_fffe;
        pc_nxt = pc_nxt & 32'hffff_fffe;
end
end
 
 
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------
 
// Sequential Logic
 
// ----------------------------------------------
 
 
always @ (posedge i_clk)
always @ (posedge i_clk)
begin
begin
        if ( i_reset )
        if ( i_reset )
        begin
        begin
Line 464... Line 442...
                shelve_ff    <= shelve_nxt;
                shelve_ff    <= shelve_nxt;
                pc_shelve_ff <= pc_shelve_nxt;
                pc_shelve_ff <= pc_shelve_nxt;
                pc_ff        <= pc_nxt;
                pc_ff        <= pc_nxt;
                cpsr_ff      <= cpsr_nxt;
                cpsr_ff      <= cpsr_nxt;
                o_decompile  <= i_decompile;
                o_decompile  <= i_decompile;
 
                o_copro_reg_rd_data_ff    <= o_rd_data_0;
        end
        end
end
end
 
 
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------
 
// Tasks
 
// ----------------------------------------------
 
 
task pc_shelve (input [31:0] new_pc);
task pc_shelve (input [31:0] new_pc);
begin
begin
        if (!i_code_stall )
        if (!i_code_stall )
        begin
        begin
Line 485... Line 466...
                pc_nxt = pc_ff;
                pc_nxt = pc_ff;
        end
        end
end
end
endtask
endtask
 
 
`ifndef SYNTHESIS
// assertions_start 
 
 
always @*
        always @ (*)
if ( cpsr_nxt[`CPSR_MODE] != USR && cpsr_ff[`CPSR_MODE] == USR )
if ( cpsr_nxt[`CPSR_MODE] != USR && cpsr_ff[`CPSR_MODE] == USR )
begin
begin
        if (
        if (
                i_data_abt      ||
                i_data_abt      ||
                i_fiq           ||
                i_fiq           ||
Line 508... Line 489...
                $display($time, "Error : %m CPU is changing out of USR mode without an exception...");
                $display($time, "Error : %m CPU is changing out of USR mode without an exception...");
                $stop;
                $stop;
        end
        end
end
end
 
 
`endif
// assertions_end
 
 
endmodule // zap_register_file.v
endmodule // zap_register_file.v
`default_nettype wire
`default_nettype wire
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

© copyright 1999-2022 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.