Line 53... |
Line 53... |
reg push;
|
reg push;
|
reg pop;
|
reg pop;
|
always @(posedge clk) begin
|
always @(posedge clk) begin
|
if(rst) begin
|
if(rst) begin
|
io_sp <= 8'd0;
|
io_sp <= 8'd0;
|
|
`ifndef REGRESS
|
SP <= 16'd0;
|
SP <= 16'd0;
|
|
`endif
|
end else begin
|
end else begin
|
io_sp <= io_a[0] ? SP[7:0] : SP[15:8];
|
io_sp <= io_a[0] ? SP[7:0] : SP[15:8];
|
if((io_a == 6'b111101) | (io_a == 6'b111110)) begin
|
if((io_a == 6'b111101) | (io_a == 6'b111110)) begin
|
if(io_we) begin
|
if(io_we) begin
|
if(io_a[0])
|
if(io_a[0])
|
Line 94... |
Line 96... |
end
|
end
|
|
|
/* Register operations */
|
/* Register operations */
|
wire immediate = (pmem_d[14]
|
wire immediate = (pmem_d[14]
|
| (pmem_d[15:12] == 4'b0011)) /* CPI */
|
| (pmem_d[15:12] == 4'b0011)) /* CPI */
|
& (pmem_d[15:10] != 6'b111111); /* SBRC - SBRS */
|
& (pmem_d[15:10] != 6'b111111) /* SBRC - SBRS */
|
|
& (pmem_d[15:10] != 6'b111110); /* BST - BLD */
|
reg lpm_en;
|
reg lpm_en;
|
wire [4:0] Rd = lpm_en ? 5'd0 : {immediate | pmem_d[8], pmem_d[7:4]};
|
wire [4:0] Rd = lpm_en ? 5'd0 : {immediate | pmem_d[8], pmem_d[7:4]};
|
wire [4:0] Rr = {pmem_d[9], pmem_d[3:0]};
|
wire [4:0] Rr = {pmem_d[9], pmem_d[3:0]};
|
wire [7:0] K = {pmem_d[11:8], pmem_d[3:0]};
|
wire [7:0] K = {pmem_d[11:8], pmem_d[3:0]};
|
wire [2:0] b = pmem_d[2:0];
|
wire [2:0] b = pmem_d[2:0];
|
Line 170... |
Line 173... |
parameter PC_SEL_KL = 4'd2;
|
parameter PC_SEL_KL = 4'd2;
|
parameter PC_SEL_KS = 4'd3;
|
parameter PC_SEL_KS = 4'd3;
|
parameter PC_SEL_DMEML = 4'd4;
|
parameter PC_SEL_DMEML = 4'd4;
|
parameter PC_SEL_DMEMH = 4'd6;
|
parameter PC_SEL_DMEMH = 4'd6;
|
parameter PC_SEL_DEC = 4'd7;
|
parameter PC_SEL_DEC = 4'd7;
|
parameter PC_SEL_Z = 4'd7;
|
parameter PC_SEL_Z = 4'd8;
|
|
|
always @(posedge clk) begin
|
always @(posedge clk) begin
|
if(rst) begin
|
if(rst) begin
|
|
`ifndef REGRESS
|
PC <= 0;
|
PC <= 0;
|
|
`endif
|
end else begin
|
end else begin
|
case(pc_sel)
|
case(pc_sel)
|
PC_SEL_NOP:;
|
PC_SEL_NOP:;
|
PC_SEL_INC: PC <= PC + 1;
|
PC_SEL_INC: PC <= PC + 1;
|
// !!! WARNING !!! replace with PC <= PC + {{pmem_width-12{Kl[11]}}, Kl}; if pmem_width>12
|
// !!! WARNING !!! replace with PC <= PC + {{pmem_width-12{Kl[11]}}, Kl}; if pmem_width>12
|
Line 190... |
Line 195... |
PC_SEL_Z: PC <= pZ - 1;
|
PC_SEL_Z: PC <= pZ - 1;
|
endcase
|
endcase
|
end
|
end
|
end
|
end
|
reg pmem_selz;
|
reg pmem_selz;
|
assign pmem_a = rst ? 0 : (pmem_selz ? pZ[15:1] : PC + 1);
|
assign pmem_a = rst ?
|
|
`ifdef REGRESS
|
|
PC
|
|
`else
|
|
0
|
|
`endif
|
|
: (pmem_selz ? pZ[15:1] : PC + 1);
|
|
|
/* Load/store operations */
|
/* Load/store operations */
|
reg [3:0] dmem_sel;
|
reg [3:0] dmem_sel;
|
|
|
parameter DMEM_SEL_UNDEFINED = 3'bxxx;
|
parameter DMEM_SEL_UNDEFINED = 3'bxxx;
|
Line 223... |
Line 234... |
integer i_rst_regf;
|
integer i_rst_regf;
|
// synthesis translate_on
|
// synthesis translate_on
|
reg [7:0] R;
|
reg [7:0] R;
|
reg writeback;
|
reg writeback;
|
reg update_nsz;
|
reg update_nsz;
|
|
reg change_z;
|
reg [15:0] R16;
|
reg [15:0] R16;
|
reg mode16;
|
reg mode16;
|
always @(posedge clk) begin
|
always @(posedge clk) begin
|
R = 8'hxx;
|
R = 8'hxx;
|
writeback = 1'b0;
|
writeback = 1'b0;
|
update_nsz = 1'b0;
|
update_nsz = 1'b0;
|
|
change_z = 1'b1;
|
R16 = 16'hxxxx;
|
R16 = 16'hxxxx;
|
mode16 = 1'b0;
|
mode16 = 1'b0;
|
if(rst) begin
|
if(rst) begin
|
|
`ifndef REGRESS
|
/*
|
/*
|
* Not resetting the register file enables the use of more efficient
|
* Not resetting the register file enables the use of more efficient
|
* distributed block RAM.
|
* distributed block RAM.
|
*/
|
*/
|
// synthesis translate_off
|
// synthesis translate_off
|
Line 251... |
Line 265... |
S = 1'b0;
|
S = 1'b0;
|
V = 1'b0;
|
V = 1'b0;
|
N = 1'b0;
|
N = 1'b0;
|
Z = 1'b0;
|
Z = 1'b0;
|
C = 1'b0;
|
C = 1'b0;
|
|
`endif
|
end else begin
|
end else begin
|
if(normal_en) begin
|
if(normal_en) begin
|
writeback = 1'b1;
|
writeback = 1'b1;
|
update_nsz = 1'b1;
|
update_nsz = 1'b1;
|
casex(pmem_d)
|
casex(pmem_d)
|
Line 268... |
Line 283... |
16'b000x_01xx_xxxx_xxxx: /* compare */ begin
|
16'b000x_01xx_xxxx_xxxx: /* compare */ begin
|
/* SUB - SBC / CP - CPC */
|
/* SUB - SBC / CP - CPC */
|
{C, R} = GPR_Rd - GPR_Rr - (~pmem_d[12] & C);
|
{C, R} = GPR_Rd - GPR_Rr - (~pmem_d[12] & C);
|
H = (~GPR_Rd[3] & GPR_Rr[3])|(GPR_Rr[3] & R[3])|(R[3] & ~GPR_Rd[3]);
|
H = (~GPR_Rd[3] & GPR_Rr[3])|(GPR_Rr[3] & R[3])|(R[3] & ~GPR_Rd[3]);
|
V = (GPR_Rd[7] & ~GPR_Rr[7] & ~R[7])|(~GPR_Rd[7] & GPR_Rr[7] & R[7]);
|
V = (GPR_Rd[7] & ~GPR_Rr[7] & ~R[7])|(~GPR_Rd[7] & GPR_Rr[7] & R[7]);
|
|
if(~pmem_d[12])
|
|
change_z = 1'b0;
|
writeback = pmem_d[11];
|
writeback = pmem_d[11];
|
end
|
end
|
16'b010x_xxxx_xxxx_xxxx, /* subtract */
|
16'b010x_xxxx_xxxx_xxxx, /* subtract */
|
16'b0011_xxxx_xxxx_xxxx: /* compare */ begin
|
16'b0011_xxxx_xxxx_xxxx: /* compare */ begin
|
/* SUBI - SBCI / CPI */
|
/* SUBI - SBCI / CPI */
|
{C, R} = GPR_Rd - K - (~pmem_d[12] & C);
|
{C, R} = GPR_Rd - K - (~pmem_d[12] & C);
|
H = (~GPR_Rd[3] & K[3])|(K[3] & R[3])|(R[3] & ~GPR_Rd[3]);
|
H = (~GPR_Rd[3] & K[3])|(K[3] & R[3])|(R[3] & ~GPR_Rd[3]);
|
V = (GPR_Rd[7] & ~K[7] & ~R[7])|(~GPR_Rd[7] & K[7] & R[7]);
|
V = (GPR_Rd[7] & ~K[7] & ~R[7])|(~GPR_Rd[7] & K[7] & R[7]);
|
|
if(~pmem_d[12])
|
|
change_z = 1'b0;
|
writeback = pmem_d[14];
|
writeback = pmem_d[14];
|
end
|
end
|
16'b0010_00xx_xxxx_xxxx: begin
|
16'b0010_00xx_xxxx_xxxx: begin
|
/* AND */
|
/* AND */
|
R = GPR_Rd & GPR_Rr;
|
R = GPR_Rd & GPR_Rr;
|
Line 390... |
Line 409... |
R = K;
|
R = K;
|
update_nsz = 1'b0;
|
update_nsz = 1'b0;
|
end
|
end
|
/* LSL is replaced with ADD */
|
/* LSL is replaced with ADD */
|
/* ROL is replaced with ADC */
|
/* ROL is replaced with ADC */
|
16'b1111_10xx_xxxx_xxxx: begin
|
16'b1111_10xx_xxxx_0xxx: begin
|
if(pmem_d[9]) begin
|
if(pmem_d[9]) begin
|
/* BST */
|
/* BST */
|
T = GPR_Rd_b;
|
T = GPR_Rd_b;
|
writeback = 1'b0;
|
writeback = 1'b0;
|
end else begin
|
end else begin
|
Line 457... |
Line 476... |
writeback = 1'b1;
|
writeback = 1'b1;
|
end
|
end
|
if(update_nsz) begin
|
if(update_nsz) begin
|
N = mode16 ? R16[15] : R[7];
|
N = mode16 ? R16[15] : R[7];
|
S = N ^ V;
|
S = N ^ V;
|
Z = mode16 ? R16 == 16'h0000 : R == 8'h00;
|
Z = mode16 ? R16 == 16'h0000 : ((R == 8'h00) & (change_z|Z));
|
end
|
end
|
if(io_we & (io_a == 6'b111111))
|
if(io_we & (io_a == 6'b111111))
|
{T, H, S, V, N, Z, C} = io_do[6:0];
|
{T, H, S, V, N, Z, C} = io_do[6:0];
|
if(writeback) begin
|
if(writeback) begin
|
if(mode16) begin
|
if(mode16) begin
|
Line 499... |
Line 518... |
DMEM_SEL_ZPLUS: pZ = pZ + 16'd1;
|
DMEM_SEL_ZPLUS: pZ = pZ + 16'd1;
|
DMEM_SEL_ZMINUS: pZ = pZ - 16'd1;
|
DMEM_SEL_ZMINUS: pZ = pZ - 16'd1;
|
default:;
|
default:;
|
endcase
|
endcase
|
end
|
end
|
end /* if(sys_rst) ... else */
|
end /* if(rst) ... else */
|
end
|
end
|
|
|
/* I/O port */
|
/* I/O port */
|
assign io_a = {pmem_d[10:9], pmem_d[3:0]};
|
assign io_a = {pmem_d[10:9], pmem_d[3:0]};
|
assign io_do = GPR_Rd;
|
assign io_do = GPR_Rd;
|
Line 530... |
Line 549... |
|
|
wire [pmem_width-1:0] PC_inc = PC + 1;
|
wire [pmem_width-1:0] PC_inc = PC + 1;
|
always @(*) begin
|
always @(*) begin
|
case(dmem_sel)
|
case(dmem_sel)
|
DMEM_SEL_X,
|
DMEM_SEL_X,
|
|
DMEM_SEL_XPLUS,
|
DMEM_SEL_XMINUS,
|
DMEM_SEL_XMINUS,
|
|
DMEM_SEL_YPLUS,
|
DMEM_SEL_YMINUS,
|
DMEM_SEL_YMINUS,
|
DMEM_SEL_YQ,
|
DMEM_SEL_YQ,
|
|
DMEM_SEL_ZPLUS,
|
DMEM_SEL_ZMINUS,
|
DMEM_SEL_ZMINUS,
|
DMEM_SEL_ZQ,
|
DMEM_SEL_ZQ,
|
DMEM_SEL_SP_R: dmem_do = GPR_Rd;
|
DMEM_SEL_SP_R: dmem_do = GPR_Rd;
|
DMEM_SEL_SP_PCL: dmem_do = PC_inc[7:0];
|
DMEM_SEL_SP_PCL: dmem_do = PC_inc[7:0];
|
DMEM_SEL_SP_PCH: dmem_do = PC_inc[pmem_width-1:8];
|
DMEM_SEL_SP_PCH: dmem_do = PC_inc[pmem_width-1:8];
|
Line 631... |
Line 653... |
pc_sel = PC_SEL_INC;
|
pc_sel = PC_SEL_INC;
|
pmem_ce = 1'b1;
|
pmem_ce = 1'b1;
|
if(reg_equal)
|
if(reg_equal)
|
next_state = SKIP;
|
next_state = SKIP;
|
end
|
end
|
16'b1111_11xx_xxxx_xxxx: begin
|
16'b1111_11xx_xxxx_0xxx: begin
|
/* SBRC - SBRS */
|
/* SBRC - SBRS */
|
pc_sel = PC_SEL_INC;
|
pc_sel = PC_SEL_INC;
|
pmem_ce = 1'b1;
|
pmem_ce = 1'b1;
|
if(GPR_Rd_b == pmem_d[9])
|
if(GPR_Rd_b == pmem_d[9])
|
next_state = SKIP;
|
next_state = SKIP;
|
Line 801... |
Line 823... |
next_state = LDS2;
|
next_state = LDS2;
|
end
|
end
|
LDS2: begin
|
LDS2: begin
|
pc_sel = PC_SEL_INC;
|
pc_sel = PC_SEL_INC;
|
pmem_ce = 1'b1;
|
pmem_ce = 1'b1;
|
normal_en = 1'b1;
|
|
lds_writeback = 1'b1;
|
lds_writeback = 1'b1;
|
next_state = NORMAL;
|
next_state = NORMAL;
|
end
|
end
|
SKIP: begin
|
SKIP: begin
|
pc_sel = PC_SEL_INC;
|
pc_sel = PC_SEL_INC;
|
Line 828... |
Line 849... |
next_state = NORMAL;
|
next_state = NORMAL;
|
end
|
end
|
endcase
|
endcase
|
end
|
end
|
|
|
|
`ifdef REGRESS
|
|
integer i;
|
|
integer cycles;
|
|
always @(posedge clk) begin
|
|
if(~rst & (state == NORMAL) & (cycles != 0)) begin
|
|
$display("DUMP REGISTERS");
|
|
for(i=0;i<24;i=i+1)
|
|
$display("%x", GPR[i]);
|
|
$display("%x", U[7:0]);
|
|
$display("%x", U[15:8]);
|
|
$display("%x", pX[7:0]);
|
|
$display("%x", pX[15:8]);
|
|
$display("%x", pY[7:0]);
|
|
$display("%x", pY[15:8]);
|
|
$display("%x", pZ[7:0]);
|
|
$display("%x", pZ[15:8]);
|
|
$display("%x", {1'b0, T, H, S, V, N, Z, C});
|
|
$display("%x", SP[15:8]);
|
|
$display("%x", SP[7:0]);
|
|
$display("%x", PC[14:7]);
|
|
$display("%x", {PC[6:0], 1'b0});
|
|
tb_regress.dump;
|
|
$finish;
|
|
end
|
|
if(rst)
|
|
cycles = 0;
|
|
else
|
|
cycles = cycles + 1;
|
|
end
|
|
|
|
reg [7:0] SPR[0:12];
|
|
reg I;
|
|
initial begin
|
|
$readmemh("gpr.rom", GPR);
|
|
$readmemh("spr.rom", SPR);
|
|
U = {SPR[1], SPR[0]};
|
|
pX = {SPR[3], SPR[2]};
|
|
pY = {SPR[5], SPR[4]};
|
|
pZ = {SPR[7], SPR[6]};
|
|
{I, T, H, S, V, N, Z, C} = SPR[8];
|
|
SP = {SPR[9], SPR[10]};
|
|
PC = {SPR[11], SPR[12]}/2;
|
|
end
|
|
`endif
|
|
|
endmodule
|
endmodule
|
|
|
No newline at end of file
|
No newline at end of file
|