URL
https://opencores.org/ocsvn/tv80/tv80/trunk
Subversion Repositories tv80
Compare Revisions
- This comparison shows the changes necessary to convert path
/tv80/trunk
- from Rev 88 to Rev 89
- ↔ Reverse comparison
Rev 88 → Rev 89
/rtl/core/tv80_reg.v
61,11 → 61,17
assign DOCL = RegsL[AddrC]; |
|
// break out ram bits for waveform debug |
// synopsys translate_off |
wire [7:0] B = RegsH[0]; |
wire [7:0] C = RegsL[0]; |
wire [7:0] D = RegsH[1]; |
wire [7:0] E = RegsL[1]; |
wire [7:0] H = RegsH[2]; |
wire [7:0] L = RegsL[2]; |
|
wire [15:0] IX = { RegsH[3], RegsL[3] }; |
wire [15:0] IY = { RegsH[7], RegsL[7] }; |
// synopsys translate_on |
|
// synopsys dc_script_begin |
// set_attribute current_design "revision" "$Id: tv80_reg.v,v 1.1 2004-05-16 17:39:57 ghutchis Exp $" -type string -quiet |
// synopsys dc_script_end |
endmodule |
|
/rtl/core/tv80s.v
24,7 → 24,7
|
module tv80s (/*AUTOARG*/ |
// Outputs |
m1_n, mreq_n, iorq_n, rd_n, wr_n, rfsh_n, halt_n, busak_n, A, do, |
m1_n, mreq_n, iorq_n, rd_n, wr_n, rfsh_n, halt_n, busak_n, A, dout, |
// Inputs |
reset_n, clk, wait_n, int_n, nmi_n, busrq_n, di |
); |
50,7 → 50,7
output busak_n; |
output [15:0] A; |
input [7:0] di; |
output [7:0] do; |
output [7:0] dout; |
|
reg mreq_n; |
reg iorq_n; |
89,13 → 89,13
.A (A), |
.dinst (di), |
.di (di_reg), |
.do (do), |
.dout (dout), |
.mc (mcycle), |
.ts (tstate), |
.intcycle_n (intcycle_n) |
); |
|
always @(posedge clk) |
always @(posedge clk or negedge reset_n) |
begin |
if (!reset_n) |
begin |
/rtl/core/tv80_core.v
24,7 → 24,7
|
module tv80_core (/*AUTOARG*/ |
// Outputs |
m1_n, iorq, no_read, write, rfsh_n, halt_n, busak_n, A, do, mc, ts, |
m1_n, iorq, no_read, write, rfsh_n, halt_n, busak_n, A, dout, mc, ts, |
intcycle_n, IntE, stop, |
// Inputs |
reset_n, clk, cen, wait_n, int_n, nmi_n, busrq_n, dinst, di |
60,7 → 60,7
output [15:0] A; |
input [7:0] dinst; |
input [7:0] di; |
output [7:0] do; |
output [7:0] dout; |
output [6:0] mc; |
output [6:0] ts; |
output intcycle_n; |
75,7 → 75,7
reg halt_n; |
reg busak_n; |
reg [15:0] A; |
reg [7:0] do; |
reg [7:0] dout; |
reg [6:0] mc; |
reg [6:0] ts; |
reg intcycle_n; |
370,7 → 370,7
Save_Mux = ALU_Q; |
end // always @ * |
|
always @ (posedge clk) |
always @ (posedge clk or negedge reset_n) |
begin |
if (reset_n == 1'b0 ) |
begin |
382,7 → 382,7
XY_State <= #1 2'b00; |
IStatus <= #1 2'b00; |
mcycles <= #1 3'b000; |
do <= #1 8'b00000000; |
dout <= #1 8'b00000000; |
|
ACC <= #1 8'hFF; |
F <= #1 8'hFF; |
457,6 → 457,7
else if (Halt_FF == 1'b1 || (IntCycle == 1'b1 && IStatus == 2'b10) || NMICycle == 1'b1 ) |
begin |
IR <= #1 8'b00000000; |
TmpAddr[7:0] <= #1 dinst; // Special M1 vector fetch |
end |
else |
begin |
804,16 → 805,16
|
if (tstate[1] && Auto_Wait_t1 == 1'b0 ) |
begin |
do <= #1 BusB; |
dout <= #1 BusB; |
if (I_RLD == 1'b1 ) |
begin |
do[3:0] <= #1 BusA[3:0]; |
do[7:4] <= #1 BusB[3:0]; |
dout[3:0] <= #1 BusA[3:0]; |
dout[7:4] <= #1 BusB[3:0]; |
end |
if (I_RRD == 1'b1 ) |
begin |
do[3:0] <= #1 BusB[7:4]; |
do[7:4] <= #1 BusA[3:0]; |
dout[3:0] <= #1 BusB[7:4]; |
dout[7:4] <= #1 BusA[3:0]; |
end |
end |
|
847,7 → 848,7
5'b10111 : |
ACC <= #1 Save_Mux; |
5'b10110 : |
do <= #1 Save_Mux; |
dout <= #1 Save_Mux; |
5'b11000 : |
SP[7:0] <= #1 Save_Mux; |
5'b11001 : |
1098,7 → 1099,7
// |
//------------------------------------------------------------------------- |
`ifdef TV80_REFRESH |
always @ (posedge clk) |
always @ (posedge clk or negedge reset_n) |
begin |
if (reset_n == 1'b0 ) |
begin |
1143,10 → 1144,9
// |
//----------------------------------------------------------------------- |
|
always @ (posedge clk) |
always @ (posedge clk or negedge reset_n) |
begin : sync_inputs |
|
if (reset_n == 1'b0 ) |
if (~reset_n) |
begin |
BusReq_s <= #1 1'b0; |
INT_s <= #1 1'b0; |
1178,7 → 1178,7
// |
//----------------------------------------------------------------------- |
|
always @ (posedge clk) |
always @ (posedge clk or negedge reset_n) |
begin |
if (reset_n == 1'b0 ) |
begin |
1206,9 → 1206,9
end |
else |
begin |
Auto_Wait_t1 <= #1 Auto_Wait || iorq_i; |
Auto_Wait_t1 <= #1 Auto_Wait || (iorq_i & ~Auto_Wait_t2); |
end |
Auto_Wait_t2 <= #1 Auto_Wait_t1; |
Auto_Wait_t2 <= #1 Auto_Wait_t1 & !T_Res; |
No_BTR <= #1 (I_BT && (~ IR[4] || ~ F[Flag_P])) || |
(I_BC && (~ IR[4] || F[Flag_Z] || ~ F[Flag_P])) || |
(I_BTR && (~ IR[4] || F[Flag_Z])); |
1216,7 → 1216,8
begin |
if (SetEI == 1'b1 ) |
begin |
IntE_FF1 <= #1 1'b1; |
if (!NMICycle) |
IntE_FF1 <= #1 1'b1; |
IntE_FF2 <= #1 1'b1; |
end |
if (I_RETN == 1'b1 ) |
1373,8 → 1374,5
end |
end // always @ * |
|
// synopsys dc_script_begin |
// set_attribute current_design "revision" "$Id: tv80_core.v,v 1.5 2005-01-26 18:55:47 ghutchis Exp $" -type string -quiet |
// synopsys dc_script_end |
endmodule // T80 |
|
/tests/bintr_crt0.asm
2,6 → 2,7
.module bintr_crt0 |
.globl _main |
.globl _isr |
.globl _nmi_isr |
|
.area _HEADER (ABS) |
;; Reset vector |
22,10 → 23,18
reti |
.org 0x38 |
di |
push af |
call _isr |
pop af |
ei |
reti |
|
.org 0x66 |
push af |
call _nmi_isr |
pop af |
retn |
|
.org 0x100 |
init: |
;; Stack at the top of memory. |
/tests/tv80_env.h
38,6 → 38,8
sfr at 0x92 cksum_accum; |
sfr at 0x93 inc_on_read; |
sfr at 0x94 randval; |
sfr at 0x95 nmi_cntdwn; |
sfr at 0xA0 nmi_trig_opcode; |
|
#define SC_TEST_PASSED 0x01 |
#define SC_TEST_FAILED 0x02 |
/tests/bintr.c
15,17 → 15,78
unsigned char foo; |
volatile unsigned char test_pass; |
static unsigned char triggers; |
int phase; |
char done; |
char nmi_trig; |
|
void nmi_isr (void) |
{ |
nmi_trig++; |
|
switch (phase) { |
// nmi test |
case 1 : |
if (nmi_trig > 5) { |
phase += 1; |
nmi_trig = 0; |
//intr_cntdwn = 255; |
//intr_cntdwn = 0; |
intr_cntdwn = 32; |
nmi_cntdwn = 0; |
} else |
nmi_cntdwn = 32; |
break; |
|
// just trigger once, and disable interrupt |
case 3 : |
nmi_cntdwn = 0; |
nmi_trig_opcode = 0; // pop AF opcode |
break; |
} |
} |
|
void isr (void) |
{ |
int i; |
triggers++; |
|
if (triggers > 5) { |
test_pass = 1; |
intr_cntdwn = 255; |
switch (phase) { |
// int test |
case 0 : |
if (triggers > 5) { |
phase += 1; |
triggers = 0; |
intr_cntdwn = 0; |
nmi_cntdwn = 64; |
} else { |
intr_cntdwn = 32; |
|
} |
break; |
|
|
// int / nmi interaction |
// in this phase set up interrupt call |
// which will be interrupted by an nmi |
case 2 : |
phase += 1; |
triggers = 0; |
nmi_trig = 0; |
intr_cntdwn = 20; |
nmi_trig_opcode = 0xF1; // pop AF opcode |
|
break; |
|
// wait for a while while servicing interrupt |
// nmi should interrupt us and increment nmi_trig |
// if test pass is true when we are done then exit |
case 3 : |
intr_cntdwn = 0; |
} else |
intr_cntdwn = 32; |
if (nmi_trig == 1) |
test_pass = 1; |
break; |
|
} |
} |
|
int main () |
35,12 → 96,19
|
test_pass = 0; |
triggers = 0; |
nmi_trig = 0; |
|
phase = 0; |
|
// start interrupt countdown |
intr_cntdwn = 64; |
set_timeout (50000); |
|
for (i=0; i<200; i++) |
for (i=0; i<1024; i++) { |
if (test_pass) |
break; |
check = sim_ctl_port; |
} |
|
if (test_pass) |
sim_ctl (SC_TEST_PASSED); |
/tests/Makefile
15,12 → 15,14
|
%.ihx : %.c |
$(CC) $^ |
rm -f $*.asm |
|
%.o : %.asm |
$(AS) -o $*.o $^ |
$(AS) -l -o $*.o $^ |
|
%.ihx : %.o |
$(LD) $(LINK_OPTIONS) $(AS_LINK_OPTIONS) -i $* $^ -e |
#$(LD) $(LINK_OPTIONS) $(AS_LINK_OPTIONS) -i $* $^ -e |
$(CC) $^ --no-std-crt0 bintr_crt0.o |
|
bintr.ihx : bintr.c bintr_crt0.o |
$(CC) --no-std-crt0 bintr.c bintr_crt0.o |
/scripts/run
36,7 → 36,7
if len(args) == 0: |
print_help() |
testname = args[0] |
simulator = "cver" |
simulator = "vcs +v2k -full64 -R -I +define+VCS=1 " |
|
filelist = " -f env/tb.vf" |
testdef = " +incdir+env -l logs/%s.log +define+DUMPFILE_NAME=\\\"logs/%s.dump\\\" +define+PROGRAM_FILE=\\\"tests/%s.vmem\\\"" % (testname, testname, testname) |
/scripts/run2
22,7 → 22,7
import sys, os |
|
testname = sys.argv[1] |
simulator = "cver" |
simulator = "vcs -full64 +v2k -R -I " |
|
filelist = " -f env/tb.vf" |
testdef = " +incdir+env -l logs/%s.log +define+DUMPFILE_NAME=\\\"logs/%s.dump\\\" +define+ROM_FILE=\\\"tests/%s.vmem\\\" +define+RAM_FILE=\\\"tests/%s.vmem\\\"" % (testname, testname, testname+"_rom", testname+"_ram") |
33,6 → 33,10
|
command = simulator + filelist + testdef |
|
# check for and create logs directory |
if (not os.path.exists ('logs')): |
os.mkdir ('logs') |
|
print "command:",command |
os.system (command) |
|
/env/tb.vf
7,6 → 7,7
* |
*/ |
|
env/tb_top.v |
rtl/core/tv80_alu.v |
rtl/core/tv80_mcode.v |
rtl/core/tv80_reg.v |
18,7 → 19,6
rtl/simple_gmii/sync2.v |
rtl/simple_gmii/ram_1r_1w.v |
rtl/uart/T16450.v |
env/tb_top.v |
env/env_io.v |
env/op_decode.v |
env/async_mem.v |
/env/env_tasks.v
23,8 → 23,13
begin |
if (!dumping) |
begin |
`ifdef VCS |
$vcdpluson; |
$vcdplusmemon; |
`else |
$dumpfile (`DUMPFILE_NAME); |
$dumpvars; |
`endif |
dumping = 1; |
end |
end |
32,7 → 37,12
|
task dumpoff; |
begin |
`ifdef VCS |
$vcdplusoff; |
$vcdplusmemoff; |
`else |
// ??? |
`endif |
end |
endtask // dumpoff |
|
/env/env_io.v
1,9 → 1,9
|
module env_io (/*AUTOARG*/ |
// Outputs |
DI, |
// Inouts |
DI, |
// Inputs |
clk, iorq_n, rd_n, wr_n, addr, DO |
clk, iorq_n, rd_n, wr_n, addr, D_OUT |
); |
|
input clk; |
11,7 → 11,7
input rd_n; |
input wr_n; |
input [7:0] addr; |
input [7:0] DO; |
input [7:0] D_OUT; |
inout [7:0] DI; |
|
reg [7:0] io_data; |
25,8 → 25,10
reg [15:0] max_timeout; |
|
reg [7:0] int_countdown; |
reg [7:0] nmi_countdown; |
reg [7:0] checksum; |
reg [7:0] ior_value; // increment-on-read value |
reg [7:0] nmi_trigger; // trigger nmi when IR = this value |
|
assign DI = (!iorq_n & !rd_n & io_cs) ? io_data : {8{1'bz}}; |
|
38,6 → 40,8
max_timeout = 10000; |
timeout_ctl = 1; |
int_countdown = 0; |
nmi_countdown = 0; |
nmi_trigger = 0; |
end |
|
always @* |
55,6 → 59,8
8'h91 : io_data = checksum; |
8'h93 : io_data = ior_value; |
8'h94 : io_data = {$random}; |
8'h95 : io_data = nmi_countdown[7:0]; |
8'hA0 : io_data = nmi_trigger; |
default : io_data = 8'hzz; |
endcase // case(addr) |
end // if (!iorq_n & !rd_n) |
72,10 → 78,18
case (addr) |
8'h80 : |
begin |
case (DO) |
1 : tb_top.test_pass; |
case (D_OUT) |
1 : |
begin |
$writememh ("test_output2.hex", tb_top.rom.mem); |
tb_top.test_pass; |
end |
|
2 : tb_top.test_fail; |
2 : |
begin |
$writememh ("test_output2.hex", tb_top.rom.mem); |
tb_top.test_fail; |
end |
|
3 : tb_top.dumpon; |
|
83,18 → 97,18
|
default : |
begin |
$display ("%t: ERROR : Unknown I/O command %x", $time, DO); |
$display ("%t: ERROR : Unknown I/O command %x", $time, D_OUT); |
end |
endcase // case(DO) |
endcase // case(D_OUT) |
end // case: :... |
|
8'h81 : |
begin |
str_buf[buf_ptr] = DO; |
str_buf[buf_ptr] = D_OUT; |
buf_ptr = buf_ptr + 1; |
|
//$display ("%t: DEBUG : Detected write of character %x", $time, DO); |
if (DO == 8'h0A) |
//$display ("%t: DEBUG : Detected write of character %x", $time, D_OUT); |
if (D_OUT == 8'h0A) |
begin |
$write ("%t: PROGRAM : ", $time); |
|
107,16 → 121,18
|
8'h82 : |
begin |
timeout_ctl = DO; |
timeout_ctl = D_OUT; |
end |
|
8'h83 : max_timeout[7:0] = DO; |
8'h84 : max_timeout[15:8] = DO; |
8'h83 : max_timeout[7:0] = D_OUT; |
8'h84 : max_timeout[15:8] = D_OUT; |
|
8'h90 : int_countdown = DO; |
8'h91 : checksum = DO; |
8'h92 : checksum = checksum + DO; |
8'h93 : ior_value = DO; |
8'h90 : int_countdown = D_OUT; |
8'h91 : checksum = D_OUT; |
8'h92 : checksum = checksum + D_OUT; |
8'h93 : ior_value = D_OUT; |
8'h95 : nmi_countdown[7:0] = D_OUT; |
8'hA0 : nmi_trigger = D_OUT; |
endcase // case(addr) |
end // always @ (posedge clk) |
|
136,10 → 152,14
|
always @(posedge clk) |
begin |
if (int_countdown == 1) |
if (int_countdown == 0) |
begin |
tb_top.int_n <= #1 1'b1; |
end |
else if (int_countdown == 1) |
begin |
tb_top.int_n <= #1 1'b0; |
int_countdown = 0; |
//int_countdown = 0; |
end |
else if (int_countdown > 1) |
begin |
146,6 → 166,36
int_countdown = int_countdown - 1; |
tb_top.int_n <= #1 1'b1; |
end |
|
// when nmi countdown reaches 1, an NMI will be issued. |
// to clear the interrupt, write nmi_countdown to 0. |
if ((nmi_countdown == 0) && (nmi_trigger == 0)) |
begin |
tb_top.nmi_n <= #1 1'b1; |
end |
else if (nmi_countdown == 1) |
begin |
tb_top.nmi_n <= #1 1'b0; |
end |
else if (nmi_countdown > 1) |
begin |
nmi_countdown = nmi_countdown - 1; |
tb_top.nmi_n <= #1 1'b1; |
end |
|
// when IR equals the target instruction, an NMI will be |
// issued. To clear the interrupt, write nmi_trigger to |
// zero. |
if (nmi_trigger != 0) |
begin |
if (nmi_trigger === tb_top.tv80s_inst.i_tv80_core.IR[7:0]) |
begin |
tb_top.nmi_n <= #80 0; |
tb_top.nmi_n <= #160 1; |
end |
end |
else if (nmi_countdown == 0) |
tb_top.nmi_n <= #1 1; |
end |
|
endmodule // env_io |
/env/tb_top.v
1,3 → 1,4
`timescale 1ns/100ps |
`define TV80_CORE_PATH tb_top.tv80s_inst.i_tv80_core |
|
module tb_top; |
18,7 → 19,7
wire busak_n; |
wire [15:0] A; |
wire [7:0] di; |
wire [7:0] do; |
wire [7:0] d_out; |
wire ram_rd_cs, ram_wr_cs, rom_rd_cs; |
reg tx_clk; |
|
54,7 → 55,7
.halt_n (halt_n), |
.busak_n (busak_n), |
.A (A[15:0]), |
.do (do[7:0]), |
.dout (d_out[7:0]), |
// Inputs |
.reset_n (reset_n), |
.clk (clk), |
70,7 → 71,7
.rd_data (di), |
// Inputs |
.wr_clk (clk), |
.wr_data (do), |
.wr_data (d_out), |
.wr_cs (ram_wr_cs), |
.addr (A[14:0]), |
.rd_cs (ram_rd_cs)); |
96,7 → 97,7
.rd_n (rd_n), |
.wr_n (wr_n), |
.addr (A[7:0]), |
.DO (do[7:0])); |
.D_OUT (d_out[7:0])); |
|
//---------------------------------------------------------------------- |
// UART |
105,7 → 106,7
wire uart_cs_n; |
wire [7:0] uart_rd_data; |
|
wire sin; |
wire ser_in; |
wire cts_n; |
wire dsr_n; |
wire ri_n; |
123,7 → 124,7
|
assign uart_cs_n = ~(!iorq_n & (A[7:3] == 5'h3)); |
assign di = (!uart_cs_n & !rd_n) ? uart_rd_data : 8'bz; |
assign sin = sout; |
assign ser_in = sout; |
|
T16450 uart0 |
(.reset_n (reset_n), |
133,9 → 134,9
.rd_n (rd_n), |
.wr_n (wr_n), |
.addr (A[2:0]), |
.wr_data (do), |
.wr_data (d_out), |
.rd_data (uart_rd_data), |
.sin (sin), |
.sin (ser_in), |
.cts_n (cts_n), |
.dsr_n (dsr_n), |
.ri_n (ri_n), |
190,7 → 191,7
.rd_n (rd_n), |
.wr_n (wr_n), |
.addr (A[15:0]), |
.wr_data (do)); |
.wr_data (d_out)); |
|
//---------------------------------------------------------------------- |
// Global Initialization |