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

Subversion Repositories rtf65002

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /rtf65002
    from Rev 11 to Rev 12
    Reverse comparison

Rev 11 → Rev 12

/trunk/rtl/verilog/mult_div.v
0,0 → 1,172
// ============================================================================
// __
// \\__/ o\ (C) 2013 Robert Finch, Stratford
// \ __ / All rights reserved.
// \/_// robfinch<remove>@opencores.org
// ||
//
// rtf65002.v
// - 32 bit CPU multiplier/divider
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// ============================================================================
//
`define MUL 4'd8
`define MULS 4'd9
`define DIV 4'd10
`define DIVS 4'd11
`define MOD 4'd12
`define MODS 4'd13
 
module mult_div(rst, clk, ld, op, a, b, p, q, r, done);
parameter IDLE=3'd0;
parameter MULT=3'd1;
parameter FIX_SIGN=3'd2;
parameter DIV=3'd3;
input rst;
input clk;
input ld;
input [3:0] op;
input [31:0] a;
input [31:0] b;
output reg [63:0] p;
output reg [31:0] q;
output reg [31:0] r;
output done;
 
reg [31:0] aa, bb;
reg res_sgn;
 
reg [2:0] state;
 
assign done = state==IDLE;
wire [31:0] diff = r - bb;
wire [31:0] pa = a[31] ? -a : a;
reg [5:0] cnt;
 
always @(posedge clk)
if (rst)
state <= IDLE;
else begin
case(state)
IDLE:
if (ld) begin
cnt <= 6'd32;
case(op)
`MUL:
begin
aa <= a;
bb <= b;
res_sgn <= 1'b0;
state <= MULT;
end
`MULS:
begin
aa <= a[31] ? -a : a;
bb <= b[31] ? -b : b;
res_sgn <= a[31] ^ b[31];
state <= MULT;
end
`DIV,`MOD:
begin
aa <= a;
bb <= b;
q <= a[30:0];
r <= a[31];
res_sgn <= 1'b0;
state <= DIV;
end
`DIVS,`MODS:
begin
aa <= a[31] ? -a : a;
bb <= b[31] ? -b : b;
q <= pa[30:0];
r <= pa[31];
res_sgn <= a[31] ^ b[31];
state <= DIV;
end
default:
state <= IDLE;
endcase
end
MULT:
begin
state <= res_sgn ? FIX_SIGN : IDLE;
p <= aa * bb;
end
DIV:
begin
q <= {q[30:0],~diff[31]};
if (cnt==6'd0) begin
state <= res_sgn ? FIX_SIGN : IDLE;
if (diff[31])
r <= r[30:0];
else
r <= diff[30:0];
end
else begin
if (diff[31])
r <= {r[30:0],q[31]};
else
r <= {diff[30:0],q[31]};
end
cnt <= cnt - 6'd1;
end
 
FIX_SIGN:
begin
state <= IDLE;
if (res_sgn) begin
p <= -p;
q <= -q;
r <= -r;
end
end
default: state <= IDLE;
endcase
end
 
endmodule
 
module multdiv_tb();
reg rst;
reg clk;
reg ld;
 
initial begin
#0 clk = 1'b0;
#0 rst = 1'b0;
#10 rst = 1'b1;
#10 rst = 1'b0;
#10 ld = 1'b1;
#20 ld = 1'b0;
end
 
always #10 clk = ~clk;
 
mult_div umd1 (
.rst(rst),
.clk(clk),
.ld(ld),
.op(`DIV),
.a(32'h12345678),
.b(32'd10),
.p(),
.q(),
.r(),
.done()
);
 
endmodule
/trunk/rtl/verilog/rtf65002d.v
76,15 → 76,20
`define DEA 8'h3A
 
`define RR 8'h02
`define ADD_RR 4'h0
`define SUB_RR 4'h1
`define CMP_RR 4'h2
`define AND_RR 4'h3
`define EOR_RR 4'h4
`define OR_RR 4'h5
`define MUL_RR 4'h8
`define ADD_RR 4'd0
`define SUB_RR 4'd1
`define CMP_RR 4'd2
`define AND_RR 4'd3
`define EOR_RR 4'd4
`define OR_RR 4'd5
`define MUL_RR 4'd8
`define MULS_RR 4'd9
`define DIV_RR 4'd10
`define DIVS_RR 4'd11
`define MOD_RR 4'd12
`define MODS_RR 4'd13
`define LD_RR 8'h7B
 
 
`define ADD_IMM8 8'h65 // 8 bit operand
`define ADD_IMM16 8'h79 // 16 bit operand
`define ADD_IMM32 8'h69 // 32 bit operand
259,10 → 264,12
`define ROR_ABS 8'h6E
`define ROR_ABSX 8'h7E
 
`define DEC_RR 8'hC6
`define DEC_ZP 8'hC6
`define DEC_ZPX 8'hD6
`define DEC_ABS 8'hCE
`define DEC_ABSX 8'hDE
`define INC_RR 8'hE6
`define INC_ZP 8'hE6
`define INC_ZPX 8'hF6
`define INC_ABS 8'hEE
600,8 → 607,9
// the sum is the same as B
assign v = (op ^ s ^ b) & (~op ^ a ^ b);
 
endmodule
endmodule
 
 
module rtf65002d(rst_i, clk_i, nmi_i, irq_i, bte_o, cti_o, bl_o, lock_o, cyc_o, stb_o, ack_i, we_o, sel_o, adr_o, dat_i, dat_o);
parameter IDLE = 3'd0;
parameter LOAD_DCACHE = 3'd1;
708,6 → 716,8
parameter BYTE_PLA2 = 7'd98;
parameter WAIT_DHIT = 7'd99;
parameter RESET2 = 7'd100;
parameter MULDIV1 = 7'd101;
parameter MULDIV2 = 7'd102;
 
input rst_i;
input clk_i;
749,7 → 759,9
wire [7:0] x8 = x[7:0];
wire [7:0] y8 = y[7:0];
reg [31:0] isp; // interrupt stack pointer
reg [63:0] prod;
wire [63:0] prod;
wire [31:0] q,r;
reg [31:0] tick;
wire [7:0] sp_dec = sp - 8'd1;
wire [7:0] sp_inc = sp + 8'd1;
wire [31:0] isp_dec = isp - 32'd1;
787,6 → 799,9
reg [3:0] Rt;
reg [33:0] ea;
reg first_ifetch;
reg [31:0] lfsr;
wire lfsr_fb;
xnor(lfsr_fb,lfsr[0],lfsr[1],lfsr[21],lfsr[31]);
reg [31:0] a, b;
reg [7:0] b8;
reg [32:0] res;
851,8 → 866,26
wire isOrb = ir[7:0]==`ORB_ZPX || ir[7:0]==`ORB_IX || ir[7:0]==`ORB_IY || ir[7:0]==`ORB_ABS || ir[7:0]==`ORB_ABSX;
wire isStb = ir[7:0]==`STB_ZPX || ir[7:0]==`STB_ABS || ir[7:0]==`STB_ABSX;
 
wire ld_muldiv = state==DECODE && ir[7:0]==`RR;
wire md_done;
wire clk;
 
mult_div umd1
(
.rst(rst),
.clk(clk),
.ld(ld_muldiv),
.op(ir[23:20]),
.a(rfoa),
.b(rfob),
.p(prod),
.q(q),
.r(r),
.done(md_done)
);
 
icachemem icm0 (
.wclk(clk_i),
.wclk(clk),
.wr(ack_i & isInsnCacheLoad),
.adr(adr_o),
.dat(dat_i),
862,7 → 895,7
);
 
tagmem tgm0 (
.wclk(clk_i),
.wclk(clk),
.wr((ack_i & isInsnCacheLoad)|isCacheReset),
.adr({adr_o[31:1],!isCacheReset}),
.rclk(~clk_i),
874,7 → 907,7
wire ihit = (hit0 & hit1);//(pc[2:0] > 3'd1 ? hit1 : 1'b1));
 
dcachemem dcm0 (
.wclk(clk_i),
.wclk(clk),
.wr(wr | (ack_i & isDataCacheLoad)),
.sel(wr ? wrsel : sel_o),
.wadr(wr ? wadr : adr_o[33:2]),
885,7 → 918,7
);
 
dtagmem dtm0 (
.wclk(clk_i),
.wclk(clk),
.wr(wr | (ack_i & isDataCacheLoad)),
.wadr(wr ? wadr : adr_o[33:2]),
.rclk(~clk_i),
974,7 → 1007,6
//
reg cpu_clk_en;
reg clk_en;
wire clk;
BUFGCE u20 (.CE(cpu_clk_en), .I(clk_i), .O(clk) );
 
always @(posedge clk_i)
1023,8 → 1055,10
clk_en <= 1'b1;
isCacheReset <= `TRUE;
gie <= 1'b0;
tick <= 32'd0;
end
else begin
tick <= tick + 32'd1;
wr <= 1'b0;
if (nmi_i & !nmi1)
nmi_edge <= 1'b1;
1259,6 → 1293,7
write_allocate <= res[2];
end
4'h1: dp <= res;
4'h5: lfsr <= res;
4'hE: begin sp <= res[7:0]; end
4'hF: begin isp <= res; gie <= 1'b1; end
endcase
1279,7 → 1314,14
`OR_RR: begin nf <= resn32; zf <= resz32; end
`EOR_RR: begin nf <= resn32; zf <= resz32; end
`MUL_RR: begin nf <= resn32; zf <= resz32; end
`MULS_RR: begin nf <= resn32; zf <= resz32; end
`DIV_RR: begin nf <= resn32; zf <= resz32; end
`DIVS_RR: begin nf <= resn32; zf <= resz32; end
`MOD_RR: begin nf <= resn32; zf <= resz32; end
`MODS_RR: begin nf <= resn32; zf <= resz32; end
endcase
`LD_RR: begin zf <= resz32; nf <= resn32; end
`DEC_RR,`INC_RR: begin zf <= resz32; nf <= resn32; end
`ASL_RR,`ROL_RR,`LSR_RR,`ROR_RR: begin cf <= resc32; nf <= resn32; zf <= resz32; end
`ADD_IMM8,`ADD_IMM16,`ADD_IMM32,`ADD_ZPX,`ADD_IX,`ADD_IY,`ADD_ABS,`ADD_ABSX,`ADD_RIND:
begin vf <= resv32; cf <= resc32; nf <= resn32; zf <= resz32; end
1907,6 → 1949,8
4'h1: res <= dp;
4'h2: res <= prod[31:0];
4'h3: res <= prod[63:32];
4'h4: res <= tick;
4'h5: begin res <= lfsr; lfsr <= {lfsr[30:0],lfsr_fb}; end
4'hE: res <= sp;
4'hF: res <= isp;
endcase
1919,6 → 1963,7
 
`RR:
begin
state <= IFETCH;
case(ir[23:20])
`ADD_RR: res <= rfoa + rfob;
`SUB_RR: res <= rfoa - rfob;
1925,17 → 1970,23
`AND_RR: res <= rfoa & rfob;
`OR_RR: res <= rfoa | rfob;
`EOR_RR: res <= rfoa ^ rfob;
`MUL_RR: begin res <= rfoa * rfob; prod <= rfoa * rfob; end
`MUL_RR: begin state <= MULDIV1; end
`MULS_RR: begin state <= MULDIV1; end
`DIV_RR: begin state <= MULDIV1; end
`DIVS_RR: begin state <= MULDIV1; end
`MOD_RR: begin state <= MULDIV1; end
`MODS_RR: begin state <= MULDIV1; end
endcase
Rt <= ir[19:16];
pc <= pc + 32'd3;
state <= IFETCH;
end
`LD_RR: begin res <= rfoa; Rt <= ir[15:12]; pc <= pc + 32'd2; end
`ASL_RR: begin res <= {rfoa,1'b0}; pc <= pc + 32'd2; Rt <= ir[15:12]; end
`ROL_RR: begin res <= {rfoa,cf}; pc <= pc + 32'd2; Rt <= ir[15:12]; end
`LSR_RR: begin res <= {rfoa[0],1'b0,rfoa[31:1]}; pc <= pc + 32'd2; Rt <= ir[15:12]; end
`ROR_RR: begin res <= {rfoa[0],cf,rfoa[31:1]}; pc <= pc + 32'd2; Rt <= ir[15:12]; end
`DEC_RR: begin res <= rfoa - 32'd1; pc <= pc + 32'd2; Rt <= ir[15:12]; end
`INC_RR: begin res <= rfoa + 32'd1; pc <= pc + 32'd2; Rt <= ir[15:12]; end
 
`ADD_IMM8: begin res <= rfoa + {{24{ir[23]}},ir[23:16]}; Rt <= ir[15:12]; pc <= pc + 32'd3; end
`SUB_IMM8: begin res <= rfoa - {{24{ir[23]}},ir[23:16]}; Rt <= ir[15:12]; pc <= pc + 32'd3; end
2908,6 → 2959,21
pc <= dat_i;
state <= IFETCH;
end
MULDIV1:
state <= MULDIV2;
MULDIV2:
if (md_done) begin
state <= IFETCH;
case(ir[23:20])
`MUL_RR: begin res <= prod[31:0]; end
`MULS_RR: begin res <= prod[31:0]; end
`DIV_RR: begin res <= q; end
`DIVS_RR: begin res <= q; end
`MOD_RR: begin res <= r; end
`MODS_RR: begin res <= r; end
endcase
end
 
endcase
 
`include "cache_controller.v"

powered by: WebSVN 2.1.0

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