Add irq status register

Upon receiving an interrupt, the corresponding bit in the interrupt
status register will be set and an IRQ will be raised for the CPU. The
cpu can then respond to the interrupt and clear the interrupt by writing
back to the interrupt status register.
This commit is contained in:
Byron Lathi
2022-03-14 13:16:09 -05:00
parent 26070313f4
commit e70fffb472
5 changed files with 126 additions and 4 deletions

View File

@@ -3,12 +3,14 @@ module addr_decode(
output logic ram_cs,
output logic rom_cs,
output logic hex_cs,
output logic uart_cs
output logic uart_cs,
output logic irq_cs
);
assign rom_cs = addr[15];
assign ram_cs = ~addr[15] && addr < 16'h7ff0;
assign hex_cs = addr >= 16'h7ff0 && addr < 16'h7ff4;
assign uart_cs = addr >= 16'h7ff4 && addr < 16'h7ff6;
assign irq_cs = addr == 16'h7fff;
endmodule

View File

@@ -9,6 +9,7 @@ logic ram_cs;
logic rom_cs;
logic hex_cs;
logic uart_cs;
logic irq_cs;
int cs_count = ram_cs + rom_cs + hex_cs + uart_cs;
@@ -32,11 +33,16 @@ initial begin : TEST_VECTORS
else
$error("Bad CS! addr=%4x should have hex_cs!", addr);
end
if (i >= 16'h7ff4 && i < 16'6) begin
if (i >= 16'h7ff4 && i < 16'h7ff6) begin
assert(uart_cs == '1)
else
$error("Bad CS! addr=%4x should have uart_cs!", addr);
end
if (i == 16'h7fff) begin
assert(irq_cs == '1)
else
$error("Bad CS! addr=%4x should have irq_cs!", addr);
end
if (i >= 2**15) begin
assert(rom_cs == '1)
else

View File

@@ -0,0 +1,75 @@
module testbench();
timeunit 10ns;
timeprecision 1ns;
logic clk_50, rst_n, button_1;
logic [15:0] cpu_addr;
wire [7:0] cpu_data;
logic [7:0] cpu_data_in;
logic [7:0] cpu_data_out;
logic cpu_vpb, cpu_mlb, cpu_rwb, cpu_sync;
logic cpu_led, cpu_resb, cpu_rdy, cpu_sob, cpu_irqb;
logic cpu_phi2, cpu_be, cpu_nmib;
logic [6:0] HEX0, HEX1, HEX2, HEX3, HEX4, HEX5;
logic UART_RXD, UART_TXD;
assign cpu_data = ~cpu_rwb ? cpu_data_out : 'z;
assign cpu_data_in = cpu_data;
super6502 dut(.*);
always #1 clk_50 = clk_50 === 1'b0;
always #100 dut.clk = dut.clk === 1'b0;
always @(posedge dut.clk) begin
dut.cpu_phi2 <= ~dut.cpu_phi2;
end
logic [7:0] _tmp_data;
initial begin
rst_n <= '0;
cpu_addr <= 16'h7fff;
cpu_rwb <= '1;
button_1 <= '1;
repeat(10) @(posedge dut.clk);
rst_n <= '1;
repeat(10) @(posedge dut.clk);
button_1 <= '0;
@(posedge dut.clk);
button_1 <= '1;
@(posedge dut.clk);
assert(cpu_data[0] == '1)
else begin
$error("IRQ location should have bit 1 set!");
end
@(posedge dut.clk);
_tmp_data <= cpu_data_in;
@(posedge dut.clk);
_tmp_data <= _tmp_data & ~8'b1;
@(posedge dut.clk);
cpu_data_out <= _tmp_data;
cpu_rwb <= '0;
@(posedge dut.clk);
cpu_rwb <= '1;
repeat (5) @(posedge dut.clk);
$finish();
end
endmodule

View File

@@ -0,0 +1,24 @@
transcript on
if {[file exists rtl_work]} {
vdel -lib rtl_work -all
}
vlib rtl_work
vmap work rtl_work
vlog -sv -work work {../../hvl/irq_testbench.sv}
vlog -vlog01compat -work work +incdir+/home/byron/Projects/super6502/hw/fpga {/home/byron/Projects/super6502/hw/fpga/ram.v}
vlog -vlog01compat -work work +incdir+/home/byron/Projects/super6502/hw/fpga {/home/byron/Projects/super6502/hw/fpga/rom.v}
vlog -vlog01compat -work work +incdir+/home/byron/Projects/super6502/hw/fpga {/home/byron/Projects/super6502/hw/fpga/cpu_clk.v}
vlog -vlog01compat -work work +incdir+/home/byron/Projects/super6502/hw/fpga/db {/home/byron/Projects/super6502/hw/fpga/db/cpu_clk_altpll.v}
vlog -sv -work work +incdir+/home/byron/Projects/super6502/hw/fpga {/home/byron/Projects/super6502/hw/fpga/uart.sv}
vlog -sv -work work +incdir+/home/byron/Projects/super6502/hw/fpga {/home/byron/Projects/super6502/hw/fpga/addr_decode.sv}
vlog -sv -work work +incdir+/home/byron/Projects/super6502/hw/fpga {/home/byron/Projects/super6502/hw/fpga/super6502.sv}
vlog -sv -work work +incdir+/home/byron/Projects/super6502/hw/fpga {/home/byron/Projects/super6502/hw/fpga/HexDriver.sv}
vlog -sv -work work +incdir+/home/byron/Projects/super6502/hw/fpga {/home/byron/Projects/super6502/hw/fpga/SevenSeg.sv}
vsim -t 1ps -L altera_ver -L lpm_ver -L sgate_ver -L altera_mf_ver -L altera_lnsim_ver -L stratixv_ver -L stratixv_hssi_ver -L stratixv_pcie_hip_ver -L rtl_work -L work -voptargs="+acc" testbench
add wave -group {dut} -radix hexadecimal sim:/testbench/dut/*
onfinish stop
run -all

View File

@@ -42,11 +42,13 @@ assign cpu_data = cpu_rwb ? cpu_data_out : 'z;
logic [7:0] rom_data_out;
logic [7:0] ram_data_out;
logic [7:0] uart_data_out;
logic [7:0] irq_data_out;
logic ram_cs;
logic rom_cs;
logic hex_cs;
logic uart_cs;
logic irq_cs;
cpu_clk cpu_clk(
.inclk0(clk_50),
@@ -62,14 +64,15 @@ assign cpu_sob = '0;
assign cpu_resb = rst_n;
assign cpu_be = '1;
assign cpu_nmib = '1;
assign cpu_irqb = button_1;
assign cpu_irqb = irq_data_out == 0;
addr_decode decode(
.addr(cpu_addr),
.ram_cs(ram_cs),
.rom_cs(rom_cs),
.hex_cs(hex_cs),
.uart_cs(uart_cs)
.uart_cs(uart_cs),
.irq_cs(irq_cs)
);
@@ -80,6 +83,8 @@ always_comb begin
cpu_data_out = rom_data_out;
else if (uart_cs)
cpu_data_out = uart_data_out;
else if (irq_cs)
cpu_data_out = irq_data_out;
else
cpu_data_out = 'x;
end
@@ -124,6 +129,16 @@ uart uart(
.TXD(UART_TXD),
.data_out(uart_data_out)
);
always_ff @(posedge clk_50) begin
if (rst)
irq_data_out <= '0;
else if (irq_cs && ~cpu_rwb)
irq_data_out <= irq_data_out & cpu_data_in;
else if (~button_1)
irq_data_out <= {irq_data_out[7:1], ~button_1};
end
endmodule