Not to disturb the flow here, but attached is a draft I made based on
your previous skeleton.

One thing I noticed when writing this is the constraint posed by the
convention of registering output.  For instance, the output of the
memory stage should be a mux between a direct forward of the ALU stage
and the fetched word.  However, the output from the memory module is
already registered, so if I understand this right, we can't do the mux
within the module itself.  My solution was to rip out such cases from
stage 2 and 4 and do the combinatorics in the top-level module.

Comparing to your new fetch stage, I see a have not made the PC
available as a return address.  An alternative to yours would be to make
it readable as a register so that it would be copied before the jump;
you probably though of that, and I guess it depends whether we need more
than one level of calls.
// Instruction Format
//
`define QMODE_BITS      31:30
`define QOP_BITS        29:26
`define QIMM_BIT        25
`define IZ_BITS         25:21
`define IX_BITS         20:16
`define IY_BITS         15:11
`define IMM_BITS        15:0
`define IMM_SIGN_BIT    15

// Instruction Format: Major Operating Mode
//
`define QMODE_ARITH     0
`define QMODE_FETCH     1
`define QMODE_STORE     2
`define QMODE_BRANCH    3

// Instruction Format: Branch Condition
//
// These overlaps with QOP_BITS which is OK since ALU is not used when
// branching.
//
`define BNOT_BIT        29    // negates branch condition
`define BZERO_BIT       28    // branch if zero (can combine with BNEG_BIT)
`define BNEG_BIT        27    // branch if negative
//
// The branch conditions can be expanded to:
//
//   3'b000 noop                        3'b100 branch always (jump)
//   3'b001 branch if negative          3'b101 branch if non-negative
//   3'b010 branch if zero              3'b110 branch if non-zero
//   3'b011 branch if non-positive      3'b111 branch if positive


// The Top-Level CPU Module
//
module ogmisc(clock, reset, do_upload, upload_addr, upload_data);
    input clock;
    input reset;

    input do_upload;
    input[8:0] upload_addr;
    input[31:0] upload_data;

wire[31:0] s1_insn, s2_insn, s3_insn;
wire[31:0] s2_x;
wire[31:0] s2_y_if_reg, s2_y_if_imm, s2_y, s3_y;
wire[4:0] s4_iz;
wire[31:0] s3_z, s4_z, s4_z_if_fetch, s4_z_if_not_fetch;
wire s4_is_fetch;

ogmisc_stg1_fetch stg1(
    clock, reset,
    do_upload, upload_addr, upload_data,
    s1_insn,
    s2_insn[`BNOT_BIT], s2_insn[`BZERO_BIT], s2_insn[`BNEG_BIT], s2_x, s2_y);

ogmisc_stg2_regio stg2(
    clock, reset, clock_2x, phase,
    s1_insn,
    s2_insn, s2_x, s2_y_if_reg,
    s4_iz, s4_z);

assign s2_y_if_imm = {{16{s2_insn[`IMM_SIGN_BIT]}}, s2_insn[`IMM_BITS]};
assign s2_y = s2_insn[`QIMM_BIT]? s2_y_if_imm : s2_y_if_reg;

ogmisc_stg3_alu stg3(
    clock, reset,
    s2_insn, s2_x, s2_y,
    s3_insn, s3_z, s3_y);

ogmisc_stg4_memio stg4(
    clock, reset,
    s3_insn, s3_z, s3_y,
    s4_iz, s4_is_fetch, s4_z_if_fetch, s4_z_if_not_fetch);

assign s4_z = s4_is_fetch? s4_z_if_fetch : s4_z_if_not_fetch;

endmodule


// Stage 1: Instruction Fetch
//
module ogmisc_stg1_fetch(clock, reset, do_upload, upload_addr, upload_data,
                         insn_out,
                         s2_bnot, s2_bzero, s2_bneg, s2_x, s2_y);
    input clock;
    input reset;

    input do_upload;
    input[8:0] upload_addr;
    input[31:0] upload_data;

    output[31:0] insn_out;

    input s2_bnot;
    input s2_bzero;
    input s2_bneg;
    input[31:0] s2_x;
    input[31:0] s2_y;

reg is_branch_insn;
wire is_zero = s2_x == 0;
wire is_neg = s2_x[31];
wire do_branch = is_branch_insn
        && s2_bnot != (is_zero == s2_bzero && is_neg == s2_bneg);

reg [8:0] pc;
wire [8:0] next_pc = do_branch ? s2_y : pc;

always @(posedge clock) begin
    pc <= next_pc + 1;
    is_branch_insn <= insn_out[`QMODE_BITS] == `QMODE_BRANCH;
end

RAMB16_S36_S36 program_memory (
    .CLKA(clock), .SSRA(1'b0),
    .ADDRA(next_pc),
    .ENA(1'b1),         .DOA(insn_out),         .DOPA(),
    .WEA(1'b0),         .DIA(32'b0),            .DIPA(4'b0),

    .CLKB(clock), .SSRB(1'b0),
    .ADDRB(upload_addr),
    .ENB(1'b1),         .DOB(),                 .DOPB(),
    .WEB(do_upload),    .DIB(upload_data),      .DIPB(4'b0));

endmodule


// Stages 2, 5: Register Fetch and Write-Back
//
module ogmisc_stg2_regio(clock, reset, clock_2x, phase,
                         insn,
                         insn_out, x_out, y_out_if_reg,
                         iz, z);
    input clock;
    input reset;
    input clock_2x;
    input phase;

    input[31:0] insn;

    output[31:0] insn_out;
    output[31:0] x_out;
    output[31:0] y_out_if_reg;

    input[4:0] iz;
    input[31:0] z;

reg[31:0] regfile[0:31];
reg[31:0] x_out, y_out_if_reg;

wire[4:0] ix = insn[IX_BITS];
wire[4:0] iy = insn[IY_BITS];

always @(posedge clock_2x) begin
    if (phase == 1)             // falling edge of clock (right?)
        regfile[iz] <= z;       // iz = 0 for no-write
    else begin
        x_out        <= regfile[ix];
        y_out_if_reg <= regfile[iy];
    end
end

endmodule


// Stage 3: ALU
//
module ogmisc_stg3_alu(clock, reset, insn, x, y, insn_out, z_out, y_out);
    input clock;
    input reset;

    input[31:0] insn;
    input[31:0] x;
    input[31:0] y;

    output[31:0] insn_out;
    output[31:0] z_out;
    output[31:0] y_out;

    parameter QOP_AND = 0;
    parameter QOP_NAND = 1;
    parameter QOP_OR = 2;
    parameter QOP_XOR = 3;
    parameter QOP_SL = 4;
    parameter QOP_ADD = 5;
    parameter QOP_SUB = 6;
    parameter QOP_MULT = 7;

reg[31:0] z_out;

always @(posedge clock) begin
    case (insn[`QOP_BITS])
        QOP_AND:  z_out <= x & y;
        QOP_NAND: z_out <= ~(x & y);
        QOP_OR:   z_out <= x | y;
        QOP_XOR:  z_out <= x ^ y;
        QOP_SL:   z_out <= x << y;
        QOP_ADD:  z_out <= x + y; // FIXME. Explicit instatiate ADDSUB
        QOP_SUB:  z_out <= x - y; // ...
        QOP_MULT: z_out <= x * y; // FIXME. Explicit instatiate.
    endcase
end

endmodule


// Stage 4: The Memory Access Stage
//
module ogmisc_stg4_memio(clock, reset, insn, z, y, iz_out,
                         is_fetch, z_out_if_fetch, z_out_if_not_fetch);
    input clock;
    input reset;

    input[31:0] insn;
    input[31:0] z;
    input[31:0] y;

    output[4:0] iz_out;
    output is_fetch;
    output[31:0] z_out_if_fetch;
    output[31:0] z_out_if_not_fetch;

wire is_store = insn[`QMODE_BITS] == `QMODE_STORE;

reg is_fetch;
reg[31:0] z_out_if_not_fetch;

always @(posedge clock) begin
    is_fetch <= insn[`QMODE_BITS] == `QMODE_FETCH;
    z_out_if_not_fetch <= z;
end

RAMB16_S36_S36 local_memory(
    .CLKA(clock), .SSRA(1'b0),
    .ADDRA(z[8:0]),
    .ENA(1'b1),         .DOA(z_out_if_fetch),   .DOPA(),
    .WEA(is_store),     .DIA(y),                .DIPA(4'b0),

    .CLKB(1'b0), .SSRB(1'b0),
    .ADDRB(9'b0),
    .ENB(1'b0),         .DOB(),                 .DOPB(),
    .WEB(1'b0),         .DIB(32'b0),            .DIPB(4'b0));

endmodule
_______________________________________________
Open-graphics mailing list
[email protected]
http://lists.duskglow.com/mailman/listinfo/open-graphics
List service provided by Duskglow Consulting, LLC (www.duskglow.com)

Reply via email to