diff --git a/documentation/SJA1000.pdf b/documentation/SJA1000.pdf index 2b3d2b6..5b808be 100644 Binary files a/documentation/SJA1000.pdf and b/documentation/SJA1000.pdf differ diff --git a/documentation/SJA1000_datasheet.pdf b/documentation/SJA1000_datasheet.pdf index 250fe3d..4209c77 100644 Binary files a/documentation/SJA1000_datasheet.pdf and b/documentation/SJA1000_datasheet.pdf differ diff --git a/programs/can_test.prog_ b/programs/can_test.prog_ new file mode 100644 index 0000000..5f1da16 --- /dev/null +++ b/programs/can_test.prog_ @@ -0,0 +1,71 @@ +reset: + br always >main + nop + +hardfault: + reti + nop + +memfault: + reti + nop + +timer_interrupt: + reti + nop + +can_interrupt: + br >can_interrupt + nop + +.align +led_addr: .word 0x000F0000 + +timer_counter_addr: .word 0x000F0008 +timer_status_addr: .word 0x000F000C + +dmem_start_addr: .word 0x00000400 +dmem_end_addr: .word 0x000004FC + +priority_mask: .word 0xFFFFFF03 + +timer_target_value: .word 127 // for simulation +// timer_target_value: .word 0xF10000 // for real board + +can_base_addr: .word 0x000F0100 + +can_control_ptr: .word =can_base_addr +can_command_ptr: .word =can_base_addr + 1 +can_acceptance_code_ptr: .word =can_base_addr + 4 +can_acceptance_mask_ptr: .word =can_base_addr + 5 +can_acceptance_bus_timing0_ptr: .word =can_base_addr + 6 +can_acceptance_bus_timing1_ptr: .word =can_base_addr + 7 +can_output_control_ptr: .word =can_base_addr + 8 +can_identifier0_ptr: .word =can_base_addr + 10 +can_identifier1_ptr: .word =can_base_addr + 11 +can_data0_ptr: .word =can_base_addr + 12 +can_data1_ptr: .word =can_base_addr + 13 + +main: + // Initialize stack pointer to the end of the data memory + ldr r12, >dmem_end_addr + + // Set runtime priority + ldr r0, >priority_mask + and r14, r0, r14 + + // Set LED to pattern + clr r2 + addi r2, 0x7A + st08 r0, r2 + + // Initialize CAN + ldr r0, >can_acceptance_code_ptr + +loop: + br >loop + nop + +can_interrupt: + reti + nop diff --git a/programs/interrupt_test.prog b/programs/interrupt_test.prog new file mode 100644 index 0000000..3dff467 --- /dev/null +++ b/programs/interrupt_test.prog @@ -0,0 +1,65 @@ +reset: + br always >main + nop + +hardfault: + reti + nop + +memfault: + reti + nop + +switches_interrupt: + br >switches_interrupt_handler + nop + +can_interrupt: + br >can_interrupt_handler + nop + +.align +led_addr: .word 0x000F0000 +timer_counter_addr: .word 0x000F0008 +timer_status_addr: .word 0x000F000C +dmem_start_addr: .word 0x00000400 +dmem_end_addr: .word 0x000004FC +priority_mask: .word 0xFFFFFF03 + +// timer_target_value: .word 127 // for simulation +timer_target_value: .word 0xF10000 // for real board + +main: + // Initialize stack pointer to the end of the data memory + ldr r12, >dmem_end_addr + + // Set runtime priority + ldr r0, >priority_mask + and r14, r0, r14 + + ldr r0,>led_addr // LED addr + ldr r1,>timer_status_addr // Timer addr + ldr r3,>timer_counter_addr // Timer addr + + // Set LED to pattern + clr r2 + addi r2, 0x7A + st08 r0, r2 + + // Enable the timer... + ldr r2, >timer_target_value + st32 r3, r2 + + clr r2 + addi r2, 0x1 // enable bit set + st32 r1, r2 + +loop: + br >loop + nop + +timer_interrupt_handler: + // Set LED to pattern + clr r2 + addi r2, 0x0C + st08 r0, r2 diff --git a/programs/scrolling.prog b/programs/scrolling.prog index 5f61807..e034797 100644 --- a/programs/scrolling.prog +++ b/programs/scrolling.prog @@ -12,11 +12,11 @@ nop scrolling_addr: .word 0x000F00A0 scrolling_count_addr: .word 0x000F00A4 -scrolling_cnt_value: .word 0x20FC000 // for real board -// scrolling_cnt_value: .word 0x500 // for simulation +// scrolling_cnt_value: .word 0x20FC000 // for real board +scrolling_cnt_value: .word 0x500 // for simulation -w_cnt_top: .word 0x3FC000 // for real board -// w_cnt_top: .word 0x100 //for simulation +// w_cnt_top: .word 0x3FC000 // for real board +w_cnt_top: .word 0x100 //for simulation pattern_ptr: .word =pattern1 diff --git a/soc/core/lt16x32_global.vhd b/soc/core/lt16x32_global.vhd index 4500d34..8c6f54a 100644 --- a/soc/core/lt16x32_global.vhd +++ b/soc/core/lt16x32_global.vhd @@ -8,7 +8,7 @@ package lt16x32_global is -- width of the memory, the core supports 32 only constant memory_width : integer := 32; -- width of the vector holding the interrupt number, maximum 7 due to processor architecture - constant irq_num_width : integer := 4; + constant irq_num_width : integer := 5; -- width of the vector holding the interrupt priority, maximum 6 due to processor architecture constant irq_prio_width : integer := 4; diff --git a/soc/lib/config.vhd b/soc/lib/config.vhd index 34d3eb1..854dea5 100644 --- a/soc/lib/config.vhd +++ b/soc/lib/config.vhd @@ -30,6 +30,7 @@ package config is constant CFG_SW : integer := CFG_LED+1; constant CFG_TIMER : integer := CFG_SW+1; constant CFG_SCR : integer := CFG_TIMER+1; + constant CFG_CAN : integer := CFG_SCR+1; ----------------------------- -- base address (BADR) & mask address (MADR) @@ -42,6 +43,7 @@ package config is constant CFG_BADR_SW : generic_addr_type := 16#000F0004#; constant CFG_BADR_TIMER : generic_addr_type := 16#000F0008#; constant CFG_BADR_SCR : generic_addr_type := 16#000F00A0#; + constant CFG_BADR_CAN : generic_addr_type := 16#000F0100#; -- mask addr constant CFG_MADR_ZERO : generic_mask_type := 0; @@ -52,6 +54,7 @@ package config is constant CFG_MADR_SW : generic_mask_type := 16#3FFFFF# - (4 - 1); -- size=4 byte constant CFG_MADR_TIMER : generic_mask_type := 16#3FFFFF# - (8 - 1); -- size=8 byte (2 words) constant CFG_MADR_SCR : generic_mask_type := 16#3FFFFF# - (8 - 1); -- size=8 byte + constant CFG_MADR_CAN : generic_mask_type := 16#3FFFFF# - (256 - 1); -- size=256 byte end package config; diff --git a/soc/peripheral/peripherals.vhd b/soc/peripheral/peripherals.vhd index f8dd4cb..bb5d10b 100644 --- a/soc/peripheral/peripherals.vhd +++ b/soc/peripheral/peripherals.vhd @@ -12,6 +12,22 @@ use work.config.all; package lt16soc_peripherals is + component can_vhdl_top is + generic( + memaddr : generic_addr_type; + addrmask : generic_mask_type + ); + port( + clk : in std_logic; + rstn : in std_logic; + wbs_i : in wb_slv_in_type; + wbs_o : out wb_slv_out_type; + rx_i : in std_logic; + tx_o : out std_logic; + irq_on : out std_logic + ); + end component can_vhdl_top; + component wb_led is generic( memaddr : generic_addr_type;-- := CFG_BADR_LED; @@ -38,7 +54,9 @@ package lt16soc_peripherals is wslvo : out wb_slv_out_type; buttons : in std_logic_vector(4 downto 0); - switches : in std_logic_vector(15 downto 0) + switches : in std_logic_vector(15 downto 0); + + interrupt : out std_logic ); end component; diff --git a/soc/peripheral/switches.vhd b/soc/peripheral/switches.vhd index 4826a1e..5257875 100644 --- a/soc/peripheral/switches.vhd +++ b/soc/peripheral/switches.vhd @@ -19,7 +19,9 @@ entity wb_switches is wslvo : out wb_slv_out_type; buttons : in std_logic_vector(4 downto 0); - switches : in std_logic_vector(15 downto 0) + switches : in std_logic_vector(15 downto 0); + + interrupt : out std_logic ); end wb_switches; @@ -28,6 +30,8 @@ architecture Behavioral of wb_switches is signal data : std_logic_vector(20 downto 0); signal ack : std_logic; + signal old_input : std_logic_vector(20 downto 0); + begin process(clk) @@ -55,6 +59,26 @@ begin end if; end process; + process(clk) + begin + if clk'event and clk='1' then + if rst = '1' then + interrupt <= '0'; + old_input <= (others => '0'); + else + if buttons & switches /= old_input + then + interrupt <= '1'; + else + interrupt <= '0'; + end if; + + old_input(15 downto 0) <= switches; + old_input(20 downto 16) <= buttons; + end if; + end if; + end process; + wslvo.dat(20 downto 0) <= data; wslvo.dat(31 downto 21) <= (others=>'0'); diff --git a/soc/testbench/can_demo_tb.vhd b/soc/testbench/can_demo_tb.vhd index 1eb55e8..60aaa65 100644 --- a/soc/testbench/can_demo_tb.vhd +++ b/soc/testbench/can_demo_tb.vhd @@ -111,13 +111,13 @@ begin --setup both can nodes - write_regs_from_file( "./testdata/default_setup.tdf", wbs_i1, wbs_o1, clk); + write_regs_from_file( "/home/derek/Git/lt16lab/soc/testbench/testdata/default_setup.tdf", wbs_i1, wbs_o1, clk); --wait for 1000 ns; - write_regs_from_file( "./testdata/default_setup.tdf", wbs_i2, wbs_o2, clk); + write_regs_from_file( "/home/derek/Git/lt16lab/soc/testbench/testdata/default_setup.tdf", wbs_i2, wbs_o2, clk); wait for 1000 ns; --setup and execute a 2 byte transmission in controller 1 - write_regs_from_file( "./testdata/data_send.tdf", wbs_i1, wbs_o1, clk); + write_regs_from_file( "/home/derek/Git/lt16lab/soc/testbench/testdata/data_send.tdf", wbs_i1, wbs_o1, clk); tx_vector(2) <= tx_vector(1); --manual ack by copying controler 2's ack @@ -131,7 +131,7 @@ begin --read status register of controller 1 can_wb_read_reg(wbs_i1, wbs_o1, 2, clk); --read from controller 2's read buffer - read_regs_with_fileaddr("./testdata/data_read.tdf", "read_data0.tdf", wbs_i2, wbs_o2, clk); + read_regs_with_fileaddr("/home/derek/Git/lt16lab/soc/testbench/testdata/data_read.tdf", "read_data0.tdf", wbs_i2, wbs_o2, clk); wait for 1200 ns; --release receive buffer of controller 2 @@ -146,8 +146,8 @@ begin wait on irq_on2; --read from both receive buffers - read_regs_with_fileaddr("./testdata/data_read.tdf", "read_data1.tdf", wbs_i1, wbs_o1, clk); - read_regs_with_fileaddr("./testdata/data_read.tdf", "read_data2.tdf", wbs_i2, wbs_o2, clk); + read_regs_with_fileaddr("/home/derek/Git/lt16lab/soc/testbench/testdata/data_read.tdf", "read_data1.tdf", wbs_i1, wbs_o1, clk); + read_regs_with_fileaddr("/home/derek/Git/lt16lab/soc/testbench/testdata/data_read.tdf", "read_data2.tdf", wbs_i2, wbs_o2, clk); wait for 2400 ns; --release both receive buffers can_wb_write_reg(wbs_i1, wbs_o1, 1, "00000100", clk); diff --git a/soc/testbench/project.vhd b/soc/testbench/project.vhd new file mode 100644 index 0000000..8474394 --- /dev/null +++ b/soc/testbench/project.vhd @@ -0,0 +1,72 @@ +-- See the file "LICENSE" for the full license governing this code. -- +LIBRARY ieee; +USE ieee.std_logic_1164.ALL; +USE ieee.numeric_std.ALL; + +ENTITY project_tb IS +END ENTITY; + +ARCHITECTURE sim OF project_tb IS + + constant CLK_PERIOD : time := 10 ns; + + signal clk : std_logic := '0'; + signal rst : std_logic; + + signal led : std_logic_vector(7 downto 0); + signal btn : std_logic_vector(4 downto 0) := (others => '0'); + signal sw : std_logic_vector(15 downto 0) := (others => '0'); + signal anodes : std_logic_vector(7 downto 0); + signal cathodes : std_logic_vector(7 downto 0); + + signal can_rx_i : std_logic := '1'; + signal can_tx_o : std_logic := '1'; + + COMPONENT lt16soc_top IS + generic( + programfilename : string := "../../programs/interrupt_test.ram" + ); + port( + clk : in std_logic; + rst : in std_logic; + led : out std_logic_vector(7 downto 0); + btn : in std_logic_vector(4 downto 0); + sw : in std_logic_vector(15 downto 0); + anodes : out std_logic_vector(7 downto 0); + cathodes : out std_logic_vector(7 downto 0); + can_rx_i : in std_logic; + can_tx_o : out std_logic + ); + END COMPONENT; + +BEGIN + + dut: lt16soc_top port map( + clk=>clk, + rst=>rst, + led=>led, + btn=>btn, + sw=>sw, + anodes=>anodes, + cathodes=>cathodes, + can_rx_i=>can_rx_i, + can_tx_o=>can_tx_o + ); + + clk_gen: process + begin + clk <= not clk; + wait for CLK_PERIOD/2; + end process clk_gen; + + stimuli: process + begin + rst <= '0'; + wait for CLK_PERIOD; + rst <= '1'; + wait for 100us; + assert false report "Simulation terminated!" severity failure; + end process stimuli; + + +END ARCHITECTURE; diff --git a/soc/testbench/switches_tb.vhd b/soc/testbench/switches_tb.vhd index b93c07e..a65cdd7 100644 --- a/soc/testbench/switches_tb.vhd +++ b/soc/testbench/switches_tb.vhd @@ -23,6 +23,8 @@ ARCHITECTURE sim OF switches_tb IS signal buttons: std_logic_vector(4 downto 0); signal switches : std_logic_vector(15 downto 0); + signal interrupt : std_logic; + signal slvi : wb_slv_in_type; signal slvo : wb_slv_out_type; @@ -38,6 +40,7 @@ BEGIN rst => rst, buttons => buttons, switches => switches, + interrupt => interrupt, wslvi => slvi, wslvo => slvo ); @@ -74,6 +77,31 @@ BEGIN generate_sync_wb_single_read(slvi,slvo,clk,data, SIZE => "01"); -- Half word wait for 100 ns; + + buttons <= "00000"; + switches <= x"DEAD"; + + wait for 50ns; + buttons <= "00100"; + switches <= x"DEAD"; + + wait for 50ns; + buttons <= "00000"; + switches <= x"DEAD"; + + wait for 50ns; + buttons <= "00000"; + switches <= x"DAAD"; + + wait for 50ns; + buttons <= "01000"; + switches <= x"DEAD"; + + wait for 50ns; + buttons <= "00010"; + switches <= x"DEAD"; + + wait for 50ns; assert false report "Simulation terminated!" severity failure; end process stimuli; diff --git a/soc/testbench/testdata/data_read.tdf b/soc/testbench/testdata/data_read.tdf new file mode 100644 index 0000000..1df864c --- /dev/null +++ b/soc/testbench/testdata/data_read.tdf @@ -0,0 +1,4 @@ +20 +21 +22 +23 \ No newline at end of file diff --git a/soc/testbench/testdata/data_send.tdf b/soc/testbench/testdata/data_send.tdf new file mode 100644 index 0000000..8768f7e --- /dev/null +++ b/soc/testbench/testdata/data_send.tdf @@ -0,0 +1,5 @@ +10 10101010 +11 11000010 +12 10101010 +13 00001111 +1 00000001 \ No newline at end of file diff --git a/soc/testbench/testdata/default_setup.tdf b/soc/testbench/testdata/default_setup.tdf new file mode 100644 index 0000000..7feff40 --- /dev/null +++ b/soc/testbench/testdata/default_setup.tdf @@ -0,0 +1,6 @@ +4 00000000 +5 11111111 +6 10000000 +7 01001000 +8 00000010 +0 11111110 \ No newline at end of file diff --git a/soc/top/top.vhd b/soc/top/top.vhd index 2e677f3..7c2da86 100644 --- a/soc/top/top.vhd +++ b/soc/top/top.vhd @@ -14,7 +14,7 @@ use work.lt16soc_peripherals.all; entity lt16soc_top is generic( - programfilename : string := "../../programs/scrolling.ram" -- see "Synthesize XST" process properties for actual value ("-generics" in .xst file)! + programfilename : string := "../../programs/interrupt_test.ram" -- see "Synthesize XST" process properties for actual value ("-generics" in .xst file)! ); port( -- clock signal @@ -28,7 +28,10 @@ port( sw : in std_logic_vector(15 downto 0); anodes : out std_logic_vector(7 downto 0); - cathodes : out std_logic_vector(7 downto 0) + cathodes : out std_logic_vector(7 downto 0); + + can_rx_i : in std_logic; + can_tx_o : out std_logic ); end entity lt16soc_top; @@ -40,7 +43,7 @@ architecture RTL of lt16soc_top is signal rst_gen : std_logic; - constant slv_mask_vector : std_logic_vector(0 to NWBSLV-1) := b"1111_1100_0000_0001"; + constant slv_mask_vector : std_logic_vector(0 to NWBSLV-1) := b"1111_1110_0000_0001"; constant mst_mask_vector : std_logic_vector(0 to NWBMST-1) := b"1000"; signal slvo : wb_slv_out_vector := (others=> wbs_out_none); @@ -180,12 +183,32 @@ begin addrmask=>CFG_MADR_DMEM) port map(clk,rst_gen,slvi(CFG_DMEM),slvo(CFG_DMEM)); + can_inst : component can_vhdl_top + generic map( + memaddr=>CFG_BADR_CAN, + addrmask=>CFG_MADR_CAN + ) + port map( + clk => clk, + rstn => rst, + wbs_i => slvi(CFG_CAN), + wbs_o => slvo(CFG_CAN), + rx_i => can_rx_i, + tx_o => can_tx_o, + irq_on => irq_lines(4) + ); + leddev : wb_led generic map( - CFG_BADR_LED,CFG_MADR_LED + CFG_BADR_LED, + CFG_MADR_LED ) port map( - clk,rst_gen,led,slvi(CFG_LED),slvo(CFG_LED) + clk, + rst_gen, + led, + slvi(CFG_LED), + slvo(CFG_LED) ); swdev : wb_switches @@ -198,10 +221,15 @@ begin timerdev : wb_timer generic map( - CFG_BADR_TIMER,CFG_MADR_TIMER + CFG_BADR_TIMER, + CFG_MADR_TIMER ) port map( - clk,rst_gen,slvi(CFG_TIMER),slvo(CFG_TIMER), irq_lines(3) + clk, + rst_gen, + slvi(CFG_TIMER), + slvo(CFG_TIMER), + irq_lines(3) ); scrollingdev : wb_scrolling diff --git a/soc/top/top.xdc b/soc/top/top.xdc index 750b6c9..f1a2f7e 100644 --- a/soc/top/top.xdc +++ b/soc/top/top.xdc @@ -81,8 +81,8 @@ set_property -dict { PACKAGE_PIN P18 IOSTANDARD LVCMOS33 } [get_ports { btn[4] ##Pmod Headers ##Pmod Header JA -#set_property -dict { PACKAGE_PIN C17 IOSTANDARD LVCMOS33 } [get_ports { JA[1] }]; #IO_L20N_T3_A19_15 Sch=ja[1] -#set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { JA[2] }]; #IO_L21N_T3_DQS_A18_15 Sch=ja[2] +set_property -dict { PACKAGE_PIN C17 IOSTANDARD LVCMOS33 } [get_ports { can_rx_i }]; #IO_L20N_T3_A19_15 Sch=ja[1] +set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { can_tx_o }]; #IO_L21N_T3_DQS_A18_15 Sch=ja[2] #set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports { JA[3] }]; #IO_L21P_T3_DQS_15 Sch=ja[3] #set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { JA[4] }]; #IO_L18N_T2_A23_15 Sch=ja[4] #set_property -dict { PACKAGE_PIN D17 IOSTANDARD LVCMOS33 } [get_ports { JA[7] }]; #IO_L16N_T2_A27_15 Sch=ja[7]