SamCoupe a test3

This commit is contained in:
antoniovillena 2016-04-28 14:18:55 +02:00
parent 9b683eb5f6
commit e6c3fca97a
13 changed files with 1253 additions and 238 deletions

View File

@ -67,12 +67,12 @@ module asic (
HBPORCH = 64,
LBORDER = 48;
parameter HTOTAL = HACTIVEREGION +
RBORDER +
parameter HTOTAL = RBORDER +
HFPORCH +
HSYNC +
HBPORCH +
LBORDER;
LBORDER +
HACTIVEREGION;
parameter VACTIVEREGION = 192,
BBORDER = 48,
@ -89,19 +89,11 @@ module asic (
TBORDER;
// Start of vertical sync, horizontal counter (last 4 scanlines)
parameter BEGINVSYNCH = HACTIVEREGION + RBORDER + HFPORCH + HSYNC + HBPORCH;
parameter BEGINVSYNCH = 0;
// Start and end of vertical retrace interrupt, horizontal counter
parameter BEGINVINTH = BEGINVSYNCH; //HACTIVEREGION + RBORDER + HFPORCH;
parameter ENDVINTH = (BEGINVINTH + 256)%HTOTAL;
// Start and end of vertical retrace interrupt, vertical counter
parameter BEGINVINTV = VACTIVEREGION + BBORDER + VFPORCH - 1;
parameter ENDVINTV = VACTIVEREGION + BBORDER + VFPORCH;
// Start and end of raster interrupt, horizontal counter
parameter BEGINHINTH = HACTIVEREGION + RBORDER;
parameter ENDHINTH = (BEGINHINTH + 256)%HTOTAL;
// Start and end of vertical sync
parameter BEGINVSYNCV = VACTIVEREGION + BBORDER + VFPORCH;
parameter ENDVSYNCV = BEGINVSYNCV + 4;
parameter IOADDR_VMPR = 8'd252,
IOADDR_HMPR = 8'd251,
@ -115,12 +107,7 @@ module asic (
//////////////////////////////////////////////////////////////////////////
// IO regs
`ifdef SYNTH
reg [7:0] vmpr = 8'h00; // port 252. bit 7 is not used. R/W
`else
reg [7:0] vmpr = 8'b01100000; // port 252. bit 7 is not used. R/W. Mode 4 for simulation
`endif
wire [1:0] screen_mode = vmpr[6:5];
wire [4:0] screen_page = vmpr[4:0];
@ -130,9 +117,10 @@ module asic (
wire rom_in_section_d = lmpr[6];
wire write_protect_section_a = lmpr[7];
reg [7:0] hmpr = 8'h00; // port 251. Bit 7 is not used for now. R/W
reg [7:0] hmpr = 8'h00; // port 251.
wire [4:0] high_page = hmpr[4:0];
wire [1:0] clut_mode_3_hi = hmpr[6:5];
wire external_memory = hmpr[7];
reg [7:0] border = 8'h00; // port 254. Bit 6 not implemented. Write only.
wire [3:0] clut_border = {border[5],border[2:0]};
@ -166,15 +154,16 @@ module asic (
end
//////////////////////////////////////////////////////////////////////////
// Pixel counter and scan counter
// Pixel counter (horizontal) and scan counter (vertical)
reg [9:0] hc = 10'h000;
reg [8:0] vc = 9'h000;
always @(posedge clk) begin
if (hc != (HTOTAL-1))
if (hc != (HTOTAL-1)) begin
hc <= hc + 1;
end
else begin
hc <= 10'h000;
hc <= 10'h000;
if (vc != (VTOTAL-1))
vc <= vc + 1;
else
@ -183,24 +172,7 @@ module asic (
end
//////////////////////////////////////////////////////////////////////////
// HPEN and LPEN counters
always @(posedge clk) begin
if (hc[0] == 1'b0) begin
if (hc == HACTIVEREGION) begin
if (vc == VTOTAL-1)
hpen <= 8'h00;
else if (vc < VACTIVEREGION)
hpen <= hpen + 1;
end
if (hc < HACTIVEREGION)
lpen <= lpen + 1;
else
lpen <= 8'h00;
end
end
//////////////////////////////////////////////////////////////////////////
// Syncs and vertical retrace/raster line int generation
// Syncs and vertical retrace/raster line interrupt generation
reg vint_n;
reg rint_n;
@ -208,39 +180,15 @@ module asic (
csync = 1'b1;
vint_n = 1'b1;
rint_n = 1'b1;
if (hc >= (HACTIVEREGION + RBORDER + HFPORCH) &&
hc < (HACTIVEREGION + RBORDER + HFPORCH + HSYNC))
csync = 1'b0;
if ( (vc > BEGINVINTV && vc < (BEGINVINTV+4)) ||
(vc == BEGINVINTV && hc >= BEGINVSYNCH) ||
(vc == (BEGINVINTV+4) && hc < BEGINVSYNCH) )
csync = ~csync;
if ( (vc == BEGINVINTV && hc >= BEGINVINTH) ||
(vc == ENDVINTV && hc < ENDVINTH) )
// if (vc == BEGINVINTV && hc >= BEGINVINTH)
vint_n = 1'b0;
if (lineint >= 8'd0 && lineint <= 8'd191) begin
// if (lineint == 8'd0) begin
// if (vc == VTOTAL-1 && hc >= BEGINHINTH ||
// vc == 9'd0 && hc < ENDHINTH)
// rint_n = 1'b0;
// end
// else begin
// if ({1'b0, lineint} == vc-1 && hc >= BEGINHINTH ||
// {1'b0, lineint} == vc && hc < ENDHINTH)
// rint_n = 1'b0;
// end
// end
if (lineint == 8'd0) begin
if (vc == VTOTAL-1 && hc >= BEGINHINTH)
rint_n = 1'b0;
end
else begin
if ({1'b0, lineint} == vc-1 && hc >= BEGINHINTH)
rint_n = 1'b0;
end
end
if (hc >= (RBORDER + HFPORCH) && hc < (RBORDER + HFPORCH + HSYNC))
csync = 1'b0;
if (vc >= BEGINVSYNCV && vc < ENDVSYNCV)
csync = ~csync;
if (vc == BEGINVSYNCV && hc < 256)
vint_n = 1'b0;
if (lineint >= 8'd0 && lineint <= 8'd191)
if ({1'b0, lineint} == vc && hc < 10'd256)
rint_n = 1'b0;
end
assign int_n = vint_n & rint_n;
@ -249,7 +197,7 @@ module asic (
reg fetching_pixels;
always @* begin
if (vc>=0 && vc<VACTIVEREGION && hc>=0 && hc<HACTIVEREGION)
if (vc>=0 && vc<VACTIVEREGION && hc>=256 && hc<HTOTAL)
fetching_pixels = ~screen_off;
else
fetching_pixels = 1'b0;
@ -260,14 +208,13 @@ module asic (
reg blank_time;
always @* begin
if ( (hc >= (HACTIVEREGION + RBORDER) &&
hc < (HACTIVEREGION + RBORDER + HFPORCH + HSYNC + HBPORCH) ) ||
(vc >= (VACTIVEREGION + BBORDER) &&
vc < (VACTIVEREGION + BBORDER + VFPORCH + VSYNC + VBPORCH) ) ||
(screen_off == 1'b1) )
blank_time = 1'b1;
else
blank_time = 1'b0;
blank_time = 1'b0;
if (screen_off == 1'b1)
blank_time = 1'b1;
if (hc >= RBORDER && hc < (RBORDER + HFPORCH + HSYNC + HBPORCH))
blank_time = 1'b1;
if (vc >= (VACTIVEREGION + BBORDER) && vc < (VACTIVEREGION + BBORDER + VFPORCH + VSYNC + VBPORCH))
blank_time = 1'b1;
end
//////////////////////////////////////////////////////////////////////////
@ -277,20 +224,24 @@ module asic (
always @* begin
mem_contention = 1'b0;
io_contention = 1'b0;
if (hc[3:0]<4'd10)
if (screen_off == 1'b0 && hc[3:0]<4'd10)
io_contention = 1'b1;
else
io_contention = 1'b0;
if (screen_off == 1'b1 && (hc[3:0]==4'd0 ||
hc[3:0]==4'd1 ||
hc[3:0]==4'd8 ||
hc[3:0]==4'd9) )
io_contention = 1'b1;
if (fetching_pixels == 1'b1 && hc[3:0]<4'd10)
mem_contention = 1'b1;
else if (fetching_pixels == 1'b0 && (hc[3:0]==4'd0 ||
hc[3:0]==4'd1 ||
hc[3:0]==4'd8 ||
hc[3:0]==4'd9) )
if (fetching_pixels == 1'b0 && (hc[3:0]==4'd0 ||
hc[3:0]==4'd1 ||
hc[3:0]==4'd8 ||
hc[3:0]==4'd9) )
mem_contention = 1'b1;
if (screen_mode == 2'b00 && hc[3:0]<4'd10 && hc[9:4]<6'd40)
if (screen_mode == 2'b00 && hc[3:0]<4'd10 && (hc<10'd128 || hc>=10'd256))
mem_contention = 1'b1; // extra contention for MODE 1
end
assign asic_is_using_ram = mem_contention & fetching_pixels;
@ -305,7 +256,7 @@ module asic (
wait_n = 1'b1;
else if (mem_contention == 1'b1 && mreq_n == 1'b0)
wait_n = 1'b0;
else if (io_contention == 1'b1 && iorq_n == 1'b0)
else if (io_contention == 1'b1 && iorq_n == 1'b0 && (rd_n == 1'b0 || wr_n == 1'b0))
wait_n = 1'b0;
end
@ -380,7 +331,7 @@ module asic (
else begin // showing border
sregm12 <= 8'h00;
attrreg <= {1'b0, clut_border, 3'b000};
sregm3 <= { {16{clut_border[1:0]}} };
sregm3 <= { {16{clut_border[0],clut_border[1]}} };
sregm4 <= { {8{clut_border}} };
hibits_clut_m3 <= clut_border[3:2];
end
@ -411,7 +362,7 @@ module asic (
else
index = {attrreg[6],attrreg[5:3]};
end
2'd2: index = {hibits_clut_m3, sregm3[31:30]};
2'd2: index = {hibits_clut_m3, sregm3[30], sregm3[31]};
2'd3: index = sregm4[31:28];
endcase
if (blank_time == 1'b1)
@ -424,6 +375,29 @@ module asic (
assign b = {pixel[4], pixel[0]};
assign bright = pixel[3];
//////////////////////////////////////////////////////////////////////////
// HPEN and LPEN counters
reg iorq_prev = 1'b1;
reg [7:0] hpen_internal = 8'h00;
always @(posedge clk) begin
if (hc == 10'd255 && vc == 9'd0) begin
hpen_internal <= 8'h00;
end
else if (hc == (HTOTAL-1)) begin
if (hpen_internal != 8'hC0)
hpen_internal <= hpen_internal + 1;
end
end
always @(posedge clk) begin
iorq_prev <= iorq_n;
if (iorq_prev == 1'b1 && iorq_n == 1'b0) begin // falling edge IORQ
lpen <= (hc<10'd256 || vc>=9'd192)? {7'b0000000,index[0]} : (hc[8:1] ^ 8'h80); // fast way to add 128 to hc[8:1]
hpen <= (screen_off == 1'b1)? 8'd192 : hpen_internal;
end
end
//////////////////////////////////////////////////////////////////////////
// CPU memory address and control signal generation
@ -437,8 +411,11 @@ module asic (
else if (mreq_n == 1'b0 && cpuaddr>=16'hC000 && rom_in_section_d==1'b1) begin
romcs_n = 1'b0;
end
else if (mreq_n == 1'b0 /*&& (contention == 1'b0 || fetching_pixels == 1'b0)*/ ) begin
ramcs_n = 1'b0;
else if (mreq_n == 1'b0) begin
if (cpuaddr >= 16'h8000 && external_memory == 1'b1) // disable internal RAM if bit 7 HMPR is set
ramcs_n = 1'b1;
else
ramcs_n = 1'b0;
end
end
@ -476,11 +453,7 @@ module asic (
// Write to IO ports from CPU
always @(posedge clk) begin
if (rst_n == 1'b0) begin
`ifdef SYNTH
vmpr <= 8'h00;
`else
vmpr <= 8'b01100000;
`endif
lmpr <= 8'h00;
hmpr <= 8'h00;
border <= 8'h00;
@ -512,7 +485,7 @@ module asic (
if (iorq_n == 1'b0 && rd_n == 1'b0) begin
data_enable_n = 1'b0;
if (cpuaddr[7:0] == IOADDR_BORDER)
data_to_cpu = {1'b0, ear, 1'b0, keyboard[4:0]};
data_to_cpu = {screen_off, ear, 1'b0, keyboard[4:0]};
else if (cpuaddr[7:0] == IOADDR_ATTRIB)
data_to_cpu = vram_byte3;
else if (cpuaddr[7:0] == IOADDR_STATUS)

View File

@ -0,0 +1,101 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 04:04:00 04/01/2012
// Design Name:
// Module Name: sigma_delta_dac
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
`define MSBI 8 // Most significant Bit of DAC input
//This is a Delta-Sigma Digital to Analog Converter
module dac (DACout, DACin, Clk, Reset);
output DACout; // This is the average output that feeds low pass filter
input [`MSBI:0] DACin; // DAC input (excess 2**MSBI)
input Clk;
input Reset;
reg DACout; // for optimum performance, ensure that this ff is in IOB
reg [`MSBI+2:0] DeltaAdder; // Output of Delta adder
reg [`MSBI+2:0] SigmaAdder; // Output of Sigma adder
reg [`MSBI+2:0] SigmaLatch = 1'b1 << (`MSBI+1); // 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 mixer (
input wire clk,
input wire rst_n,
input wire ear,
input wire mic,
input wire spk,
input wire [7:0] saa_left,
input wire [7:0] saa_right,
output wire audio_left,
output wire audio_right
);
reg [6:0] beeper;
always @* begin
beeper = 7'd0;
if (ear == 1'b1)
beeper = beeper + 7'd38; // 30% of total output
if (mic == 1'b1)
beeper = beeper + 7'd38; // 30% of total output
if (spk == 1'b1)
beeper = beeper + 7'd51; // 40% of total output
end
wire [8:0] next_sample_l = beeper + saa_left;
wire [8:0] next_sample_r = beeper + saa_right;
reg [8:0] sample_l, sample_r;
always @(posedge clk) begin
sample_l <= next_sample_l;
sample_r <= next_sample_r;
end
dac audio_dac_left (
.DACout(audio_left),
.DACin(sample_l),
.Clk(clk),
.Reset(~rst_n)
);
dac audio_dac_right (
.DACout(audio_right),
.DACin(sample_r),
.Clk(clk),
.Reset(~rst_n)
);
endmodule

View File

@ -0,0 +1,256 @@
00
05
08
0B
0E
10
13
15
18
1A
1C
1E
20
22
24
26
28
2A
2C
2E
2F
31
33
35
36
38
3A
3B
3D
3F
40
42
44
45
47
48
4A
4B
4D
4F
50
52
53
55
56
57
59
5A
5C
5D
5F
60
62
63
64
66
67
69
6A
6B
6D
6E
6F
71
72
73
75
76
77
79
7A
7B
7D
7E
7F
81
82
83
84
86
87
88
89
8B
8C
8D
8E
90
91
92
93
95
96
97
98
9A
9B
9C
9D
9E
A0
A1
A2
A3
A4
A6
A7
A8
A9
AA
AB
AD
AE
AF
B0
B1
B2
B4
B5
B6
B7
B8
B9
BA
BC
BD
BE
BF
C0
C1
C2
C4
C5
C6
C7
C8
C9
CA
CB
CC
CE
CF
D0
D1
D2
D3
D4
D5
D6
D7
D9
DA
DB
DC
DD
DE
DF
E0
E1
E2
E3
E4
E5
E6
E8
E9
EA
EB
EC
ED
EE
EF
F0
F1
F2
F3
F4
F5
F6
F7
F8
F9
FA
FB
FC
FD
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF
FF

View File

@ -0,0 +1,27 @@
#include <stdio.h>
#include <math.h>
#define GAMMA 0.75
int main()
{
FILE *f;
int i,v;
double x;
f = fopen ("compressor_lut.hex", "wt");
for (i=0;i<256;i++)
{
if (i<=186)
{
x = i/186.0;
v = 255*pow(x,GAMMA);
}
else
v = 255;
printf ("%4d -> %4d\n", i, v);
fprintf (f, "%.2X\n", v);
}
fclose (f);
return 0;
}

View File

@ -3,14 +3,14 @@
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
// Engineer: Miguel Angel Rodriguez Jodar
//
// Create Date: 15:18:53 06/03/2015
// Design Name:
// Module Name: ps2_keyb
// Project Name:
// Target Devices:
// Tool versions:
// Create Date: 15:18:53 03/06/2015
// Design Name: SAM Coupé clone
// Module Name: ps2_keyb
// Project Name: SAM Coupé clone
// Target Devices: Spartan 6
// Tool versions: ISE 12.4
// Description:
//
// Dependencies:

View File

@ -74,10 +74,11 @@ module relojes
// Clock out ports
output wire CLK_OUT1,
output wire CLK_OUT2,
output wire CLK_OUT3
output wire CLK_OUT3,
output wire CLK_OUT4
);
wire clkin1, clkout0, clkout1, clkout2;
wire clkin1, clkout0, clkout1, clkout2, clkout3;
// Input buffering
//------------------------------------
@ -95,7 +96,6 @@ module relojes
wire drdy_unused;
wire locked_unused;
wire clkfbout;
wire clkout3_unused;
wire clkout4_unused;
wire clkout5_unused;
@ -114,7 +114,10 @@ module relojes
.CLKOUT1_DUTY_CYCLE (0.500),
.CLKOUT2_DIVIDE (100),
.CLKOUT2_PHASE (0.000),
.CLKOUT2_DUTY_CYCLE (0.500),
.CLKOUT3_DUTY_CYCLE (0.500),
.CLKOUT3_DIVIDE (75),
.CLKOUT3_PHASE (0.000),
.CLKOUT3_DUTY_CYCLE (0.500),
.CLKIN_PERIOD (20.0),
.REF_JITTER (0.010))
pll_base_inst
@ -123,7 +126,7 @@ module relojes
.CLKOUT0 (clkout0),
.CLKOUT1 (clkout1),
.CLKOUT2 (clkout2),
.CLKOUT3 (clkout3_unused),
.CLKOUT3 (clkout3),
.CLKOUT4 (clkout4_unused),
.CLKOUT5 (clkout5_unused),
.LOCKED (locked_unused),
@ -141,7 +144,6 @@ module relojes
(.O (CLK_OUT1),
.I (clkout0));
BUFG clkout2_buf
(.O (CLK_OUT2),
.I (clkout1));
@ -150,6 +152,8 @@ module relojes
(.O (CLK_OUT3),
.I (clkout2));
BUFG clkout4_buf
(.O (CLK_OUT4),
.I (clkout3));
endmodule

645
cores/SamCoupe/saa1099.v Normal file
View File

@ -0,0 +1,645 @@
`timescale 1ns / 1ps
`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer: Miguel Angel Rodriguez Jodar
//
// Create Date: 17:20:11 08/09/2015
// Design Name: SAM Coupé clone
// Module Name: saa1099
// Project Name: SAM Coupé clone
// Target Devices: Spartan 6
// Tool versions: ISE 12.4
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module saa1099 (
input wire clk, // 8 MHz
input wire rst_n,
input wire cs_n,
input wire a0, // 0=data, 1=address
input wire wr_n,
input wire [7:0] din,
output wire [7:0] out_l,
output wire [7:0] out_r
);
// DTACK is not implemented. Sorry about that
reg [7:0] amplit0, amplit1, amplit2, amplit3, amplit4, amplit5;
reg [8:0] freq0, freq1, freq2, freq3, freq4, freq5;
reg [7:0] oct10, oct32, oct54;
reg [7:0] freqenable;
reg [7:0] noiseenable;
reg [7:0] noisegen;
reg [7:0] envelope0, envelope1;
reg [7:0] ctrl; // frequency reset and sound enable for all channels
reg [4:0] addr; // holds the address of the register to write to
// Write values into internal registers
always @(posedge clk) begin
if (rst_n == 1'b0) begin
ctrl <= 8'h00;
end
else begin
if (cs_n == 1'b0 && wr_n == 1'b0) begin
if (a0 == 1'b1)
addr <= din[4:0];
else begin
case (addr)
5'h00: amplit0 <= din;
5'h01: amplit1 <= din;
5'h02: amplit2 <= din;
5'h03: amplit3 <= din;
5'h04: amplit4 <= din;
5'h05: amplit5 <= din;
5'h08: freq0 <= 9'd510 - {1'b0, din};
5'h09: freq1 <= 9'd510 - {1'b0, din};
5'h0A: freq2 <= 9'd510 - {1'b0, din};
5'h0B: freq3 <= 9'd510 - {1'b0, din};
5'h0C: freq4 <= 9'd510 - {1'b0, din};
5'h0D: freq5 <= 9'd510 - {1'b0, din};
5'h10: oct10 <= din;
5'h11: oct32 <= din;
5'h12: oct54 <= din;
5'h14: freqenable <= din;
5'h15: noiseenable <= din;
5'h16: noisegen <= din;
5'h18: envelope0 <= din;
5'h19: envelope1 <= din;
5'h1C: ctrl <= din;
endcase
end
end
end
end
wire gen0_tone;
wire gen1_tone;
wire gen2_tone;
wire gen3_tone;
wire gen4_tone;
wire gen5_tone;
wire pulse_to_noise0, pulse_to_envelope0;
wire pulse_to_noise1, pulse_to_envelope1;
wire noise0, noise1;
wire [4:0] mixout0_l, mixout0_r;
wire [4:0] mixout1_l, mixout1_r;
wire [4:0] mixout2_l, mixout2_r;
wire [4:0] mixout2_l_with_env, mixout2_r_with_env;
wire [4:0] mixout3_l, mixout3_r;
wire [4:0] mixout4_l, mixout4_r;
wire [4:0] mixout5_l, mixout5_r;
wire [4:0] mixout5_l_with_env, mixout5_r_with_env;
// Frequency and noise generators, top half
saa1099_tone_gen freq_gen0 (
.clk(clk),
.octave(oct10[2:0]),
.freq(freq0),
.out(gen0_tone),
.pulseout(pulse_to_noise0)
);
saa1099_tone_gen freq_gen1 (
.clk(clk),
.octave(oct10[6:4]),
.freq(freq1),
.out(gen1_tone),
.pulseout(pulse_to_envelope0)
);
saa1099_tone_gen freq_gen2 (
.clk(clk),
.octave(oct32[2:0]),
.freq(freq2),
.out(gen2_tone),
.pulseout()
);
saa1099_noise_gen noise_gen0 (
.clk(clk),
.rst_n(rst_n),
.pulse_from_gen(pulse_to_noise0),
.noise_freq(noisegen[1:0]),
.out(noise0)
);
// Frequency and noise generators, bottom half
saa1099_tone_gen freq_gen3 (
.clk(clk),
.octave(oct32[6:4]),
.freq(freq3),
.out(gen3_tone),
.pulseout(pulse_to_noise1)
);
saa1099_tone_gen freq_gen4 (
.clk(clk),
.octave(oct54[2:0]),
.freq(freq4),
.out(gen4_tone),
.pulseout(pulse_to_envelope1)
);
saa1099_tone_gen freq_gen5 (
.clk(clk),
.octave(oct54[6:4]),
.freq(freq5),
.out(gen5_tone),
.pulseout()
);
saa1099_noise_gen noise_gen1 (
.clk(clk),
.rst_n(rst_n),
.pulse_from_gen(pulse_to_noise1),
.noise_freq(noisegen[5:4]),
.out(noise1)
);
// Mixers
sa1099_mixer_and_amplitude mixer0 (
.clk(clk),
.en_tone(freqenable[0] == 1'b1 && noisegen[1:0] != 2'd3), // if gen0 is being used to generate noise, don't use this channel for tone output
.en_noise(noiseenable[0]),
.tone(gen0_tone),
.noise(noise0),
.amplitude_l(amplit0[3:0]),
.amplitude_r(amplit0[7:4]),
.out_l(mixout0_l),
.out_r(mixout0_r)
);
sa1099_mixer_and_amplitude mixer1 (
.clk(clk),
.en_tone(freqenable[1] == 1'b1 && envelope0[7] == 1'b0),
.en_noise(noiseenable[1]),
.tone(gen1_tone),
.noise(noise0),
.amplitude_l(amplit1[3:0]),
.amplitude_r(amplit1[7:4]),
.out_l(mixout1_l),
.out_r(mixout1_r)
);
sa1099_mixer_and_amplitude mixer2 (
.clk(clk),
.en_tone(freqenable[2]),
.en_noise(noiseenable[2]),
.tone(gen2_tone),
.noise(noise0),
.amplitude_l(amplit2[3:0]),
.amplitude_r(amplit2[7:4]),
.out_l(mixout2_l),
.out_r(mixout2_r)
);
sa1099_mixer_and_amplitude mixer3 (
.clk(clk),
.en_tone(freqenable[3] == 1'b1 && noisegen[5:4] != 2'd3), // if gen3 is being used to generate noise, don't use this channel for tone output
.en_noise(noiseenable[3]),
.tone(gen3_tone),
.noise(noise1),
.amplitude_l(amplit3[3:0]),
.amplitude_r(amplit3[7:4]),
.out_l(mixout3_l),
.out_r(mixout3_r)
);
sa1099_mixer_and_amplitude mixer4 (
.clk(clk),
.en_tone(freqenable[4] == 1'b1 && envelope1[7] == 1'b0),
.en_noise(noiseenable[4]),
.tone(gen4_tone),
.noise(noise1),
.amplitude_l(amplit4[3:0]),
.amplitude_r(amplit4[7:4]),
.out_l(mixout4_l),
.out_r(mixout4_r)
);
sa1099_mixer_and_amplitude mixer5 (
.clk(clk),
.en_tone(freqenable[5]),
.en_noise(noiseenable[5]),
.tone(gen5_tone),
.noise(noise1),
.amplitude_l(amplit5[3:0]),
.amplitude_r(amplit5[7:4]),
.out_l(mixout5_l),
.out_r(mixout5_r)
);
// Envelope generators
saa1099_envelope_gen envelope_gen0 (
.clk(clk),
.rst_n(rst_n),
.envreg(envelope0),
.write_to_envreg_addr(cs_n == 1'b0 && wr_n == 1'b0 && a0 == 1'b1 && din[4:0] == 5'h18),
.write_to_envreg_data(cs_n == 1'b0 && wr_n == 1'b0 && a0 == 1'b0 && addr == 5'h18),
.pulse_from_tonegen(pulse_to_envelope0),
.tone_en(freqenable[2]),
.noise_en(noiseenable[2]),
.sound_in_left(mixout2_l),
.sound_in_right(mixout2_r),
.sound_out_left(mixout2_l_with_env),
.sound_out_right(mixout2_r_with_env)
);
saa1099_envelope_gen envelope_gen1 (
.clk(clk),
.rst_n(rst_n),
.envreg(envelope1),
.write_to_envreg_addr(cs_n == 1'b0 && wr_n == 1'b0 && a0 == 1'b1 && din[4:0] == 5'h19),
.write_to_envreg_data(cs_n == 1'b0 && wr_n == 1'b0 && a0 == 1'b0 && addr == 5'h19),
.pulse_from_tonegen(pulse_to_envelope1),
.tone_en(freqenable[5]),
.noise_en(noiseenable[5]),
.sound_in_left(mixout5_l),
.sound_in_right(mixout5_r),
.sound_out_left(mixout5_l_with_env),
.sound_out_right(mixout5_r_with_env)
);
// Final mix
saa1099_output_mixer outmix_left (
.clk(clk),
.sound_enable(ctrl[0]),
.i0(mixout0_l),
.i1(mixout1_l),
.i2(mixout2_l_with_env),
.i3(mixout3_l),
.i4(mixout4_l),
.i5(mixout5_l_with_env),
.o(out_l)
);
saa1099_output_mixer outmix_right (
.clk(clk),
.sound_enable(ctrl[0]),
.i0(mixout0_r),
.i1(mixout1_r),
.i2(mixout2_r_with_env),
.i3(mixout3_r),
.i4(mixout4_r),
.i5(mixout5_r_with_env),
.o(out_r)
);
endmodule
module saa1099_tone_gen (
input wire clk,
input wire [2:0] octave,
input wire [8:0] freq,
output reg out,
output reg pulseout
);
reg [7:0] fcounter;
always @* begin
case (octave)
3'd0: fcounter = 8'd255;
3'd1: fcounter = 8'd127;
3'd2: fcounter = 8'd63;
3'd3: fcounter = 8'd31;
3'd4: fcounter = 8'd15;
3'd5: fcounter = 8'd7;
3'd6: fcounter = 8'd3;
3'd7: fcounter = 8'd1;
endcase
end
reg [7:0] count = 8'd0;
always @(posedge clk) begin
if (count == fcounter)
count <= 8'd0;
else
count <= count + 1;
end
reg pulse;
always @* begin
if (count == fcounter)
pulse = 1'b1;
else
pulse = 1'b0;
end
initial out = 1'b0;
reg [8:0] cfinal = 9'd0;
always @(posedge clk) begin
if (pulse == 1'b1) begin
if (cfinal == freq) begin
cfinal <= 9'd0;
out <= ~out;
end
else
cfinal <= cfinal + 1;
end
end
always @* begin
if (pulse == 1'b1 && cfinal == freq)
pulseout = 1'b1;
else
pulseout = 1'b0;
end
endmodule
module saa1099_noise_gen (
input wire clk,
input wire rst_n,
input wire pulse_from_gen,
input wire [1:0] noise_freq,
output wire out
);
reg [10:0] fcounter;
always @* begin
case (noise_freq)
2'd0: fcounter = 11'd255;
2'd1: fcounter = 11'd511;
2'd2: fcounter = 11'd1023;
default: fcounter = 11'd2047; // actually not used
endcase
end
reg [10:0] count = 11'd0;
always @(posedge clk) begin
if (count == fcounter)
count <= 11'd0;
else
count <= count + 1;
end
reg [30:0] lfsr = 31'h11111111;
always @(posedge clk) begin
if (rst_n == 1'b0)
lfsr <= 31'h11111111; // just a seed
if ((noise_freq == 2'd3 && pulse_from_gen == 1'b1) ||
(noise_freq != 2'd3 && count == fcounter)) begin
if ((lfsr[2] ^ lfsr[30]) == 1'b1)
lfsr <= {lfsr[29:0], 1'b1};
else
lfsr <= {lfsr[29:0], 1'b0};
end
end
assign out = lfsr[0];
endmodule
module sa1099_mixer_and_amplitude (
input wire clk,
input wire en_tone,
input wire en_noise,
input wire tone,
input wire noise,
input wire [3:0] amplitude_l,
input wire [3:0] amplitude_r,
output reg [4:0] out_l,
output reg [4:0] out_r
);
reg [4:0] next_out_l, next_out_r;
always @* begin
next_out_l = 5'b0000;
next_out_r = 5'b0000;
if (en_tone == 1'b1)
if (tone == 1'b1) begin
next_out_l = next_out_l + {1'b0, amplitude_l};
next_out_r = next_out_r + {1'b0, amplitude_r};
end
if (en_noise == 1'b1)
if (noise == 1'b1) begin
next_out_l = next_out_l + {1'b0, amplitude_l};
next_out_r = next_out_r + {1'b0, amplitude_r};
end
end
always @(posedge clk) begin
out_l <= next_out_l;
out_r <= next_out_r;
end
endmodule
module saa1099_envelope_gen (
input wire clk,
input wire rst_n,
input wire [7:0] envreg,
input wire write_to_envreg_addr,
input wire write_to_envreg_data,
input wire pulse_from_tonegen,
input wire tone_en,
input wire noise_en,
input wire [4:0] sound_in_left,
input wire [4:0] sound_in_right,
output wire [4:0] sound_out_left,
output wire [4:0] sound_out_right
);
reg [3:0] envelopes[0:511];
integer i;
initial begin
// Generating envelopes
// 0 0 0 : ______________
for (i=0;i<64;i=i+1)
envelopes[{3'b000,i[5:0]}] = 4'd0;
// 0 0 1 : --------------
for (i=0;i<64;i=i+1)
envelopes[{3'b001,i[5:0]}] = 4'd15;
// 0 1 0 : \_____________
for (i=0;i<16;i=i+1)
envelopes[{3'b010,i[5:0]}] = ~i[3:0];
for (i=16;i<64;i=i+1)
envelopes[{3'b010,i[5:0]}] = 4'd0;
// 0 1 1 : \|\|\|\|\|\|\|\
for (i=0;i<64;i=i+1)
envelopes[{3'b011,i[5:0]}] = ~i[3:0];
// 1 0 0 : /\______________
for (i=0;i<16;i=i+1)
envelopes[{3'b100,i[5:0]}] = i[3:0];
for (i=16;i<32;i=i+1)
envelopes[{3'b100,i[5:0]}] = ~i[3:0];
for (i=32;i<64;i=i+1)
envelopes[{3'b100,i[5:0]}] = 4'd0;
// 1 0 1 : /\/\/\/\/\/\/\/\
for (i=0;i<16;i=i+1)
envelopes[{3'b101,i[5:0]}] = i[3:0];
for (i=16;i<32;i=i+1)
envelopes[{3'b101,i[5:0]}] = ~i[3:0];
for (i=32;i<48;i=i+1)
envelopes[{3'b101,i[5:0]}] = i[3:0];
for (i=48;i<64;i=i+1)
envelopes[{3'b101,i[5:0]}] = ~i[3:0];
// 1 1 0 : /|________________
for (i=0;i<16;i=i+1)
envelopes[{3'b110,i[5:0]}] = i[3:0];
for (i=16;i<64;i=i+1)
envelopes[{3'b110,i[5:0]}] = 4'd0;
// 1 1 1 : /|/|/|/|/|/|/|/|/|
for (i=0;i<64;i=i+1)
envelopes[{3'b111,i[5:0]}] = i[3:0];
end
reg write_to_address_prev = 1'b0;
wire write_to_address_edge = (~write_to_address_prev & write_to_envreg_addr);
reg write_to_data_prev = 1'b0;
wire write_to_data_edge = (~write_to_data_prev & write_to_envreg_data);
reg [2:0] envshape = 3'b000;
reg stereoshape = 1'b0;
reg envclock = 1'b0;
wire env_enable = envreg[7];
wire env_resolution = envreg[4];
reg pending_data = 1'b0;
reg [5:0] envcounter = 6'd0;
always @(posedge clk) begin
if (rst_n == 1'b0) begin
envcounter <= 6'd0;
stereoshape <= 1'b0;
envshape <= 3'b000;
envclock <= 1'b0;
write_to_address_prev = 1'b0;
write_to_data_prev = 1'b0;
pending_data <= 1'b0;
end
else begin
write_to_address_prev <= write_to_envreg_addr;
write_to_data_prev <= write_to_envreg_data;
if (write_to_data_edge == 1'b1)
pending_data <= 1'b1;
if (env_enable == 1'b1) begin
if (envclock == 1'b0 && pulse_from_tonegen == 1'b1 || envclock == 1'b1 && write_to_address_edge == 1'b1) begin // pulse from internal or external clock?
if (envcounter == 6'd63)
envcounter <= 6'd32;
else begin
if (env_resolution == 1'b0)
envcounter <= envcounter + 1;
else
envcounter <= envcounter + 2;
end
if (envcounter == 6'd0 ||
envcounter >= 6'd15 && (envshape == 3'b000 || envshape == 3'b010 || envshape == 3'b110) ||
envcounter[3:0] == 4'd15 && (envshape == 3'b001 || envshape == 3'b011 || envshape == 3'b111) ||
envcounter >= 6'd31 && envshape == 3'b100 ||
envcounter[4:0] == 5'd31 && envshape ==3'b101) begin // find out when to updated buffered values
if (pending_data == 1'b1) begin // if we reached one of the designated points (3) or (4) and there is pending data, load it
envshape <= envreg[3:1];
stereoshape <= envreg[0];
envclock <= envreg[5];
envcounter <= 6'd0;
pending_data <= 1'b0;
end
end
end
end
end
end
reg [3:0] envleft = 4'b0000;
wire [3:0] envright = (stereoshape == 1'b0)? envleft : ~envleft; // bit 0 of envreg inverts envelope shape
always @(posedge clk)
envleft <= envelopes[{envshape,envcounter}]; // take current envelope from envelopes ROM
wire [4:0] temp_out_left, temp_out_right;
saa1099_amp_env_mixer modulate_left (
.a(sound_in_left),
.b(envleft),
.o(temp_out_left)
);
saa1099_amp_env_mixer modulate_right (
.a(sound_in_right),
.b(envright),
.o(temp_out_right)
);
assign sound_out_left = (env_enable == 1'b0)? sound_in_left : // if envelopes are not enabled, just bypass them
(env_enable == 1'b1 && tone_en == 1'b0 && noise_en == 1'b0)? {envleft, envleft[3]} : // if tone and noise are off, output is envelope signal itself
temp_out_left; // else it is original signal modulated by envelope
assign sound_out_right = (env_enable == 1'b0)? sound_in_right :
(env_enable == 1'b1 && tone_en == 1'b0 && noise_en == 1'b0)? {envright, envright[3]} :
temp_out_right;
endmodule
module saa1099_amp_env_mixer (
input wire [4:0] a, // amplitude
input wire [3:0] b, // envelope
output wire [4:0] o // output
);
wire [6:0] res1 = ((b[0] == 1'b1)? a : 5'h00) + ((b[1] == 1'b1)? {a,1'b0} : 6'h00);
wire [8:0] res2 = ((b[2] == 1'b1)? {a,2'b00} : 7'h00) + ((b[3] == 1'b1)? {a,3'b000} : 8'h00);
wire [8:0] res3 = res1 + res2;
assign o = res3[8:4];
endmodule
module saa1099_output_mixer (
input wire clk,
input wire sound_enable,
input wire [4:0] i0,
input wire [4:0] i1,
input wire [4:0] i2,
input wire [4:0] i3,
input wire [4:0] i4,
input wire [4:0] i5,
output reg [7:0] o
);
reg [7:0] compressor_table[0:255];
initial begin
$readmemh ("compressor_lut.hex", compressor_table);
end
reg [7:0] mix;
always @* begin
if (sound_enable == 1'b1)
mix = i0 + i1 + i2 + i3 + i4 + i5;
else
mix = 8'd0;
end
always @(posedge clk) begin
o <= compressor_table[mix];
end
endmodule

View File

@ -3,14 +3,14 @@
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
// Engineer: Miguel Angel Rodriguez Jodar
//
// Create Date: 03:54:40 07/25/2015
// Design Name:
// Module Name: samcoupe
// Project Name:
// Target Devices:
// Tool versions:
// Create Date: 03:54:40 13/25/2015
// Design Name: SAM Coupé clone
// Module Name: samcoupe
// Project Name: SAM Coupé clone
// Target Devices: Spartan 6
// Tool versions: ISE 12.4
// Description:
//
// Dependencies:
@ -24,6 +24,7 @@ module samcoupe (
input wire clk24,
input wire clk12,
input wire clk6,
input wire clk8,
input wire master_reset_n,
// Video output
output wire [1:0] r,
@ -82,8 +83,7 @@ module samcoupe (
// Audio signals
wire mic, beep;
assign audio_out_left = ear;
assign audio_out_right = beep;
wire [7:0] saa_out_l, saa_out_r;
// MUX from memory/devices to Z80 data bus
assign data_to_cpu = (rom_oe_n == 1'b0)? data_from_rom :
@ -158,30 +158,12 @@ module samcoupe (
.dout(data_from_rom)
);
// ram_dual_port_turnos ram_512k (
// .clk(clk24),
// .whichturn(asic_is_using_ram),
// .vramaddr(vramaddr),
// .cpuramaddr(cpuramaddr),
// .cpu_we_n(ram_we_n),
// .data_from_cpu(data_from_cpu),
// .data_to_asic(data_to_asic),
// .data_to_cpu(data_from_ram),
// // Actual interface with SRAM
// .sram_a(sram_addr),
// .sram_we_n(sram_we_n),
// .sram_d(sram_data)
// );
ram_dual_port ram_512k (
ram_dual_port_turnos ram_512k (
.clk(clk24),
.whichturn(asic_is_using_ram),
.vramaddr(vramaddr),
.cpuramaddr(cpuramaddr),
.mreq_n(ram_oe_n),
.rd_n(rd_n),
.wr_n(ram_we_n),
.rfsh_n(rfsh_n),
.cpu_we_n(ram_we_n),
.data_from_cpu(data_from_cpu),
.data_to_asic(data_to_asic),
.data_to_cpu(data_from_ram),
@ -190,20 +172,25 @@ module samcoupe (
.sram_we_n(sram_we_n),
.sram_d(sram_data)
);
// ps2k el_teclado (
// .clk(clk6),
// .ps2clk(clkps2),
// .ps2data(dataps2),
// .rows(kbrows[7:0]),
// .cols(kbcolumns[4:0]),
// .joy(), // Implementación joystick kempston en teclado numerico
// .scancode(), // El scancode original desde el teclado
// .rst(kb_rst_n), // esto son salidas, no entradas
// .nmi(kb_nmi_n), // Señales de reset y NMI
// .mrst() // generadas por pulsaciones especiales del teclado
// );
// ram_dual_port ram_512k (
// .clk(clk24),
// .whichturn(asic_is_using_ram),
// .vramaddr(vramaddr),
// .cpuramaddr(cpuramaddr),
// .mreq_n(ram_oe_n),
// .rd_n(rd_n),
// .wr_n(ram_we_n),
// .rfsh_n(rfsh_n),
// .data_from_cpu(data_from_cpu),
// .data_to_asic(data_to_asic),
// .data_to_cpu(data_from_ram),
// // Actual interface with SRAM
// .sram_a(sram_addr),
// .sram_we_n(sram_we_n),
// .sram_d(sram_data)
// );
ps2_keyb el_teclado (
.clk(clk6),
.clkps2(clkps2),
@ -228,4 +215,28 @@ module samcoupe (
.kbstatus_dout(),
.oe_n_kbstatus()
);
saa1099 el_saa (
.clk(clk8), // 8 MHz
.rst_n(kb_rst_n),
.cs_n(~(cpuaddr[7:0] == 8'hFF && iorq_n == 1'b0)),
.a0(cpuaddr[8]), // 0=data, 1=address
.wr_n(wr_n),
.din(data_from_cpu),
.out_l(saa_out_l),
.out_r(saa_out_r)
);
mixer sam_audio_mixer (
.clk(clk8),
.rst_n(kb_rst_n),
.ear(ear),
.mic(mic),
.spk(beep),
.saa_left(saa_out_l),
.saa_right(saa_out_r),
.audio_left(audio_out_left),
.audio_right(audio_out_right)
);
endmodule

View File

@ -85,6 +85,14 @@
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
<file xil_pn:name="saa1099.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
<file xil_pn:name="audio_management.v" xil_pn:type="FILE_VERILOG">
<association xil_pn:name="BehavioralSimulation"/>
<association xil_pn:name="Implementation"/>
</file>
</files>
<properties>
@ -107,11 +115,11 @@
<property xil_pn:name="Bring Out Global Tristate Net as a Port" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Bus Delimiter" xil_pn:value="&lt;>" xil_pn:valueState="default"/>
<property xil_pn:name="Case" xil_pn:value="Maintain" xil_pn:valueState="default"/>
<property xil_pn:name="Case Implementation Style" xil_pn:value="None" xil_pn:valueState="default"/>
<property xil_pn:name="Case Implementation Style" xil_pn:value="Full-Parallel" xil_pn:valueState="non-default"/>
<property xil_pn:name="Change Device Speed To" xil_pn:value="-2" xil_pn:valueState="default"/>
<property xil_pn:name="Change Device Speed To Post Trace" xil_pn:value="-2" xil_pn:valueState="default"/>
<property xil_pn:name="Combinatorial Logic Optimization" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Compile EDK Simulation Library" xil_pn:value="true" xil_pn:valueState="non-default"/>
<property xil_pn:name="Compile EDK Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Compile SIMPRIM (Timing) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Compile UNISIM (Functional) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Compile XilinxCoreLib (CORE Generator) Simulation Library" xil_pn:value="true" xil_pn:valueState="default"/>
@ -129,7 +137,7 @@
<property xil_pn:name="Create Mask File" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Create ReadBack Data Files" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Cross Clock Analysis" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Custom Waveform Configuration File Behav" xil_pn:value="crono_samcoupe.wcfg" xil_pn:valueState="non-default"/>
<property xil_pn:name="Custom Waveform Configuration File Behav" xil_pn:value="crono_asic_syncs.wcfg" xil_pn:valueState="non-default"/>
<property xil_pn:name="DSP Utilization Ratio" xil_pn:value="100" xil_pn:valueState="default"/>
<property xil_pn:name="Delay Values To Be Read from SDF" xil_pn:value="Setup Time" xil_pn:valueState="default"/>
<property xil_pn:name="Device" xil_pn:value="xc6slx9" xil_pn:valueState="non-default"/>
@ -322,8 +330,8 @@
<property xil_pn:name="Run for Specified Time Translate" xil_pn:value="true" xil_pn:valueState="default"/>
<property xil_pn:name="Safe Implementation" xil_pn:value="No" xil_pn:valueState="default"/>
<property xil_pn:name="Security" xil_pn:value="Enable Readback and Reconfiguration" xil_pn:valueState="default"/>
<property xil_pn:name="Selected Module Instance Name" xil_pn:value="/tb_samcoupe" xil_pn:valueState="non-default"/>
<property xil_pn:name="Selected Simulation Root Source Node Behavioral" xil_pn:value="work.tb_samcoupe" xil_pn:valueState="non-default"/>
<property xil_pn:name="Selected Module Instance Name" xil_pn:value="/tb_asic" xil_pn:valueState="non-default"/>
<property xil_pn:name="Selected Simulation Root Source Node Behavioral" xil_pn:value="work.tb_asic" xil_pn:valueState="non-default"/>
<property xil_pn:name="Selected Simulation Root Source Node Post-Map" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Selected Simulation Root Source Node Post-Route" xil_pn:value="" xil_pn:valueState="default"/>
<property xil_pn:name="Selected Simulation Root Source Node Post-Translate" xil_pn:value="" xil_pn:valueState="default"/>
@ -341,7 +349,7 @@
<property xil_pn:name="Simulator" xil_pn:value="ISim (VHDL/Verilog)" xil_pn:valueState="default"/>
<property xil_pn:name="Slice Utilization Ratio" xil_pn:value="100" xil_pn:valueState="default"/>
<property xil_pn:name="Specify 'define Macro Name and Value" xil_pn:value="SIMUL=1" xil_pn:valueState="non-default"/>
<property xil_pn:name="Specify Top Level Instance Names Behavioral" xil_pn:value="work.tb_samcoupe" xil_pn:valueState="default"/>
<property xil_pn:name="Specify Top Level Instance Names Behavioral" xil_pn:value="work.tb_asic" xil_pn:valueState="default"/>
<property xil_pn:name="Specify Top Level Instance Names Post-Map" xil_pn:value="Default" xil_pn:valueState="default"/>
<property xil_pn:name="Specify Top Level Instance Names Post-Route" xil_pn:value="Default" xil_pn:valueState="default"/>
<property xil_pn:name="Specify Top Level Instance Names Post-Translate" xil_pn:value="Default" xil_pn:valueState="default"/>
@ -387,11 +395,11 @@
<property xil_pn:name="Wakeup Clock spartan6" xil_pn:value="Startup Clock" xil_pn:valueState="default"/>
<property xil_pn:name="Watchdog Timer Value spartan6" xil_pn:value="0xFFFF" xil_pn:valueState="default"/>
<property xil_pn:name="Working Directory" xil_pn:value="." xil_pn:valueState="non-default"/>
<property xil_pn:name="Write Timing Constraints" xil_pn:value="false" xil_pn:valueState="default"/>
<property xil_pn:name="Write Timing Constraints" xil_pn:value="true" xil_pn:valueState="non-default"/>
<!-- -->
<!-- The following properties are for internal use only. These should not be modified.-->
<!-- -->
<property xil_pn:name="PROP_BehavioralSimTop" xil_pn:value="Module|tb_samcoupe" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_BehavioralSimTop" xil_pn:value="Module|tb_asic" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_DesignName" xil_pn:value="samcoupe" xil_pn:valueState="non-default"/>
<property xil_pn:name="PROP_DevFamilyPMName" xil_pn:value="spartan6" xil_pn:valueState="default"/>
<property xil_pn:name="PROP_FPGAConfiguration" xil_pn:value="FPGAConfiguration" xil_pn:valueState="default"/>

View File

@ -51,10 +51,13 @@ module tb_asic;
.data_enable_n(),
.wait_n(),
// RAM/ROM interface
.ramaddr(),
.vramaddr(),
.cpuramaddr(),
.data_from_ram(8'hAA),
.ramwr_n(),
.romcs_n(),
.ramcs_n(),
.asic_is_using_ram(),
// audio I/O
.ear(1'b0),
.mic(),

View File

@ -59,20 +59,22 @@ module tld_sam (
assign stdn = 1'b0; // fijar norma PAL
assign stdnb = 1'b1; // y conectamos reloj PAL
wire clk24, clk12, clk6;
wire clk24, clk12, clk6, clk8;
relojes los_relojes (
.CLK_IN1 (clk50mhz), // IN
// Clock out ports
.CLK_OUT1 (clk24), // OUT
.CLK_OUT2 (clk12), // OUT
.CLK_OUT3 (clk6) // OUT
.CLK_OUT1 (clk24), // modulo multiplexor de SRAM
.CLK_OUT2 (clk12), // ASIC
.CLK_OUT3 (clk6), // CPU y teclado PS/2
.CLK_OUT4 (clk8) // SAA1099 y DAC
);
samcoupe maquina (
.clk24(clk24),
.clk12(clk12),
.clk6(clk6),
.clk8(clk8),
.master_reset_n(1'b1), // esta señal es sólo para simulación
// Video output
.r(sam_r),

View File

@ -34,7 +34,7 @@ module tv80_core (/*AUTOARG*/
// Beginning of automatic inputs (from unused autoinst inputs)
// End of automatics
parameter Mode = 1; // 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
parameter Mode = 0; // 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
parameter IOWait = 1; // 0 => Single cycle I/O, 1 => Std I/O cycle
parameter Flag_C = 0;
parameter Flag_N = 1;

View File

@ -102,80 +102,65 @@ module tv80n (/*AUTOARG*/
.intcycle_n (intcycle_n)
);
always @*
begin
nxt_mreq_n = 1;
nxt_rd_n = 1;
nxt_iorq_n = 1;
nxt_wr_n = 1;
if (mcycle[0])
begin
if (tstate[1] || tstate[2])
begin
nxt_rd_n = ~ intcycle_n;
nxt_mreq_n = ~ intcycle_n;
nxt_iorq_n = intcycle_n;
end
always @* begin
nxt_mreq_n = 1;
nxt_rd_n = 1;
nxt_iorq_n = 1;
nxt_wr_n = 1;
if (mcycle[0]) begin
if (tstate[1] || tstate[2]) begin
nxt_rd_n = ~ intcycle_n;
nxt_mreq_n = ~ intcycle_n;
nxt_iorq_n = intcycle_n;
end
end // if (mcycle[0])
else
begin
if ((tstate[1] || tstate[2]) && !no_read && !write)
begin
nxt_rd_n = 1'b0;
nxt_iorq_n = ~ iorq;
nxt_mreq_n = iorq;
end
if (T2Write == 0)
begin
if (tstate[2] && write)
begin
nxt_wr_n = 1'b0;
nxt_iorq_n = ~ iorq;
nxt_mreq_n = iorq;
else begin
if ((tstate[1] || tstate[2]) && !no_read && !write) begin
nxt_rd_n = 1'b0;
nxt_iorq_n = ~ iorq;
nxt_mreq_n = iorq;
end
if (T2Write == 0) begin
if (tstate[2] && write) begin
nxt_wr_n = 1'b0;
nxt_iorq_n = ~ iorq;
nxt_mreq_n = iorq;
end
end
else
begin
if ((tstate[1] || (tstate[2] && !wait_n)) && write)
begin
nxt_wr_n = 1'b0;
nxt_iorq_n = ~ iorq;
nxt_mreq_n = iorq;
end
end // else: !if(T2write == 0)
end // else: !if(mcycle[0])
else begin
if ((tstate[1] || (tstate[2] && !wait_n)) && write) begin
nxt_wr_n = 1'b0;
nxt_iorq_n = ~ iorq;
nxt_mreq_n = iorq;
end
end // else: !if(T2write == 0)
end // else: !if(mcycle[0])
end // always @ *
always @(negedge clk)
begin
if (!reset_n)
begin
rd_n <= #1 1'b1;
wr_n <= #1 1'b1;
iorq_n <= #1 1'b1;
mreq_n <= #1 1'b1;
always @(negedge clk) begin
if (!reset_n) begin
rd_n <= #1 1'b1;
wr_n <= #1 1'b1;
iorq_n <= #1 1'b1;
mreq_n <= #1 1'b1;
end
else
begin
rd_n <= #1 nxt_rd_n;
wr_n <= #1 nxt_wr_n;
iorq_n <= #1 nxt_iorq_n;
mreq_n <= #1 nxt_mreq_n;
end // else: !if(!reset_n)
else begin
rd_n <= #1 nxt_rd_n;
wr_n <= #1 nxt_wr_n;
iorq_n <= #1 nxt_iorq_n;
mreq_n <= #1 nxt_mreq_n;
end // else: !if(!reset_n)
end // always @ (posedge clk or negedge reset_n)
always @(posedge clk)
begin
if (!reset_n)
begin
di_reg <= #1 0;
always @(posedge clk) begin
if (!reset_n) begin
di_reg <= #1 0;
end
else
begin
if (tstate[2] && wait_n == 1'b1)
di_reg <= #1 di;
end // else: !if(!reset_n)
else begin
if (tstate[2] && wait_n == 1'b1)
di_reg <= #1 di;
end // else: !if(!reset_n)
end // always @ (posedge clk)
endmodule // t80n