From e70fffb4722ff283e84c274d629b5c3dfab16318 Mon Sep 17 00:00:00 2001 From: Byron Lathi Date: Mon, 14 Mar 2022 13:16:09 -0500 Subject: [PATCH] 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. --- hw/fpga/addr_decode.sv | 4 +- hw/fpga/hvl/cs_testbench.sv | 8 ++- hw/fpga/hvl/irq_testbench.sv | 75 ++++++++++++++++++++ hw/fpga/simulation/modelsim/irq_testbench.do | 24 +++++++ hw/fpga/super6502.sv | 19 ++++- 5 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 hw/fpga/hvl/irq_testbench.sv create mode 100644 hw/fpga/simulation/modelsim/irq_testbench.do diff --git a/hw/fpga/addr_decode.sv b/hw/fpga/addr_decode.sv index 83f3c57..8d7da6a 100644 --- a/hw/fpga/addr_decode.sv +++ b/hw/fpga/addr_decode.sv @@ -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 diff --git a/hw/fpga/hvl/cs_testbench.sv b/hw/fpga/hvl/cs_testbench.sv index b764c0f..d89ce93 100644 --- a/hw/fpga/hvl/cs_testbench.sv +++ b/hw/fpga/hvl/cs_testbench.sv @@ -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 diff --git a/hw/fpga/hvl/irq_testbench.sv b/hw/fpga/hvl/irq_testbench.sv new file mode 100644 index 0000000..8c0534d --- /dev/null +++ b/hw/fpga/hvl/irq_testbench.sv @@ -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 diff --git a/hw/fpga/simulation/modelsim/irq_testbench.do b/hw/fpga/simulation/modelsim/irq_testbench.do new file mode 100644 index 0000000..7b29453 --- /dev/null +++ b/hw/fpga/simulation/modelsim/irq_testbench.do @@ -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 diff --git a/hw/fpga/super6502.sv b/hw/fpga/super6502.sv index 37f7178..c564854 100644 --- a/hw/fpga/super6502.sv +++ b/hw/fpga/super6502.sv @@ -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 \ No newline at end of file