1855 lines
48 KiB
Verilog
1855 lines
48 KiB
Verilog
`define YES
|
|
`include "revision.v"
|
|
|
|
module lfsre(
|
|
input clk,
|
|
output reg [16:0] lfsr);
|
|
wire d0;
|
|
|
|
xnor(d0,lfsr[16],lfsr[13]);
|
|
|
|
always @(posedge clk) begin
|
|
lfsr <= {lfsr[15:0],d0};
|
|
end
|
|
endmodule
|
|
|
|
module oldram256x1s(
|
|
input d,
|
|
input we,
|
|
input wclk,
|
|
input [7:0] a,
|
|
output o);
|
|
|
|
wire sel0 = (a[7:6] == 0);
|
|
wire o0;
|
|
RAM64X1S r0(.O(o0), .A0(a[0]), .A1(a[1]), .A2(a[2]), .A3(a[3]), .A4(a[4]), .A5(a[5]), .D(d), .WCLK(wclk), .WE(sel0 & we));
|
|
|
|
wire sel1 = (a[7:6] == 1);
|
|
wire o1;
|
|
RAM64X1S r1(.O(o1), .A0(a[0]), .A1(a[1]), .A2(a[2]), .A3(a[3]), .A4(a[4]), .A5(a[5]), .D(d), .WCLK(wclk), .WE(sel1 & we));
|
|
|
|
wire sel2 = (a[7:6] == 2);
|
|
wire o2;
|
|
RAM64X1S r2(.O(o2), .A0(a[0]), .A1(a[1]), .A2(a[2]), .A3(a[3]), .A4(a[4]), .A5(a[5]), .D(d), .WCLK(wclk), .WE(sel2 & we));
|
|
|
|
wire sel3 = (a[7:6] == 3);
|
|
wire o3;
|
|
RAM64X1S r3(.O(o3), .A0(a[0]), .A1(a[1]), .A2(a[2]), .A3(a[3]), .A4(a[4]), .A5(a[5]), .D(d), .WCLK(wclk), .WE(sel3 & we));
|
|
|
|
assign o = (a[7] == 0) ? ((a[6] == 0) ? o0 : o1) : ((a[6] == 0) ? o2 : o3);
|
|
endmodule
|
|
|
|
module ring64(
|
|
input clk,
|
|
input i,
|
|
output o);
|
|
|
|
wire o0, o1, o2;
|
|
SRL16E ring0( .CLK(clk), .CE(1), .D(i), .A0(1), .A1(1), .A2(1), .A3(1), .Q(o0));
|
|
SRL16E ring1( .CLK(clk), .CE(1), .D(o0), .A0(1), .A1(1), .A2(1), .A3(1), .Q(o1));
|
|
SRL16E ring2( .CLK(clk), .CE(1), .D(o1), .A0(1), .A1(1), .A2(1), .A3(1), .Q(o2));
|
|
SRL16E ring3( .CLK(clk), .CE(1), .D(o2), .A0(1), .A1(1), .A2(1), .A3(1), .Q(o));
|
|
endmodule
|
|
|
|
module ram256x1s(
|
|
input d,
|
|
input we,
|
|
input wclk,
|
|
input [7:0] a,
|
|
output o);
|
|
|
|
wire [1:0] rsel = a[7:6];
|
|
wire [3:0] oo;
|
|
genvar i;
|
|
generate
|
|
for (i = 0; i < 4; i=i+1) begin : ramx
|
|
RAM64X1S r0(.O(oo[i]), .A0(a[0]), .A1(a[1]), .A2(a[2]), .A3(a[3]), .A4(a[4]), .A5(a[5]), .D(d), .WCLK(wclk), .WE((rsel == i) & we));
|
|
end
|
|
endgenerate
|
|
|
|
assign o = oo[rsel];
|
|
endmodule
|
|
|
|
module ram448x1s(
|
|
input d,
|
|
input we,
|
|
input wclk,
|
|
input [8:0] a,
|
|
output o);
|
|
|
|
wire [2:0] rsel = a[8:6];
|
|
wire [7:0] oo;
|
|
genvar i;
|
|
generate
|
|
for (i = 0; i < 7; i=i+1) begin : ramx
|
|
RAM64X1S r0(.O(oo[i]), .A0(a[0]), .A1(a[1]), .A2(a[2]), .A3(a[3]), .A4(a[4]), .A5(a[5]), .D(d), .WCLK(wclk), .WE((rsel == i) & we));
|
|
end
|
|
endgenerate
|
|
|
|
assign o = oo[rsel];
|
|
endmodule
|
|
|
|
module ram400x1s(
|
|
input d,
|
|
input we,
|
|
input wclk,
|
|
input [8:0] a,
|
|
output o);
|
|
|
|
wire [2:0] rsel = a[8:6];
|
|
wire [6:0] oo;
|
|
genvar i;
|
|
generate
|
|
for (i = 0; i < 6; i=i+1) begin : ramx
|
|
RAM64X1S r0(.O(oo[i]), .A0(a[0]), .A1(a[1]), .A2(a[2]), .A3(a[3]), .A4(a[4]), .A5(a[5]), .D(d), .WCLK(wclk), .WE((rsel == i) & we));
|
|
end
|
|
endgenerate
|
|
RAM16X1S r6(.O(oo[6]), .A0(a[0]), .A1(a[1]), .A2(a[2]), .A3(a[3]), .D(d), .WCLK(wclk), .WE((rsel == 6) & we));
|
|
|
|
assign o = oo[rsel];
|
|
endmodule
|
|
|
|
module ram256x8s(
|
|
input [7:0] d,
|
|
input we,
|
|
input wclk,
|
|
input [7:0] a,
|
|
output [7:0] o);
|
|
genvar i;
|
|
generate
|
|
for (i = 0; i < 8; i=i+1) begin : ramx
|
|
ram256x1s ramx(
|
|
.d(d[i]),
|
|
.we(we),
|
|
.wclk(wclk),
|
|
.a(a),
|
|
.o(o[i]));
|
|
end
|
|
endgenerate
|
|
endmodule
|
|
|
|
module ram32x8s(
|
|
input [7:0] d,
|
|
input we,
|
|
input wclk,
|
|
input [4:0] a,
|
|
output [7:0] o);
|
|
genvar i;
|
|
generate
|
|
for (i = 0; i < 8; i=i+1) begin : ramx
|
|
RAM32X1S r0(.O(o[i]), .A0(a[0]), .A1(a[1]), .A2(a[2]), .A3(a[3]), .A4(a[4]), .D(d[i]), .WCLK(wclk), .WE(we));
|
|
end
|
|
endgenerate
|
|
endmodule
|
|
|
|
module ram64x8s(
|
|
input [7:0] d,
|
|
input we,
|
|
input wclk,
|
|
input [5:0] a,
|
|
output [7:0] o);
|
|
genvar i;
|
|
generate
|
|
for (i = 0; i < 8; i=i+1) begin : ramx
|
|
RAM64X1S r0(.O(o[i]), .A0(a[0]), .A1(a[1]), .A2(a[2]), .A3(a[3]), .A4(a[4]), .A5(a[5]), .D(d[i]), .WCLK(wclk), .WE(we));
|
|
end
|
|
endgenerate
|
|
endmodule
|
|
|
|
module mRAM32X1D(
|
|
input D,
|
|
input WE,
|
|
input WCLK,
|
|
input A0, // port A
|
|
input A1,
|
|
input A2,
|
|
input A3,
|
|
input A4,
|
|
input DPRA0, // port B
|
|
input DPRA1,
|
|
input DPRA2,
|
|
input DPRA3,
|
|
input DPRA4,
|
|
output DPO, // port A out
|
|
output SPO); // port B out
|
|
|
|
parameter INIT = 32'b0;
|
|
wire hDPO;
|
|
wire lDPO;
|
|
wire hSPO;
|
|
wire lSPO;
|
|
RAM16X1D
|
|
#( .INIT(INIT[15:0]) )
|
|
lo(
|
|
.D(D),
|
|
.WE(WE & !A4),
|
|
.WCLK(WCLK),
|
|
.A0(A0),
|
|
.A1(A1),
|
|
.A2(A2),
|
|
.A3(A3),
|
|
.DPRA0(DPRA0),
|
|
.DPRA1(DPRA1),
|
|
.DPRA2(DPRA2),
|
|
.DPRA3(DPRA3),
|
|
.DPO(lDPO),
|
|
.SPO(lSPO));
|
|
RAM16X1D
|
|
#( .INIT(INIT[31:16]) )
|
|
hi(
|
|
.D(D),
|
|
.WE(WE & A4),
|
|
.WCLK(WCLK),
|
|
.A0(A0),
|
|
.A1(A1),
|
|
.A2(A2),
|
|
.A3(A3),
|
|
.DPRA0(DPRA0),
|
|
.DPRA1(DPRA1),
|
|
.DPRA2(DPRA2),
|
|
.DPRA3(DPRA3),
|
|
.DPO(hDPO),
|
|
.SPO(hSPO));
|
|
assign DPO = DPRA4 ? hDPO : lDPO;
|
|
assign SPO = A4 ? hSPO : lSPO;
|
|
endmodule
|
|
|
|
module mRAM64X1D(
|
|
input D,
|
|
input WE,
|
|
input WCLK,
|
|
input A0, // port A
|
|
input A1,
|
|
input A2,
|
|
input A3,
|
|
input A4,
|
|
input A5,
|
|
input DPRA0, // port B
|
|
input DPRA1,
|
|
input DPRA2,
|
|
input DPRA3,
|
|
input DPRA4,
|
|
input DPRA5,
|
|
output DPO, // port A out
|
|
output SPO); // port B out
|
|
|
|
parameter INIT = 64'b0;
|
|
wire hDPO;
|
|
wire lDPO;
|
|
wire hSPO;
|
|
wire lSPO;
|
|
mRAM32X1D
|
|
#( .INIT(INIT[31:0]) )
|
|
lo(
|
|
.D(D),
|
|
.WE(WE & !A5),
|
|
.WCLK(WCLK),
|
|
.A0(A0),
|
|
.A1(A1),
|
|
.A2(A2),
|
|
.A3(A3),
|
|
.A4(A4),
|
|
.DPRA0(DPRA0),
|
|
.DPRA1(DPRA1),
|
|
.DPRA2(DPRA2),
|
|
.DPRA3(DPRA3),
|
|
.DPRA4(DPRA4),
|
|
.DPO(lDPO),
|
|
.SPO(lSPO));
|
|
mRAM32X1D
|
|
#( .INIT(INIT[63:32]) )
|
|
hi(
|
|
.D(D),
|
|
.WE(WE & A5),
|
|
.WCLK(WCLK),
|
|
.A0(A0),
|
|
.A1(A1),
|
|
.A2(A2),
|
|
.A3(A3),
|
|
.A4(A4),
|
|
.DPRA0(DPRA0),
|
|
.DPRA1(DPRA1),
|
|
.DPRA2(DPRA2),
|
|
.DPRA3(DPRA3),
|
|
.DPRA4(DPRA4),
|
|
.DPO(hDPO),
|
|
.SPO(hSPO));
|
|
assign DPO = DPRA5 ? hDPO : lDPO;
|
|
assign SPO = A5 ? hSPO : lSPO;
|
|
endmodule
|
|
|
|
module mRAM128X1D(
|
|
input D,
|
|
input WE,
|
|
input WCLK,
|
|
input A0, // port A
|
|
input A1,
|
|
input A2,
|
|
input A3,
|
|
input A4,
|
|
input A5,
|
|
input A6,
|
|
input DPRA0, // port B
|
|
input DPRA1,
|
|
input DPRA2,
|
|
input DPRA3,
|
|
input DPRA4,
|
|
input DPRA5,
|
|
input DPRA6,
|
|
output DPO, // port A out
|
|
output SPO); // port B out
|
|
parameter INIT = 128'b0;
|
|
|
|
wire hDPO;
|
|
wire lDPO;
|
|
wire hSPO;
|
|
wire lSPO;
|
|
mRAM64X1D
|
|
#( .INIT(INIT[63:0]) )
|
|
lo(
|
|
.D(D),
|
|
.WE(WE & !A6),
|
|
.WCLK(WCLK),
|
|
.A0(A0),
|
|
.A1(A1),
|
|
.A2(A2),
|
|
.A3(A3),
|
|
.A4(A4),
|
|
.A5(A5),
|
|
.DPRA0(DPRA0),
|
|
.DPRA1(DPRA1),
|
|
.DPRA2(DPRA2),
|
|
.DPRA3(DPRA3),
|
|
.DPRA4(DPRA4),
|
|
.DPRA5(DPRA5),
|
|
.DPO(lDPO),
|
|
.SPO(lSPO));
|
|
mRAM64X1D
|
|
#( .INIT(INIT[127:64]) )
|
|
hi(
|
|
.D(D),
|
|
.WE(WE & A6),
|
|
.WCLK(WCLK),
|
|
.A0(A0),
|
|
.A1(A1),
|
|
.A2(A2),
|
|
.A3(A3),
|
|
.A4(A4),
|
|
.A5(A5),
|
|
.DPRA0(DPRA0),
|
|
.DPRA1(DPRA1),
|
|
.DPRA2(DPRA2),
|
|
.DPRA3(DPRA3),
|
|
.DPRA4(DPRA4),
|
|
.DPRA5(DPRA5),
|
|
.DPO(hDPO),
|
|
.SPO(hSPO));
|
|
assign DPO = DPRA6 ? hDPO : lDPO;
|
|
assign SPO = A6 ? hSPO : lSPO;
|
|
endmodule
|
|
|
|
|
|
module mRAM256X1D(
|
|
input D,
|
|
input WE,
|
|
input WCLK,
|
|
input A0, // port A
|
|
input A1,
|
|
input A2,
|
|
input A3,
|
|
input A4,
|
|
input A5,
|
|
input A6,
|
|
input A7,
|
|
input DPRA0, // port B
|
|
input DPRA1,
|
|
input DPRA2,
|
|
input DPRA3,
|
|
input DPRA4,
|
|
input DPRA5,
|
|
input DPRA6,
|
|
input DPRA7,
|
|
output DPO, // port A out
|
|
output SPO); // port B out
|
|
|
|
wire hDPO;
|
|
wire lDPO;
|
|
wire hSPO;
|
|
wire lSPO;
|
|
mRAM128X1D
|
|
lo(
|
|
.D(D),
|
|
.WE(WE & !A7),
|
|
.WCLK(WCLK),
|
|
.A0(A0),
|
|
.A1(A1),
|
|
.A2(A2),
|
|
.A3(A3),
|
|
.A4(A4),
|
|
.A5(A5),
|
|
.A6(A6),
|
|
.DPRA0(DPRA0),
|
|
.DPRA1(DPRA1),
|
|
.DPRA2(DPRA2),
|
|
.DPRA3(DPRA3),
|
|
.DPRA4(DPRA4),
|
|
.DPRA5(DPRA5),
|
|
.DPRA6(DPRA6),
|
|
.DPO(lDPO),
|
|
.SPO(lSPO));
|
|
mRAM128X1D
|
|
hi(
|
|
.D(D),
|
|
.WE(WE & A7),
|
|
.WCLK(WCLK),
|
|
.A0(A0),
|
|
.A1(A1),
|
|
.A2(A2),
|
|
.A3(A3),
|
|
.A4(A4),
|
|
.A5(A5),
|
|
.A6(A6),
|
|
.DPRA0(DPRA0),
|
|
.DPRA1(DPRA1),
|
|
.DPRA2(DPRA2),
|
|
.DPRA3(DPRA3),
|
|
.DPRA4(DPRA4),
|
|
.DPRA5(DPRA5),
|
|
.DPRA6(DPRA6),
|
|
.DPO(hDPO),
|
|
.SPO(hSPO));
|
|
assign DPO = DPRA7 ? hDPO : lDPO;
|
|
assign SPO = A7 ? hSPO : lSPO;
|
|
endmodule
|
|
|
|
module ram32x8d(
|
|
input [7:0] ad,
|
|
input wea,
|
|
input wclk,
|
|
input [4:0] a,
|
|
input [4:0] b,
|
|
output [7:0] ao,
|
|
output [7:0] bo
|
|
);
|
|
genvar i;
|
|
generate
|
|
for (i = 0; i < 8; i=i+1) begin : ramx
|
|
mRAM32X1D ramx(
|
|
.D(ad[i]),
|
|
.WE(wea),
|
|
.WCLK(wclk),
|
|
.A0(a[0]),
|
|
.A1(a[1]),
|
|
.A2(a[2]),
|
|
.A3(a[3]),
|
|
.A4(a[4]),
|
|
.DPRA0(b[0]),
|
|
.DPRA1(b[1]),
|
|
.DPRA2(b[2]),
|
|
.DPRA3(b[3]),
|
|
.DPRA4(b[4]),
|
|
.SPO(ao[i]),
|
|
.DPO(bo[i]));
|
|
end
|
|
endgenerate
|
|
endmodule
|
|
|
|
module ram64x8d(
|
|
input [7:0] ad,
|
|
input wea,
|
|
input wclk,
|
|
input [5:0] a,
|
|
input [5:0] b,
|
|
output [7:0] ao,
|
|
output [7:0] bo
|
|
);
|
|
genvar i;
|
|
generate
|
|
for (i = 0; i < 8; i=i+1) begin : ramx
|
|
mRAM64X1D ramx(
|
|
.D(ad[i]),
|
|
.WE(wea),
|
|
.WCLK(wclk),
|
|
.A0(a[0]),
|
|
.A1(a[1]),
|
|
.A2(a[2]),
|
|
.A3(a[3]),
|
|
.A4(a[4]),
|
|
.A5(a[5]),
|
|
.DPRA0(b[0]),
|
|
.DPRA1(b[1]),
|
|
.DPRA2(b[2]),
|
|
.DPRA3(b[3]),
|
|
.DPRA4(b[4]),
|
|
.DPRA5(b[5]),
|
|
.SPO(ao[i]),
|
|
.DPO(bo[i]));
|
|
end
|
|
endgenerate
|
|
endmodule
|
|
|
|
// Same but latched read port, for CPU
|
|
module ram32x8rd(
|
|
input wclk,
|
|
input [15:0] ad,
|
|
input wea,
|
|
input [4:0] a,
|
|
input [4:0] b,
|
|
output reg [15:0] ao,
|
|
output reg [15:0] bo
|
|
);
|
|
wire [15:0] _ao;
|
|
wire [15:0] _bo;
|
|
always @(posedge wclk)
|
|
begin
|
|
ao <= _ao;
|
|
bo <= _bo;
|
|
end
|
|
genvar i;
|
|
generate
|
|
for (i = 0; i < 16; i=i+1) begin : ramx
|
|
mRAM32X1D ramx(
|
|
.D(ad[i]),
|
|
.WE(wea),
|
|
.WCLK(wclk),
|
|
.A0(a[0]),
|
|
.A1(a[1]),
|
|
.A2(a[2]),
|
|
.A3(a[3]),
|
|
.A4(a[4]),
|
|
.DPRA0(b[0]),
|
|
.DPRA1(b[1]),
|
|
.DPRA2(b[2]),
|
|
.DPRA3(b[3]),
|
|
.DPRA4(b[4]),
|
|
.SPO(_ao[i]),
|
|
.DPO(_bo[i]));
|
|
end
|
|
endgenerate
|
|
endmodule
|
|
|
|
module ram128x8rd(
|
|
input wclk,
|
|
input [15:0] ad,
|
|
input wea,
|
|
input [6:0] a,
|
|
input [6:0] b,
|
|
output reg [15:0] ao,
|
|
output reg [15:0] bo
|
|
);
|
|
wire [15:0] _ao;
|
|
wire [15:0] _bo;
|
|
always @(posedge wclk)
|
|
begin
|
|
ao <= _ao;
|
|
bo <= _bo;
|
|
end
|
|
genvar i;
|
|
generate
|
|
for (i = 0; i < 8; i=i+1) begin : ramx
|
|
mRAM128X1D ramx(
|
|
.D(ad[i]),
|
|
.WE(wea),
|
|
.WCLK(wclk),
|
|
.A0(a[0]),
|
|
.A1(a[1]),
|
|
.A2(a[2]),
|
|
.A3(a[3]),
|
|
.A4(a[4]),
|
|
.A5(a[5]),
|
|
.A6(a[6]),
|
|
.DPRA0(b[0]),
|
|
.DPRA1(b[1]),
|
|
.DPRA2(b[2]),
|
|
.DPRA3(b[3]),
|
|
.DPRA4(b[4]),
|
|
.DPRA5(b[5]),
|
|
.DPRA6(b[6]),
|
|
.SPO(_ao[i]),
|
|
.DPO(_bo[i]));
|
|
end
|
|
endgenerate
|
|
endmodule
|
|
|
|
module ram256x8rd(
|
|
input wclk,
|
|
input [7:0] ad,
|
|
input wea,
|
|
input [7:0] a,
|
|
input [7:0] b,
|
|
output reg [7:0] ao,
|
|
output reg [7:0] bo
|
|
);
|
|
wire [7:0] _ao;
|
|
wire [7:0] _bo;
|
|
always @(posedge wclk)
|
|
begin
|
|
ao <= _ao;
|
|
bo <= _bo;
|
|
end
|
|
genvar i;
|
|
generate
|
|
for (i = 0; i < 8; i=i+1) begin : ramx
|
|
mRAM256X1D ramx(
|
|
.D(ad[i]),
|
|
.WE(wea),
|
|
.WCLK(wclk),
|
|
.A0(a[0]),
|
|
.A1(a[1]),
|
|
.A2(a[2]),
|
|
.A3(a[3]),
|
|
.A4(a[4]),
|
|
.A5(a[5]),
|
|
.A6(a[6]),
|
|
.A7(a[7]),
|
|
.DPRA0(b[0]),
|
|
.DPRA1(b[1]),
|
|
.DPRA2(b[2]),
|
|
.DPRA3(b[3]),
|
|
.DPRA4(b[4]),
|
|
.DPRA5(b[5]),
|
|
.DPRA6(b[6]),
|
|
.DPRA7(b[7]),
|
|
.SPO(_ao[i]),
|
|
.DPO(_bo[i]));
|
|
end
|
|
endgenerate
|
|
endmodule
|
|
|
|
module ram448x9s(
|
|
input [8:0] d,
|
|
input we,
|
|
input wclk,
|
|
input [8:0] a,
|
|
output [8:0] o);
|
|
genvar i;
|
|
generate
|
|
for (i = 0; i < 9; i=i+1) begin : ramx
|
|
ram448x1s ramx(
|
|
.d(d[i]),
|
|
.we(we),
|
|
.wclk(wclk),
|
|
.a(a),
|
|
.o(o[i]));
|
|
end
|
|
endgenerate
|
|
endmodule
|
|
|
|
module ram400x9s(
|
|
input [8:0] d,
|
|
input we,
|
|
input wclk,
|
|
input [8:0] a,
|
|
output [8:0] o);
|
|
genvar i;
|
|
generate
|
|
for (i = 0; i < 9; i=i+1) begin : ramx
|
|
ram400x1s ramx(
|
|
.d(d[i]),
|
|
.we(we),
|
|
.wclk(wclk),
|
|
.a(a),
|
|
.o(o[i]));
|
|
end
|
|
endgenerate
|
|
endmodule
|
|
|
|
module ram400x8s(
|
|
input [7:0] d,
|
|
input we,
|
|
input wclk,
|
|
input [8:0] a,
|
|
output [7:0] o);
|
|
genvar i;
|
|
generate
|
|
for (i = 0; i < 8; i=i+1) begin : ramx
|
|
ram400x1s ramx(
|
|
.d(d[i]),
|
|
.we(we),
|
|
.wclk(wclk),
|
|
.a(a),
|
|
.o(o[i]));
|
|
end
|
|
endgenerate
|
|
endmodule
|
|
|
|
module ram400x7s(
|
|
input [6:0] d,
|
|
input we,
|
|
input wclk,
|
|
input [8:0] a,
|
|
output [6:0] o);
|
|
genvar i;
|
|
generate
|
|
for (i = 0; i < 7; i=i+1) begin : ramx
|
|
ram400x1s ramx(
|
|
.d(d[i]),
|
|
.we(we),
|
|
.wclk(wclk),
|
|
.a(a),
|
|
.o(o[i]));
|
|
end
|
|
endgenerate
|
|
endmodule
|
|
|
|
// SPI can be many things, so to be clear, this implementation:
|
|
// MSB first
|
|
// CPOL 0, leading edge when SCK rises
|
|
// CPHA 0, sample on leading, setup on trailing
|
|
|
|
module SPI_memory(
|
|
input clk,
|
|
input SCK, input MOSI, output MISO, input SSEL,
|
|
output wire [15:0] raddr, // read address
|
|
output reg [15:0] waddr, // write address
|
|
output reg [7:0] data_w,
|
|
input [7:0] data_r,
|
|
output reg we,
|
|
output reg re,
|
|
output mem_clk
|
|
);
|
|
reg [15:0] paddr;
|
|
reg [4:0] count;
|
|
wire [4:0] _count = (count == 23) ? 16 : (count + 1);
|
|
|
|
assign mem_clk = clk;
|
|
|
|
// sync SCK to the FPGA clock using a 3-bits shift register
|
|
reg [2:0] SCKr; always @(posedge clk) SCKr <= {SCKr[1:0], SCK};
|
|
wire SCK_risingedge = (SCKr[2:1]==2'b01); // now we can detect SCK rising edges
|
|
wire SCK_fallingedge = (SCKr[2:1]==2'b10); // and falling edges
|
|
|
|
// same thing for SSEL
|
|
reg [2:0] SSELr; always @(posedge clk) SSELr <= {SSELr[1:0], SSEL};
|
|
wire SSEL_active = ~SSELr[1]; // SSEL is active low
|
|
wire SSEL_startmessage = (SSELr[2:1]==2'b10); // message starts at falling edge
|
|
wire SSEL_endmessage = (SSELr[2:1]==2'b01); // message stops at rising edge
|
|
|
|
// and for MOSI
|
|
reg [1:0] MOSIr; always @(posedge clk) MOSIr <= {MOSIr[0], MOSI};
|
|
wire MOSI_data = MOSIr[1];
|
|
|
|
assign raddr = (count[4] == 0) ? {paddr[14:0], MOSI} : paddr;
|
|
|
|
always @(posedge clk)
|
|
begin
|
|
if (~SSEL_active) begin
|
|
count <= 0;
|
|
re <= 0;
|
|
we <= 0;
|
|
end else
|
|
if (SCK_risingedge) begin
|
|
if (count[4] == 0) begin
|
|
we <= 0;
|
|
paddr <= raddr;
|
|
re <= (count == 15);
|
|
end else begin
|
|
data_w <= {data_w[6:0], MOSI_data};
|
|
if (count == 23) begin
|
|
we <= paddr[15];
|
|
re <= !paddr[15];
|
|
waddr <= paddr;
|
|
paddr <= paddr + 1;
|
|
end else begin
|
|
we <= 0;
|
|
re <= 0;
|
|
end
|
|
end
|
|
count <= _count;
|
|
end
|
|
if (SCK_fallingedge) begin
|
|
re <= 0;
|
|
we <= 0;
|
|
end
|
|
end
|
|
|
|
reg readbit;
|
|
always @*
|
|
begin
|
|
case (count[2:0])
|
|
3'd0: readbit <= data_r[7];
|
|
3'd1: readbit <= data_r[6];
|
|
3'd2: readbit <= data_r[5];
|
|
3'd3: readbit <= data_r[4];
|
|
3'd4: readbit <= data_r[3];
|
|
3'd5: readbit <= data_r[2];
|
|
3'd6: readbit <= data_r[1];
|
|
3'd7: readbit <= data_r[0];
|
|
endcase
|
|
end
|
|
assign MISO = readbit;
|
|
|
|
endmodule
|
|
|
|
// This is a Delta-Sigma Digital to Analog Converter
|
|
`define MSBI 12 // Most significant Bit of DAC input, 12 means 13-bit
|
|
|
|
module dac(DACout, DACin, Clk, Reset);
|
|
output DACout; // This is the average output that feeds low pass filter
|
|
reg DACout; // for optimum performance, ensure that this ff is in IOB
|
|
input [`MSBI:0] DACin; // DAC input (excess 2**MSBI)
|
|
input Clk;
|
|
input Reset;
|
|
reg [`MSBI+2:0] DeltaAdder; // Output of Delta adder
|
|
reg [`MSBI+2:0] SigmaAdder; // Output of Sigma adder
|
|
reg [`MSBI+2:0] SigmaLatch; // Latches output of Sigma adder
|
|
reg [`MSBI+2:0] DeltaB; // B input of Delta adder
|
|
|
|
always @(SigmaLatch) DeltaB = {SigmaLatch[`MSBI+2], SigmaLatch[`MSBI+2]} << (`MSBI+1);
|
|
always @(DACin or DeltaB) DeltaAdder = DACin + DeltaB;
|
|
always @(DeltaAdder or SigmaLatch) SigmaAdder = DeltaAdder + SigmaLatch;
|
|
always @(posedge Clk or posedge Reset)
|
|
begin
|
|
if (Reset) begin
|
|
SigmaLatch <= #1 1'b1 << (`MSBI+1);
|
|
DACout <= #1 1'b0;
|
|
end else begin
|
|
SigmaLatch <= #1 SigmaAdder;
|
|
DACout <= #1 SigmaLatch[`MSBI+2];
|
|
end
|
|
end
|
|
endmodule
|
|
|
|
module top(
|
|
input clka,
|
|
output [2:0] vga_red,
|
|
output [2:0] vga_green,
|
|
output [2:0] vga_blue,
|
|
output vga_hsync_n,
|
|
output vga_vsync_n,
|
|
|
|
input SCK, // arduino 13
|
|
input MOSI, // arduino 11
|
|
inout MISO, // arduino 12
|
|
input SSEL, // arduino 9
|
|
inout AUX, // arduino 2
|
|
output AUDIOL,
|
|
output AUDIOR,
|
|
|
|
output flashMOSI,
|
|
input flashMISO,
|
|
output flashSCK,
|
|
output flashSSEL
|
|
|
|
);
|
|
|
|
|
|
wire mem_clk;
|
|
wire [7:0] host_mem_data_wr;
|
|
reg [7:0] mem_data_rd;
|
|
reg [7:0] latched_mem_data_rd;
|
|
wire [14:0] mem_w_addr; // Combined write address
|
|
wire [14:0] mem_r_addr; // Combined read address
|
|
wire [14:0] host_mem_w_addr;
|
|
wire [14:0] host_mem_r_addr;
|
|
wire host_mem_wr;
|
|
wire mem_rd;
|
|
|
|
wire vga_clk;
|
|
ck_div #(.DIV_BY(2), .MULT_BY(4)) vga_ck_gen(.ck_in(clka), .ck_out(vga_clk));
|
|
|
|
wire [15:0] j1_insn;
|
|
wire [12:0] j1_insn_addr;
|
|
wire [15:0] j1_mem_addr;
|
|
wire [15:0] j1_mem_dout;
|
|
wire j1_mem_wr;
|
|
|
|
wire [7:0] j1insnl_read;
|
|
wire [7:0] j1insnh_read;
|
|
wire [7:0] mem_data_rd0;
|
|
wire [7:0] mem_data_rd1;
|
|
wire [7:0] mem_data_rd2;
|
|
wire [7:0] mem_data_rd3;
|
|
wire [7:0] mem_data_rd4;
|
|
wire [7:0] mem_data_rd5;
|
|
|
|
wire gdMISO;
|
|
|
|
always @(posedge vga_clk)
|
|
if (mem_rd)
|
|
latched_mem_data_rd <= mem_data_rd;
|
|
|
|
SPI_memory spi1(
|
|
.clk(vga_clk),
|
|
.SCK(SCK), .MOSI(MOSI), .MISO(gdMISO), .SSEL(SSEL),
|
|
.raddr(host_mem_r_addr),
|
|
.waddr(host_mem_w_addr),
|
|
.data_w(host_mem_data_wr),
|
|
.data_r(latched_mem_data_rd),
|
|
.we(host_mem_wr),
|
|
.re(mem_rd),
|
|
.mem_clk(mem_clk));
|
|
wire host_busy = host_mem_wr | mem_rd;
|
|
wire mem_wr = host_busy ? host_mem_wr : j1_mem_wr;
|
|
wire [7:0] mem_data_wr = host_busy ? host_mem_data_wr : j1_mem_dout;
|
|
wire [14:0] mem_addr = host_busy ? (host_mem_wr ? host_mem_w_addr : host_mem_r_addr) : j1_mem_addr;
|
|
assign mem_w_addr = host_busy ? host_mem_w_addr : j1_mem_addr;
|
|
assign mem_r_addr = host_busy ? host_mem_r_addr : j1_mem_addr;
|
|
|
|
reg signed [15:0] sample_l;
|
|
reg signed [15:0] sample_r;
|
|
reg [6:0] modvoice = 64;
|
|
reg [14:0] bg_color;
|
|
reg [7:0] pin2mode = 0;
|
|
wire pin2f = (pin2mode == 8'h46);
|
|
wire pin2j = (pin2mode == 8'h4A);
|
|
|
|
wire flashsel = (AUX == 0) & pin2f;
|
|
|
|
assign MISO = SSEL ? (flashsel ? flashMISO : 1'bz) : gdMISO;
|
|
// assign MISO = SSEL ? (1'bz ) : gdMISO;
|
|
// PULLUP MISO_pullup(.O(MISO));
|
|
// IOBUF MISO_iobuf(
|
|
// .I(gdMISO),
|
|
// .IO(MISO),
|
|
// .T(SSEL));
|
|
|
|
|
|
// user-visible registers
|
|
reg [7:0] frames;
|
|
reg [8:0] scrollx;
|
|
reg [8:0] scrolly;
|
|
reg jkmode;
|
|
|
|
wire [7:0] palette16l_read;
|
|
wire [7:0] palette16h_read;
|
|
wire [4:0] palette16_addr;
|
|
wire [15:0] palette16_data;
|
|
|
|
// 11'b00001xxxxx0: low
|
|
wire palette16_wr = (mem_wr & (mem_w_addr[14:11] == 5) & (mem_w_addr[10:6] == 1));
|
|
ram32x8d palette16l(
|
|
.a(mem_addr[5:1]),
|
|
.wclk(mem_clk),
|
|
.wea((mem_w_addr[0] == 0) & palette16_wr),
|
|
.ad(mem_data_wr),
|
|
.ao(palette16l_read),
|
|
.b(palette16_addr),
|
|
.bo(palette16_data[7:0]));
|
|
ram32x8d palette16h(
|
|
.a(mem_addr[5:1]),
|
|
.wclk(mem_clk),
|
|
.wea((mem_w_addr[0] == 1) & palette16_wr),
|
|
.ad(mem_data_wr),
|
|
.ao(palette16h_read),
|
|
.b(palette16_addr),
|
|
.bo(palette16_data[15:8]));
|
|
|
|
wire [7:0] palette4l_read;
|
|
wire [7:0] palette4h_read;
|
|
wire [4:0] palette4_addr;
|
|
wire [15:0] palette4_data;
|
|
|
|
// 11'b00010xxxxx0: low
|
|
wire palette4_wr = (mem_wr & (mem_w_addr[14:11] == 5) & (mem_w_addr[10:6] == 2));
|
|
ram32x8d palette4l(
|
|
.a(mem_addr[5:1]),
|
|
.wclk(mem_clk),
|
|
.wea((mem_w_addr[0] == 0) & palette4_wr),
|
|
.ad(mem_data_wr),
|
|
.ao(palette4l_read),
|
|
.b(palette4_addr),
|
|
.bo(palette4_data[7:0]));
|
|
ram32x8d palette4h(
|
|
.a(mem_addr[5:1]),
|
|
.wclk(mem_clk),
|
|
.wea((mem_w_addr[0] == 1) & palette4_wr),
|
|
.ad(mem_data_wr),
|
|
.ao(palette4h_read),
|
|
.b(palette4_addr),
|
|
.bo(palette4_data[15:8]));
|
|
|
|
// Generate CounterX and CounterY
|
|
// A single line is 1040 clocks. Line pair is 2080 clocks.
|
|
|
|
reg [10:0] CounterX;
|
|
reg [9:0] CounterY;
|
|
wire CounterXmaxed = (CounterX==1040);
|
|
|
|
always @(posedge vga_clk)
|
|
if(CounterXmaxed)
|
|
CounterX <= 0;
|
|
else
|
|
CounterX <= CounterX + 1;
|
|
wire lastline = (CounterY == 665);
|
|
wire [9:0] _CounterY = lastline ? 0 : (CounterY + 1);
|
|
|
|
always @(posedge vga_clk)
|
|
if (CounterXmaxed) begin
|
|
CounterY <= _CounterY;
|
|
if (lastline)
|
|
frames <= frames + 1;
|
|
end
|
|
|
|
reg [12:0] comp_workcnt; // Compositor work address
|
|
reg comp_workcnt_lt_400;
|
|
always @(posedge vga_clk)
|
|
begin
|
|
if (CounterXmaxed & (CounterY[0] == 0)) begin
|
|
comp_workcnt <= 0;
|
|
comp_workcnt_lt_400 <= 1;
|
|
end else begin
|
|
comp_workcnt <= comp_workcnt + 1;
|
|
if (comp_workcnt == 399)
|
|
comp_workcnt_lt_400 <= 0;
|
|
end
|
|
end
|
|
|
|
// horizontal
|
|
// Front porch 56
|
|
// Sync 120
|
|
// Back porch 64
|
|
|
|
// vertical
|
|
// Front porch 37 lines
|
|
// Sync 6
|
|
// Back porch 23
|
|
|
|
// `define HSTART (53 + 120 + 61)
|
|
`define HSTART 0
|
|
|
|
reg vga_HS, vga_VS, vga_active;
|
|
always @(posedge vga_clk)
|
|
begin
|
|
vga_HS <= ((800 + 61) <= CounterX) & (CounterX < (800 + 61 + 120));
|
|
vga_VS <= (35 <= CounterY) & (CounterY < (35 + 6));
|
|
vga_active = ((`HSTART + 1) <= CounterX) & (CounterX < (`HSTART + 1 + 800)) & ((35 + 6 + 21) < CounterY) & (CounterY <= (35 + 6 + 21 + 600));
|
|
end
|
|
|
|
wire [10:0] xx = (CounterX - `HSTART);
|
|
wire [10:0] xx_1 = (CounterX - `HSTART + 1);
|
|
wire [10:0] yy = (CounterY + 2 - (35 + 6 + 21 + 1)); // yy range 0-665
|
|
|
|
wire [10:0] column = comp_workcnt + scrollx;
|
|
wire [10:0] row = yy[10:1] + scrolly;
|
|
wire [7:0] glyph;
|
|
|
|
wire [11:0] picaddr = {row[8:3], column[8:3]};
|
|
|
|
|
|
wire en_pic = (mem_addr[14:12] == 0);
|
|
RAM_PICTURE picture(
|
|
.dia(0),
|
|
.doa(glyph),
|
|
.wea(0),
|
|
.ena(1),
|
|
.clka(vga_clk),
|
|
.addra(picaddr),
|
|
.dib(mem_data_wr),
|
|
.dob(mem_data_rd0),
|
|
.web(mem_wr),
|
|
.enb(en_pic),
|
|
.clkb(mem_clk),
|
|
.addrb(mem_addr)
|
|
);
|
|
|
|
reg [2:0] _column;
|
|
always @(posedge vga_clk)
|
|
_column = column;
|
|
|
|
wire en_chr = (mem_addr[14:12] == 1);
|
|
wire [1:0] charout;
|
|
RAM_CHR chars(
|
|
.dia(0), .doa(charout), .wea(0), .ena(1), .clka(vga_clk), .addra({glyph, row[2:0], _column[2], ~_column[1:0]}),
|
|
.dib(mem_data_wr), .dob(mem_data_rd1), .web(mem_wr), .enb(en_chr), .clkb(mem_clk), .addrb(mem_addr));
|
|
|
|
reg [7:0] _glyph;
|
|
always @(posedge vga_clk)
|
|
_glyph <= glyph;
|
|
|
|
wire [4:0] bg_r;
|
|
wire [4:0] bg_g;
|
|
wire [4:0] bg_b;
|
|
|
|
wire en_pal = (mem_addr[14:11] == 4'b0100);
|
|
wire [15:0] char_matte;
|
|
RAM_PAL charpalette(
|
|
.DIA(mem_data_wr),
|
|
.WEA(mem_wr),
|
|
.ENA(en_pal),
|
|
.CLKA(mem_clk),
|
|
.ADDRA(mem_addr),
|
|
.DOA(mem_data_rd2),
|
|
.SSRA(0),
|
|
|
|
.DIB(0),
|
|
.WEB(0),
|
|
.ENB(1),
|
|
.CLKB(vga_clk),
|
|
.ADDRB({_glyph, charout}),
|
|
.DOB(char_matte),
|
|
.SSRB(0)
|
|
);
|
|
// wire [4:0] bg_mix_r = bg_color[14:10] + char_matte[14:10];
|
|
// wire [4:0] bg_mix_g = bg_color[9:5] + char_matte[9:5];
|
|
// wire [4:0] bg_mix_b = bg_color[4:0] + char_matte[4:0];
|
|
// wire [14:0] char_final = char_matte[15] ? {bg_mix_r, bg_mix_g, bg_mix_b} : char_matte[14:0];
|
|
wire [14:0] char_final = char_matte[15] ? bg_color : char_matte[14:0];
|
|
|
|
reg [7:0] mem_data_rd_reg;
|
|
|
|
// Collision detection RAM is readable during vblank
|
|
// writes coll_d to coll_w_addr during render
|
|
wire coll_rd = (yy >= 600); // 1 means reading
|
|
wire [7:0] coll_d;
|
|
wire [7:0] coll_w_addr;
|
|
wire coll_we;
|
|
wire [7:0] coll_addr = coll_rd ? mem_r_addr[7:0] : coll_w_addr;
|
|
wire [7:0] coll_o;
|
|
ram256x8s coll(.o(coll_o), .a(coll_addr), .d(coll_d), .wclk(vga_clk), .we(~coll_rd & coll_we));
|
|
wire [7:0] screenshot_rd;
|
|
|
|
wire [7:0] voicefl_read;
|
|
wire [7:0] voicefh_read;
|
|
wire [7:0] voicela_read;
|
|
wire [7:0] voicera_read;
|
|
|
|
reg j1_reset = 0;
|
|
reg spr_disable = 0;
|
|
reg spr_page = 0;
|
|
|
|
// Screenshot notes
|
|
// three states, controlled by screenshot_primed, _done:
|
|
// primed done composer.A
|
|
// 0 0 screenshot disabled write(comp_write)
|
|
// 1 0 screenshot primed write(comp_write)
|
|
// 1 1 screenshot done read(mem_r_addr[9:1])
|
|
|
|
reg [8:0] screenshot_yy; // 9 bits, 0-400
|
|
reg screenshot_primed;
|
|
reg screenshot_done;
|
|
wire screenshot_reset;
|
|
wire [8:0] public_yy = coll_rd ? 300 : yy[10:1];
|
|
|
|
always @(posedge vga_clk)
|
|
begin
|
|
if (screenshot_reset)
|
|
screenshot_done <= 0;
|
|
else if (CounterXmaxed & screenshot_primed & !screenshot_done & (public_yy == screenshot_yy)) begin
|
|
screenshot_done <= 1;
|
|
end
|
|
end
|
|
|
|
always @(mem_data_rd_reg)
|
|
begin
|
|
casex (mem_r_addr[10:0])
|
|
11'h000: mem_data_rd_reg <= 8'h6d; // Gameduino ident
|
|
11'h001: mem_data_rd_reg <= `REVISION;
|
|
11'h002: mem_data_rd_reg <= frames;
|
|
11'h003: mem_data_rd_reg <= coll_rd; // called VBLANK, but really "is coll readable?"
|
|
11'h004: mem_data_rd_reg <= scrollx[7:0];
|
|
11'h005: mem_data_rd_reg <= scrollx[8];
|
|
11'h006: mem_data_rd_reg <= scrolly[7:0];
|
|
11'h007: mem_data_rd_reg <= scrolly[8];
|
|
11'h008: mem_data_rd_reg <= jkmode;
|
|
11'h009: mem_data_rd_reg <= j1_reset;
|
|
11'h00a: mem_data_rd_reg <= spr_disable;
|
|
11'h00b: mem_data_rd_reg <= spr_page;
|
|
11'h00c: mem_data_rd_reg <= pin2mode;
|
|
11'h00e: mem_data_rd_reg <= bg_color[7:0];
|
|
11'h00f: mem_data_rd_reg <= bg_color[14:8];
|
|
11'h010: mem_data_rd_reg <= sample_l[7:0];
|
|
11'h011: mem_data_rd_reg <= sample_l[15:8];
|
|
11'h012: mem_data_rd_reg <= sample_r[7:0];
|
|
11'h013: mem_data_rd_reg <= sample_r[15:8];
|
|
11'h014: mem_data_rd_reg <= modvoice;
|
|
11'h01e: mem_data_rd_reg <= public_yy[7:0];
|
|
11'h01f: mem_data_rd_reg <= {screenshot_done, 6'b000000, public_yy[8]};
|
|
|
|
11'b00001xxxxx0: mem_data_rd_reg <= palette16l_read;
|
|
11'b00001xxxxx1: mem_data_rd_reg <= palette16h_read;
|
|
11'b00010xxxxx0: mem_data_rd_reg <= palette4l_read;
|
|
11'b00010xxxxx1: mem_data_rd_reg <= palette4h_read;
|
|
11'b001xxxxxxxx:
|
|
mem_data_rd_reg <= coll_rd ? coll_o : 8'hff;
|
|
11'b010xxxxxx00: mem_data_rd_reg <= voicefl_read;
|
|
11'b010xxxxxx01: mem_data_rd_reg <= voicefh_read;
|
|
11'b010xxxxxx10: mem_data_rd_reg <= voicela_read;
|
|
11'b010xxxxxx11: mem_data_rd_reg <= voicera_read;
|
|
11'b011xxxxxxx0: mem_data_rd_reg <= j1insnl_read;
|
|
11'b011xxxxxxx1: mem_data_rd_reg <= j1insnh_read;
|
|
11'b1xxxxxxxxxx: mem_data_rd_reg <= screenshot_rd;
|
|
// default: mem_data_rd_reg <= 0;
|
|
endcase
|
|
end
|
|
|
|
reg [17:0] soundcounter;
|
|
always @(posedge vga_clk)
|
|
soundcounter <= soundcounter + 1;
|
|
wire [5:0] viN = soundcounter + 1;
|
|
wire [5:0] vi = soundcounter;
|
|
|
|
wire voice_wr = mem_wr & (mem_w_addr[14:11] == 5) & (mem_w_addr[10:8] == 3'b010);
|
|
wire voicefl_wr = voice_wr & (mem_w_addr[1:0] == 2'b00);
|
|
wire voicefh_wr = voice_wr & (mem_w_addr[1:0] == 2'b01);
|
|
wire voicela_wr = voice_wr & (mem_w_addr[1:0] == 2'b10);
|
|
wire voicera_wr = voice_wr & (mem_w_addr[1:0] == 2'b11);
|
|
|
|
wire [7:0] voicela_data;
|
|
wire [7:0] voicera_data;
|
|
wire [7:0] voicefl_data;
|
|
wire [7:0] voicefh_data;
|
|
wire [5:0] voice_addr = mem_addr[7:2];
|
|
|
|
ram64x8d voicefl(
|
|
.a(voice_addr),
|
|
.wclk(mem_clk),
|
|
.wea(voicefl_wr),
|
|
.ad(mem_data_wr),
|
|
.ao(voicefl_read),
|
|
.b(viN),
|
|
.bo(voicefl_data));
|
|
|
|
ram64x8d voicefh(
|
|
.a(voice_addr),
|
|
.wclk(mem_clk),
|
|
.wea(voicefh_wr),
|
|
.ad(mem_data_wr),
|
|
.ao(voicefh_read),
|
|
.b(viN),
|
|
.bo(voicefh_data));
|
|
|
|
ram64x8d voicela(
|
|
.a(voice_addr),
|
|
.wclk(mem_clk),
|
|
.wea(voicela_wr),
|
|
.ad(mem_data_wr),
|
|
.ao(voicela_read),
|
|
.b(viN),
|
|
.bo(voicela_data));
|
|
|
|
ram64x8d voicera(
|
|
.a(voice_addr),
|
|
.wclk(mem_clk),
|
|
.wea(voicera_wr),
|
|
.ad(mem_data_wr),
|
|
.ao(voicera_read),
|
|
.b(viN),
|
|
.bo(voicera_data));
|
|
|
|
assign screenshot_reset = mem_wr & (mem_w_addr[14:11] == 5) & (mem_w_addr[10:0] == 11'h01f);
|
|
always @(posedge mem_clk)
|
|
begin
|
|
if (mem_wr & mem_w_addr[14:11] == 5)
|
|
casex (mem_w_addr[10:0])
|
|
11'h004: scrollx[7:0] <= mem_data_wr;
|
|
11'h005: scrollx[8] <= mem_data_wr;
|
|
11'h006: scrolly[7:0] <= mem_data_wr;
|
|
11'h007: scrolly[8] <= mem_data_wr;
|
|
11'h008: jkmode <= mem_data_wr;
|
|
11'h009: j1_reset <= mem_data_wr;
|
|
11'h00a: spr_disable <= mem_data_wr;
|
|
11'h00b: spr_page <= mem_data_wr;
|
|
11'h00c: pin2mode <= mem_data_wr;
|
|
11'h00e: bg_color[7:0] <= mem_data_wr;
|
|
11'h00f: bg_color[14:8] <= mem_data_wr;
|
|
11'h010: sample_l[7:0] <= mem_data_wr;
|
|
11'h011: sample_l[15:8] <= mem_data_wr;
|
|
11'h012: sample_r[7:0] <= mem_data_wr;
|
|
11'h013: sample_r[15:8] <= mem_data_wr;
|
|
11'h014: modvoice <= mem_data_wr;
|
|
|
|
11'h01e: screenshot_yy[7:0] <= mem_data_wr;
|
|
11'h01f: begin screenshot_primed <= mem_data_wr[7];
|
|
screenshot_yy[8] <= mem_data_wr; end
|
|
endcase
|
|
end
|
|
|
|
/*
|
|
0000-0fff Picture
|
|
1000-1fff Character
|
|
2000-27ff Character
|
|
2800-2fff (Unused)
|
|
3000-37ff Sprite values
|
|
3800-3fff Sprite palette
|
|
4000-7fff Sprite image
|
|
*/
|
|
always @*
|
|
begin
|
|
case (mem_addr[14:11]) // 2K pages
|
|
4'h0: mem_data_rd <= mem_data_rd0; // pic
|
|
4'h1: mem_data_rd <= mem_data_rd0;
|
|
4'h2: mem_data_rd <= mem_data_rd1; // chr
|
|
4'h3: mem_data_rd <= mem_data_rd1;
|
|
4'h4: mem_data_rd <= mem_data_rd2; // pal
|
|
4'h5: mem_data_rd <= mem_data_rd_reg;
|
|
4'h6: mem_data_rd <= mem_data_rd3; // sprval
|
|
4'h7: mem_data_rd <= mem_data_rd4; // sprpal
|
|
4'h8: mem_data_rd <= mem_data_rd5; // sprimg
|
|
4'h9: mem_data_rd <= mem_data_rd5; // sprimg
|
|
4'ha: mem_data_rd <= mem_data_rd5; // sprimg
|
|
4'hb: mem_data_rd <= mem_data_rd5; // sprimg
|
|
4'hc: mem_data_rd <= mem_data_rd5; // sprimg
|
|
4'hd: mem_data_rd <= mem_data_rd5; // sprimg
|
|
4'he: mem_data_rd <= mem_data_rd5; // sprimg
|
|
4'hf: mem_data_rd <= mem_data_rd5; // sprimg
|
|
|
|
default: mem_data_rd <= 8'h97;
|
|
endcase
|
|
end
|
|
|
|
// Sprite memory
|
|
|
|
// Stage 1: scan for valid
|
|
reg [8:0] s1_count;
|
|
|
|
wire en_sprval = (mem_addr[14:11] == 4'b0110);
|
|
wire [31:0] sprval_data;
|
|
RAM_SPRVAL sprval(
|
|
.DIA(mem_data_wr),
|
|
.WEA(mem_wr),
|
|
.ENA(en_sprval),
|
|
.CLKA(mem_clk),
|
|
.ADDRA(mem_addr),
|
|
.DOA(mem_data_rd3),
|
|
.SSRA(0),
|
|
|
|
.DIB(0),
|
|
.WEB(0),
|
|
.ENB(1),
|
|
.CLKB(vga_clk),
|
|
.ADDRB({spr_page, s1_count[7:0]}),
|
|
.DOB(sprval_data),
|
|
.SSRB(0)
|
|
);
|
|
wire [9:0] sprpal_addr;
|
|
wire [15:0] sprpal_data;
|
|
wire en_sprpal = (mem_addr[14:11] == 4'b0111);
|
|
RAM_SPRPAL sprpal(
|
|
.DIA(mem_data_wr),
|
|
.WEA(mem_wr),
|
|
.ENA(en_sprpal),
|
|
.CLKA(mem_clk),
|
|
.ADDRA(mem_addr),
|
|
.DOA(mem_data_rd4),
|
|
.SSRA(0),
|
|
|
|
.DIB(0),
|
|
.WEB(0),
|
|
.ENB(1),
|
|
.CLKB(vga_clk),
|
|
.ADDRB(sprpal_addr),
|
|
.DOB(sprpal_data),
|
|
.SSRB(0)
|
|
);
|
|
wire [13:0] sprimg_readaddr;
|
|
wire [7:0] sprimg_data;
|
|
wire en_sprimg = (mem_addr[14] == 1'b1);
|
|
// ram16K_8_8 sprimg(
|
|
RAM_SPRIMG sprimg(
|
|
.dia(mem_data_wr),
|
|
.wea(mem_wr),
|
|
.ena(en_sprimg),
|
|
.clka(mem_clk),
|
|
.addra(mem_addr),
|
|
.doa(mem_data_rd5),
|
|
.ssra(0),
|
|
|
|
.dib(0),
|
|
.web(0),
|
|
.enb(1),
|
|
.clkb(vga_clk),
|
|
.addrb(sprimg_readaddr),
|
|
.dob(sprimg_data),
|
|
.ssrb(0)
|
|
);
|
|
|
|
// Stage 1: scan for valid
|
|
|
|
reg s1_consider; // Consider the sprval on the next cycle
|
|
wire s2_room; // Does s2 fifo have room for one entry?
|
|
always @(posedge vga_clk)
|
|
begin
|
|
if (comp_workcnt == 0) begin
|
|
s1_count <= 0;
|
|
s1_consider <= 0;
|
|
end else
|
|
if ((s1_count <= 255) & s2_room) begin
|
|
s1_count <= s1_count + 1;
|
|
s1_consider <= 1;
|
|
end else begin
|
|
s1_consider <= 0;
|
|
end
|
|
end
|
|
wire [31:0] s1_out = sprval_data;
|
|
wire [8:0] s1_y_offset = yy[9:1] - s1_out[24:16];
|
|
wire s1_visible = (spr_disable == 0) & (s1_y_offset[8:4] == 0);
|
|
wire s1_valid = s1_consider & s1_visible;
|
|
reg [8:0] s1_id;
|
|
always @(posedge vga_clk)
|
|
s1_id <= s1_count;
|
|
|
|
// Stage 2: fifo
|
|
wire [4:0] s2_fullness;
|
|
wire s3_read;
|
|
wire [40:0] s2_out;
|
|
fifo #(40) s2(.clk(vga_clk),
|
|
.wr(s1_valid), .datain({s1_id, s1_out}),
|
|
.rd(s3_read), .dataout(s2_out),
|
|
.fullness(s2_fullness));
|
|
assign s2_room = (s2_fullness < 14);
|
|
|
|
wire s2_valid = s2_fullness != 0;
|
|
|
|
// 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
|
// [ image ] [ y ] [PAL] [ ROT ] [ x ]
|
|
|
|
/* Stage 3: read sprimg
|
|
consume s2_out on last cycle
|
|
out: s3_valid, s3_pal, s3_out, s3_compaddr
|
|
*/
|
|
|
|
reg [4:0] s3_state;
|
|
reg [3:0] s3_pal;
|
|
reg [31:0] s3_in;
|
|
assign s3_read = (s3_state == 15);
|
|
always @(posedge vga_clk)
|
|
begin
|
|
if (comp_workcnt < 403)
|
|
s3_state <= 16;
|
|
else if (s3_state == 16) begin
|
|
if (s2_valid) begin
|
|
s3_state <= 0;
|
|
s3_in <= s2_out;
|
|
end
|
|
end else begin
|
|
s3_state <= s3_state + 1;
|
|
end
|
|
s3_pal <= s2_out[15:12];
|
|
end
|
|
wire [3:0] s3_yoffset = yy[4:1] - s2_out[19:16];
|
|
wire [3:0] s3_prev_state = (s3_state == 16) ? 0 : (s3_state + 1);
|
|
wire [3:0] readx = (s2_out[9] ? s3_yoffset : s3_prev_state) ^ {4{s2_out[10]}};
|
|
wire [3:0] ready = (s2_out[9] ? s3_prev_state : s3_yoffset) ^ {4{s2_out[11]}};
|
|
assign sprimg_readaddr = {s2_out[30:25], ready, readx};
|
|
wire [7:0] s3_out = sprimg_data;
|
|
wire [8:0] s3_compaddr = s2_out[8:0] + s3_state;
|
|
wire s3_valid = (s3_state != 16) & (s3_compaddr < 400);
|
|
reg [8:0] s3_id;
|
|
reg s3_jk;
|
|
always @(posedge vga_clk)
|
|
begin
|
|
s3_id <= s2_out[40:32];
|
|
s3_jk <= s2_out[31];
|
|
end
|
|
|
|
/* Stage 4: read sprpal
|
|
out: s4_valid, s4_out, s4_compaddr
|
|
*/
|
|
reg [15:0] sprpal4;
|
|
reg [15:0] sprpal16;
|
|
assign sprpal_addr = {s3_pal[1:0], s3_out};
|
|
reg [8:0] s4_compaddr;
|
|
reg s4_valid;
|
|
reg [8:0] s4_id;
|
|
reg s4_jk;
|
|
wire [3:0] subfield4 = s3_pal[1] ? s3_out[7:4] : s3_out[3:0];
|
|
wire [1:0] subfield2 = s3_pal[2] ? (s3_pal[1] ? s3_out[7:6] : s3_out[5:4]) : (s3_pal[1] ? s3_out[3:2] : s3_out[1:0]);
|
|
assign palette4_addr = {s3_pal[0], subfield2};
|
|
assign palette16_addr = {s3_pal[0], subfield4};
|
|
always @(posedge vga_clk)
|
|
begin
|
|
s4_compaddr <= s3_compaddr;
|
|
s4_valid <= s3_valid;
|
|
s4_id <= s3_id;
|
|
s4_jk <= s3_jk;
|
|
sprpal4 <= palette4_data;
|
|
sprpal16 <= palette16_data;
|
|
end
|
|
wire [15:0] s4_out = s3_pal[3] ? sprpal4 : ((s3_pal[3:2] == 0) ? sprpal_data : sprpal16);
|
|
|
|
// Common signals for collision and composite
|
|
wire sprite_write = s4_valid & !s4_out[15]; // transparency
|
|
|
|
// Collision detect
|
|
// Have 400x9 occupancy buffer. If NEW overwrites a fragment OLD
|
|
// (and their groups differ) write OLD to coll[NEW].
|
|
// Reset coll to FF at start of frame.
|
|
// Reset occ to FF at start of line, since sprites drawn 0->ff,
|
|
// ff is impossible and means empty.
|
|
|
|
wire coll_scrub = (yy == 0) & (comp_workcnt < 256);
|
|
wire [8:0] occ_addr = comp_workcnt_lt_400 ? comp_workcnt : s4_compaddr;
|
|
wire [8:0] occ_d = comp_workcnt_lt_400 ? 9'hff : {s4_jk, s4_id[7:0]};
|
|
wire [8:0] oldocc;
|
|
wire occ_w = comp_workcnt_lt_400 | sprite_write;
|
|
ram400x9s occ(.o(oldocc), .a(occ_addr), .d(occ_d), .wclk(vga_clk), .we(occ_w));
|
|
assign coll_d = coll_scrub ? 8'hff : oldocc[7:0];
|
|
assign coll_w_addr = coll_scrub ? comp_workcnt : s4_id[7:0];
|
|
// old contents 0xff, never write
|
|
// jkmode=1 and JK's differ, allow write
|
|
wire overwriting = (oldocc[7:0] != 8'hff);
|
|
wire jkpass = (jkmode == 0) | (oldocc[8] ^ s4_jk);
|
|
assign coll_we = coll_scrub | ((403 <= comp_workcnt) & sprite_write & overwriting & jkpass);
|
|
|
|
// Composite
|
|
|
|
wire comp_read = yy[1]; // which block is reading
|
|
wire [8:0] comp_scanout = xx[9:1];
|
|
wire [8:0] comp_write = (comp_workcnt < 403) ? (comp_workcnt - 3) : s4_compaddr;
|
|
wire comp_part1 = (3 <= comp_workcnt) & (comp_workcnt < 403);
|
|
`ifdef NELLY
|
|
wire [14:0] comp_out0;
|
|
wire [14:0] comp_out1;
|
|
RAMB16_S18_S18 composer(
|
|
.DIPA(0),
|
|
.DIA(comp_part1 ? char_final : s4_out),
|
|
.WEA(comp_read == 1 & (comp_part1 | sprite_write)),
|
|
.ENA(1),
|
|
.CLKA(vga_clk),
|
|
.ADDRA({1'b0, (comp_read == 0) ? comp_scanout : comp_write[8:0]}),
|
|
.DOA(comp_out0),
|
|
.SSRA(0),
|
|
|
|
.DIPB(0),
|
|
.DIB(comp_part1 ? char_final : s4_out),
|
|
.WEB(comp_read == 0 & (comp_part1 | sprite_write)),
|
|
.ENB(1),
|
|
.CLKB(vga_clk),
|
|
.ADDRB({1'b1, (comp_read == 1) ? comp_scanout : comp_write[8:0]}),
|
|
.DOB(comp_out1),
|
|
.SSRB(0)
|
|
);
|
|
wire [14:0] comp_out = comp_read ? comp_out1 : comp_out0;
|
|
`else
|
|
wire ss = screenshot_primed & screenshot_done; // screenshot readout mode
|
|
wire [15:0] screenshot_rdHL;
|
|
wire [14:0] comp_out;
|
|
// Port A is the write, or read when screenshot is ready
|
|
// Port B is scanout
|
|
RAMB16_S18_S18
|
|
composer(
|
|
.DIPA(0),
|
|
.DIA(comp_part1 ? char_final : s4_out),
|
|
.WEA(!ss & (comp_part1 | sprite_write)),
|
|
.ENA(1),
|
|
.CLKA(vga_clk),
|
|
.ADDRA(ss ? {screenshot_yy[0], mem_r_addr[9:1]} : {comp_read, comp_write[8:0]}),
|
|
.DOA(screenshot_rdHL),
|
|
.SSRA(0),
|
|
|
|
.DIPB(0),
|
|
.DIB(0),
|
|
.WEB(0),
|
|
.ENB(1),
|
|
.CLKB(vga_clk),
|
|
.ADDRB({!comp_read, comp_scanout}),
|
|
.DOB(comp_out),
|
|
.SSRB(0)
|
|
);
|
|
assign screenshot_rd = mem_r_addr[0] ? screenshot_rdHL[15:8] : screenshot_rdHL[7:0];
|
|
`endif
|
|
assign {bg_r,bg_g,bg_b} = comp_out;
|
|
|
|
// Figure out from above signals when composite completes
|
|
// by detecting pipeline idle
|
|
wire composite_complete = (comp_workcnt > 403) & (s1_count == 256) & !s1_consider & !s2_valid & (s3_state == 16) & !s4_valid;
|
|
|
|
// Signal generation
|
|
|
|
wire [16:0] lfsr;
|
|
lfsre lfsr0(
|
|
.clk(vga_clk),
|
|
.lfsr(lfsr));
|
|
|
|
wire [1:0] dith;
|
|
// 0 2
|
|
// 3 1
|
|
assign dith = {(xx[0]^yy[0]), yy[0]};
|
|
wire [5:0] dith_r = (bg_r + dith);
|
|
wire [5:0] dith_g = (bg_g + dith);
|
|
wire [5:0] dith_b = (bg_b + dith);
|
|
wire [2:0] f_r = {3{dith_r[5]}} | dith_r[4:2];
|
|
wire [2:0] f_g = {3{dith_g[5]}} | dith_g[4:2];
|
|
wire [2:0] f_b = {3{dith_b[5]}} | dith_b[4:2];
|
|
|
|
wire [2:0] ccc = { charout[1], charout[0], charout[0] };
|
|
assign vga_red = vga_active ? f_r : 0;
|
|
assign vga_green = vga_active ? f_g : 0;
|
|
assign vga_blue = vga_active ? f_b : 0;
|
|
assign vga_hsync_n = ~vga_HS;
|
|
assign vga_vsync_n = ~vga_VS;
|
|
|
|
/*
|
|
An 18-bit counter, multiplied by the frequency gives a single bit
|
|
pulse that advances the voice's wave counter.
|
|
Frequency of 4 means 1Hz, 16385 means 4095.75Hz.
|
|
18-bit counter increments every 1/(2**18), or 262144 Hz.
|
|
*/
|
|
`define MASTERFREQ (1 << 22)
|
|
reg [27:0] d;
|
|
wire [27:0] dInc = d[27] ? (`MASTERFREQ) : (`MASTERFREQ - 50000000);
|
|
wire [27:0] dN = d + dInc;
|
|
|
|
reg [16:0] soundmaster; // This increments at MASTERFREQ Hz
|
|
always @(posedge vga_clk)
|
|
begin
|
|
d = dN;
|
|
// clock B tick whenever d[27] is zero
|
|
if (dN[27] == 0) begin
|
|
soundmaster <= soundmaster + 1;
|
|
end
|
|
end
|
|
|
|
wire [6:0] hsin;
|
|
wire [6:0] wavecounter;
|
|
wire [6:0] note = wavecounter[6:0];
|
|
|
|
`ifdef YES
|
|
RAM64X1S #(.INIT(64'b0000000000110101100010001111010010010111100010001101011000000000) /* 0 */
|
|
) sin0(.O(hsin[0]), .A0(note[0]), .A1(note[1]), .A2(note[2]), .A3(note[3]), .A4(note[4]), .A5(note[5]), .D(0), .WCLK(vga_clk), .WE(0));
|
|
RAM64X1S #(.INIT(64'b0101010101101100011100010101001111100101010001110001101101010101) /* 1 */
|
|
) sin1(.O(hsin[1]), .A0(note[0]), .A1(note[1]), .A2(note[2]), .A3(note[3]), .A4(note[4]), .A5(note[5]), .D(0), .WCLK(vga_clk), .WE(0));
|
|
RAM64X1S #(.INIT(64'b0110011001001001010101001100111111111001100101010100100100110011) /* 2 */
|
|
) sin2(.O(hsin[2]), .A0(note[0]), .A1(note[1]), .A2(note[2]), .A3(note[3]), .A4(note[4]), .A5(note[5]), .D(0), .WCLK(vga_clk), .WE(0));
|
|
RAM64X1S #(.INIT(64'b0010110100100100110011000011111111111110000110011001001001011010) /* 3 */
|
|
) sin3(.O(hsin[3]), .A0(note[0]), .A1(note[1]), .A2(note[2]), .A3(note[3]), .A4(note[4]), .A5(note[5]), .D(0), .WCLK(vga_clk), .WE(0));
|
|
RAM64X1S #(.INIT(64'b0001110011100011110000111111111111111111111000011110001110011100) /* 4 */
|
|
) sin4(.O(hsin[4]), .A0(note[0]), .A1(note[1]), .A2(note[2]), .A3(note[3]), .A4(note[4]), .A5(note[5]), .D(0), .WCLK(vga_clk), .WE(0));
|
|
RAM64X1S #(.INIT(64'b0000001111100000001111111111111111111111111111100000001111100000) /* 5 */
|
|
) sin5(.O(hsin[5]), .A0(note[0]), .A1(note[1]), .A2(note[2]), .A3(note[3]), .A4(note[4]), .A5(note[5]), .D(0), .WCLK(vga_clk), .WE(0));
|
|
RAM64X1S #(.INIT(64'b0000000000011111111111111111111111111111111111111111110000000000) /* 6 */
|
|
) sin6(.O(hsin[6]), .A0(note[0]), .A1(note[1]), .A2(note[2]), .A3(note[3]), .A4(note[4]), .A5(note[5]), .D(0), .WCLK(vga_clk), .WE(0));
|
|
`else
|
|
ROM64X1 #(.INIT(64'b0000000000110101100010001111010010010111100010001101011000000000) /* 0 */) sin0(.O(hsin[0]), .A0(note[0]), .A1(note[1]), .A2(note[2]), .A3(note[3]), .A4(note[4]), .A5(note[5]));
|
|
ROM64X1 #(.INIT(64'b0101010101101100011100010101001111100101010001110001101101010101) /* 1 */) sin1(.O(hsin[1]), .A0(note[0]), .A1(note[1]), .A2(note[2]), .A3(note[3]), .A4(note[4]), .A5(note[5]));
|
|
ROM64X1 #(.INIT(64'b0110011001001001010101001100111111111001100101010100100100110011) /* 2 */) sin2(.O(hsin[2]), .A0(note[0]), .A1(note[1]), .A2(note[2]), .A3(note[3]), .A4(note[4]), .A5(note[5]));
|
|
ROM64X1 #(.INIT(64'b0010110100100100110011000011111111111110000110011001001001011010) /* 3 */) sin3(.O(hsin[3]), .A0(note[0]), .A1(note[1]), .A2(note[2]), .A3(note[3]), .A4(note[4]), .A5(note[5]));
|
|
ROM64X1 #(.INIT(64'b0001110011100011110000111111111111111111111000011110001110011100) /* 4 */) sin4(.O(hsin[4]), .A0(note[0]), .A1(note[1]), .A2(note[2]), .A3(note[3]), .A4(note[4]), .A5(note[5]));
|
|
ROM64X1 #(.INIT(64'b0000001111100000001111111111111111111111111111100000001111100000) /* 5 */) sin5(.O(hsin[5]), .A0(note[0]), .A1(note[1]), .A2(note[2]), .A3(note[3]), .A4(note[4]), .A5(note[5]));
|
|
ROM64X1 #(.INIT(64'b0000000000011111111111111111111111111111111111111111110000000000) /* 6 */) sin6(.O(hsin[6]), .A0(note[0]), .A1(note[1]), .A2(note[2]), .A3(note[3]), .A4(note[4]), .A5(note[5]));
|
|
`endif
|
|
|
|
wire signed [7:0] sin = note[6] ? (8'h00 - hsin) : hsin;
|
|
|
|
wire voiceshape = voicefh_data[7];
|
|
wire [14:0] voicefreq = {voicefh_data[6:0], voicefl_data};
|
|
|
|
wire [35:0] derived = {1'b0, soundmaster} * voicefreq;
|
|
|
|
wire highfreq = voicefreq[14];
|
|
wire newpulse = highfreq ? derived[18] : derived[17]; // pulse is a square wave frequency 64*f
|
|
wire oldpulse;
|
|
wire [6:0] nextwavecounter = voiceshape ? lfsr : (wavecounter + (highfreq ? 2 : 1));
|
|
wire [6:0] _wavecounter = (newpulse != oldpulse) ? nextwavecounter : wavecounter;
|
|
|
|
`ifdef NELLY
|
|
ram64x8s voicestate(
|
|
.a(viN),
|
|
.we(1),
|
|
.wclk(vga_clk),
|
|
.d({_wavecounter, newpulse}),
|
|
.o({wavecounter, oldpulse}));
|
|
`else
|
|
wire [8:0] vsi = {_wavecounter, newpulse};
|
|
wire [8:0] vso;
|
|
ring64 vs0(.clk(vga_clk), .i(vsi[0]), .o(vso[0]));
|
|
ring64 vs1(.clk(vga_clk), .i(vsi[1]), .o(vso[1]));
|
|
ring64 vs2(.clk(vga_clk), .i(vsi[2]), .o(vso[2]));
|
|
ring64 vs3(.clk(vga_clk), .i(vsi[3]), .o(vso[3]));
|
|
ring64 vs4(.clk(vga_clk), .i(vsi[4]), .o(vso[4]));
|
|
ring64 vs5(.clk(vga_clk), .i(vsi[5]), .o(vso[5]));
|
|
ring64 vs6(.clk(vga_clk), .i(vsi[6]), .o(vso[6]));
|
|
ring64 vs7(.clk(vga_clk), .i(vsi[7]), .o(vso[7]));
|
|
assign wavecounter = vso[7:1];
|
|
assign oldpulse = vso[0];
|
|
`endif
|
|
|
|
wire signed [8:0] lamp = voicela_data;
|
|
wire signed [8:0] ramp = voicera_data;
|
|
reg signed [35:0] lmodulated;
|
|
reg signed [35:0] rmodulated;
|
|
always @(posedge vga_clk)
|
|
begin
|
|
lmodulated = lamp * sin;
|
|
rmodulated = ramp * sin;
|
|
end
|
|
|
|
// Have lmodulated and rmodulated
|
|
|
|
reg signed [15:0] lacc;
|
|
reg signed [15:0] racc;
|
|
wire signed [15:0] lsum = lacc + lmodulated[15:0];
|
|
wire signed [15:0] rsum = racc + rmodulated[15:0];
|
|
wire signed [31:0] lprod = lacc * lmodulated;
|
|
wire signed [31:0] rprod = racc * rmodulated;
|
|
wire zeroacc = (vi == 63);
|
|
wire [15:0] _lacc = zeroacc ? sample_l : ((vi == modvoice) ? lprod[30:15] : lsum);
|
|
wire [15:0] _racc = zeroacc ? sample_r : ((vi == modvoice) ? rprod[30:15] : rsum);
|
|
reg signed [12:0] lvalue;
|
|
reg signed [12:0] rvalue;
|
|
always @(posedge vga_clk)
|
|
begin
|
|
if (vi == 63) begin
|
|
lvalue <= lsum[15:3] /* + sample_l + 32768 */;
|
|
rvalue <= rsum[15:3] /* + sample_r + 32768 */;
|
|
end
|
|
lacc <= _lacc;
|
|
racc <= _racc;
|
|
end
|
|
|
|
wire signed [7:0] dither = soundcounter;
|
|
// wire [15:0] dither = {soundcounter[0],
|
|
// soundcounter[1],
|
|
// soundcounter[2],
|
|
// soundcounter[3],
|
|
// soundcounter[4],
|
|
// soundcounter[5],
|
|
// soundcounter[6],
|
|
// soundcounter[7],
|
|
// soundcounter[8],
|
|
// soundcounter[9],
|
|
// soundcounter[10],
|
|
// soundcounter[11],
|
|
// soundcounter[12],
|
|
// soundcounter[13],
|
|
// soundcounter[14],
|
|
// soundcounter[15]
|
|
// };
|
|
|
|
`ifdef NELLY
|
|
wire lau_out = lvalue >= dither;
|
|
wire rau_out = rvalue >= dither;
|
|
|
|
assign AUDIOL = lau_out;
|
|
assign AUDIOR = rau_out;
|
|
`else
|
|
wire [12:0] ulvalue = lvalue ^ 4096;
|
|
wire [12:0] urvalue = rvalue ^ 4096;
|
|
dac ldac(AUDIOL, ulvalue, vga_clk, 0);
|
|
dac rdac(AUDIOR, urvalue, vga_clk, 0);
|
|
`endif
|
|
|
|
reg [2:0] busyhh;
|
|
always @(posedge vga_clk) busyhh = { busyhh[1:0], host_busy };
|
|
|
|
// J1 Peripherals
|
|
reg [7:0] icap_i; // ICAP in
|
|
reg icap_write;
|
|
reg icap_ce;
|
|
reg icap_clk;
|
|
|
|
wire [7:0] icap_o; // ICAP out
|
|
wire icap_busy;
|
|
|
|
reg j1_p2_dir = 1; // pin defaults to input
|
|
reg j1_p2_o = 1;
|
|
|
|
ICAP_SPARTAN3A ICAP_SPARTAN3A_inst (
|
|
.O(icap_o),
|
|
.BUSY(icap_busy),
|
|
.I(icap_i),
|
|
.WRITE(icap_write),
|
|
.CE(icap_ce),
|
|
.CLK(icap_clk));
|
|
|
|
reg dna_read;
|
|
reg dna_shift;
|
|
reg dna_clk;
|
|
wire dna_dout;
|
|
DNA_PORT dna(
|
|
.DOUT(dna_dout),
|
|
.DIN(0),
|
|
.READ(dna_read),
|
|
.SHIFT(dna_shift),
|
|
.CLK(dna_clk));
|
|
|
|
wire j1_wr;
|
|
|
|
reg [8:0] YYLINE;
|
|
wire [9:0] yyline = (CounterY + 4 - (35 + 6 + 21 + 1));
|
|
always @(posedge vga_clk)
|
|
begin
|
|
// if (xx == 400)
|
|
if (composite_complete)
|
|
YYLINE = yyline[9:1];
|
|
end
|
|
|
|
reg [15:0] freqhz = 8000;
|
|
reg [7:0] freqtick;
|
|
|
|
reg [26:0] freqd;
|
|
wire [26:0] freqdN = freqd + freqhz - (freqd[26] ? 0 : 50000000);
|
|
always @(posedge vga_clk)
|
|
begin
|
|
freqd = freqdN;
|
|
if (freqd[26] == 0)
|
|
freqtick = freqtick + 1;
|
|
end
|
|
|
|
reg [15:0] local_j1_read;
|
|
always @*
|
|
begin
|
|
case ({j1_mem_addr[4:1], 1'b0})
|
|
5'h00: local_j1_read <= YYLINE;
|
|
5'h02: local_j1_read <= icap_o;
|
|
5'h0c: local_j1_read <= freqtick;
|
|
5'h0e: local_j1_read <= AUX;
|
|
5'h12: local_j1_read <= lfsr;
|
|
5'h14: local_j1_read <= soundcounter;
|
|
5'h16: local_j1_read <= flashMISO;
|
|
5'h18: local_j1_read <= dna_dout;
|
|
|
|
// default: local_j1_read <= 16'hffff;
|
|
endcase
|
|
end
|
|
|
|
wire [0:7] j1_mem_dout_be = j1_mem_dout;
|
|
reg j1_flashMOSI;
|
|
reg j1_flashSCK;
|
|
reg j1_flashSSEL;
|
|
|
|
always @(posedge vga_clk)
|
|
begin
|
|
if (j1_wr & (j1_mem_addr[15] == 1))
|
|
case ({j1_mem_addr[4:1], 1'b0})
|
|
// 5'h06: icap_i <= j1_mem_dout;
|
|
// 5'h08: icap_write <= j1_mem_dout;
|
|
// 5'h0a: icap_ce <= j1_mem_dout;
|
|
// 5'h0c: icap_clk <= j1_mem_dout;
|
|
5'h06: {icap_write,icap_ce,icap_clk,icap_i} <= j1_mem_dout;
|
|
5'h08: {dna_read, dna_shift, dna_clk} <= j1_mem_dout;
|
|
5'h0a: freqhz <= j1_mem_dout;
|
|
5'h0e: j1_p2_o <= j1_mem_dout;
|
|
5'h10: j1_p2_dir <= j1_mem_dout;
|
|
5'h18: j1_flashMOSI <= j1_mem_dout;
|
|
5'h1a: j1_flashSCK <= j1_mem_dout;
|
|
5'h1c: j1_flashSSEL <= j1_mem_dout;
|
|
endcase
|
|
end
|
|
|
|
assign j1_mem_wr = j1_wr & (j1_mem_addr[15] == 0);
|
|
j0 j(.sys_clk_i(vga_clk),
|
|
.sys_rst_i(j1_reset),
|
|
.insn(j1_insn),
|
|
.insn_addr(j1_insn_addr),
|
|
.mem_wr(j1_wr),
|
|
.mem_addr(j1_mem_addr),
|
|
.mem_dout(j1_mem_dout),
|
|
.mem_din(j1_mem_addr[15] ? local_j1_read : mem_data_rd),
|
|
.pause(host_busy | (busyhh != 0))
|
|
);
|
|
|
|
// 0x2b00: j1 insn RAM
|
|
wire jinsn_wr = (mem_wr & (mem_w_addr[14:8] == 6'h2b));
|
|
RAM_CODEL jinsnl(.b(j1_insn_addr), .bo(j1_insn[7:0]),
|
|
.a(mem_addr[7:1]),
|
|
.wclk(vga_clk),
|
|
.wea((mem_w_addr[0] == 0) & jinsn_wr),
|
|
.ad(mem_data_wr),
|
|
.ao(j1insnl_read));
|
|
RAM_CODEH jinsnh(.b(j1_insn_addr), .bo(j1_insn[15:8]),
|
|
.a(mem_addr[7:1]),
|
|
.wclk(vga_clk),
|
|
.wea((mem_w_addr[0] == 1) & jinsn_wr),
|
|
.ad(mem_data_wr),
|
|
.ao(j1insnh_read));
|
|
|
|
assign flashMOSI = pin2j ? j1_flashMOSI : MOSI;
|
|
assign flashSCK = pin2j ? j1_flashSCK : SCK;
|
|
assign flashSSEL = pin2f ? AUX : (pin2j ? j1_flashSSEL : 1);
|
|
|
|
assign AUX = (pin2j & (j1_p2_dir == 0)) ? j1_p2_o : 1'bz;
|
|
|
|
endmodule // top
|