From 8e14e73cb65faa5819684f0712624b427d78a0c1 Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Sat, 15 Jan 2011 22:23:44 +0100 Subject: [PATCH 1/1] spartan3e/lcd: (hw) signale per ext.modul rausziehen (sw) rest --- cpu/src/core_pkg.vhd | 3 +- cpu/src/core_top_s3e.vhd | 9 +- cpu/src/extension_lcd.vhd | 21 +++++ cpu/src/extension_lcd_b.vhd | 73 ++++++++++++++++ cpu/src/extension_lcd_pkg.vhd | 23 +++++ cpu/src/extension_pkg.vhd | 1 + cpu/src/writeback_stage.vhd | 3 +- cpu/src/writeback_stage_b.vhd | 19 ++++- progs/Makefile | 2 + progs/lcd.s | 153 ++++++++++++++++++++++++++++++++++ spartan3e/Makefile | 6 ++ spartan3e/spartan3e.ucf | 14 ++++ 12 files changed, 316 insertions(+), 11 deletions(-) create mode 100644 cpu/src/extension_lcd.vhd create mode 100644 cpu/src/extension_lcd_b.vhd create mode 100644 cpu/src/extension_lcd_pkg.vhd create mode 100644 progs/lcd.s diff --git a/cpu/src/core_pkg.vhd b/cpu/src/core_pkg.vhd index 9731f37..722b196 100644 --- a/cpu/src/core_pkg.vhd +++ b/cpu/src/core_pkg.vhd @@ -164,8 +164,9 @@ package core_pkg is sseg2 : out std_logic_vector(0 to 6); sseg3 : out std_logic_vector(0 to 6); - int_req : out interrupt_t + int_req : out interrupt_t; + lcd_data : out std_logic_vector(6 downto 0) ); end component writeback_stage; diff --git a/cpu/src/core_top_s3e.vhd b/cpu/src/core_top_s3e.vhd index 62b2b5d..26c2cea 100644 --- a/cpu/src/core_top_s3e.vhd +++ b/cpu/src/core_top_s3e.vhd @@ -20,11 +20,8 @@ entity core_top is bus_rx : in std_logic; led1 : out std_logic; led2 : out std_logic; - - sseg0 : out std_logic_vector(0 to 6); - sseg1 : out std_logic_vector(0 to 6); - sseg2 : out std_logic_vector(0 to 6); - sseg3 : out std_logic_vector(0 to 6) + -- RW, EN, RS, DB7, DB6, DB5, DB4 + lcd_data : out std_logic_vector(6 downto 0) ); end core_top; @@ -165,7 +162,7 @@ begin reg_wr_data_pin, reg_we_pin, reg_w_addr_pin, jump_result_pin, alu_jump_bit_pin,bus_tx, bus_rx, -- instruction memory program port :D new_im_data, im_addr, im_data, - sseg0, sseg1, sseg2, sseg3, int_req); + open, open, open, open, int_req, lcd_data); syn: process(sys_clk, sys_res) diff --git a/cpu/src/extension_lcd.vhd b/cpu/src/extension_lcd.vhd new file mode 100644 index 0000000..8d99b8a --- /dev/null +++ b/cpu/src/extension_lcd.vhd @@ -0,0 +1,21 @@ +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.common_pkg.all; +use work.extension_pkg.all; +use work.extension_imp_pkg.all; + +entity extension_lcd is + generic ( RESET_VALUE : std_logic); + port( + --System inputs + clk : in std_logic; + reset : in std_logic; + -- general extension interface + ext_reg : in extmod_rec; + data_out : out gp_register_t; + -- out lcd + lcd_data : out std_logic_vector(6 downto 0) + ); +end extension_lcd; diff --git a/cpu/src/extension_lcd_b.vhd b/cpu/src/extension_lcd_b.vhd new file mode 100644 index 0000000..d39f848 --- /dev/null +++ b/cpu/src/extension_lcd_b.vhd @@ -0,0 +1,73 @@ +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +use work.common_pkg.all; +use work.core_pkg.all; + +use work.mem_pkg.all; +use work.extension_pkg.all; +use work.extension_lcd_pkg.all; + +architecture behav of extension_lcd is + +signal w1_st_co, w1_st_co_nxt : gp_register_t; + +begin +syn : process (clk, reset) +begin + if (reset = RESET_VALUE) then + w1_st_co <= (others => '0'); + elsif rising_edge(clk) then + w1_st_co <= w1_st_co_nxt; + end if; +end process syn; + +-------------------------- LESEN UND SCHREIBEN ANFANG ------------------------------------------------------------ +-- w1_st_co LAYOUT: (auf addr 0x2050) +-- w1_st_co(3 downto 0) = DB7 - DB4 +-- w1_st_co(4) = RS +-- w1_st_co(5) = EN +-- w1_st_co(6) = RW + +gwriten : process (clk, ext_reg, w1_st_co) +variable tmp_data : gp_register_t; +begin + w1_st_co_nxt <= w1_st_co; + + if ext_reg.sel = '1' and ext_reg.wr_en = '1' then + tmp_data := (others =>'0'); + for i in 0 to 3 loop + if ext_reg.byte_en(i) = '1' then + tmp_data(((i+1)*byte_t'length-1) downto i*byte_t'length) := ext_reg.data(((i+1)*byte_t'length-1) downto i*byte_t'length); + end if; + end loop; + + case ext_reg.addr(1 downto 0) is + when "00" => -- status/config + w1_st_co_nxt(6 downto 0) <= tmp_data(6 downto 0); + when others => null; + end case; + end if; +end process gwriten; + +gread : process (clk, ext_reg, w1_st_co) +variable tmp_data : gp_register_t; +begin + tmp_data := (others => '0'); + if ext_reg.sel = '1' and ext_reg.wr_en = '0' then + case ext_reg.addr(1 downto 0) is + when "00" => put_word_be(tmp_data, w1_st_co, ext_reg.byte_en); + when others => null; + end case; + end if; + data_out <= tmp_data; +end process gread; + +-------------------------- LESEN UND SCHREIBEN ENDE --------------------------------------------------------------- +-------------------------- INTERNE VERARBEITUNG ANFANG ------------------------------------------------------------ +lcd_data <= w1_st_co(6 downto 0); +-------------------------- INTERNE VERARBEITUNG ENDE -------------------------------------------------------------- +end behav; diff --git a/cpu/src/extension_lcd_pkg.vhd b/cpu/src/extension_lcd_pkg.vhd new file mode 100644 index 0000000..19a35ec --- /dev/null +++ b/cpu/src/extension_lcd_pkg.vhd @@ -0,0 +1,23 @@ +library IEEE; + +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +use work.common_pkg.all; +use work.extension_pkg.all; + +package extension_lcd_pkg is + component extension_lcd is + generic ( RESET_VALUE : std_logic); + port( + --System inputs + clk : in std_logic; + reset : in std_logic; + -- general extension interface + ext_reg : in extmod_rec; + data_out : out gp_register_t; + -- out lcd + lcd_data : out std_logic_vector(6 downto 0) + ); + end component extension_lcd; +end package extension_lcd_pkg; diff --git a/cpu/src/extension_pkg.vhd b/cpu/src/extension_pkg.vhd index f20a119..31cc542 100644 --- a/cpu/src/extension_pkg.vhd +++ b/cpu/src/extension_pkg.vhd @@ -42,6 +42,7 @@ constant EXT_7SEG_ADDR: ext_addrid_t := x"0000201"; constant EXT_INT_ADDR: ext_addrid_t := x"0000202"; constant EXT_IMP_ADDR: ext_addrid_t := x"0000203"; constant EXT_TIMER_ADDR: ext_addrid_t := x"0000204"; +constant EXT_LCD_ADDR: ext_addrid_t := x"0000205"; -- dummy addressen constant EXT_EXTMEM_ADDR: ext_addrid_t := x"FFFFFFB"; constant EXT_AC97_ADDR: ext_addrid_t := x"FFFFFFD"; diff --git a/cpu/src/writeback_stage.vhd b/cpu/src/writeback_stage.vhd index ea82a1e..4f2c231 100644 --- a/cpu/src/writeback_stage.vhd +++ b/cpu/src/writeback_stage.vhd @@ -49,8 +49,9 @@ entity writeback_stage is sseg2 : out std_logic_vector(0 to 6); sseg3 : out std_logic_vector(0 to 6); - int_req : out interrupt_t + int_req : out interrupt_t; + lcd_data : out std_logic_vector(6 downto 0) ); end writeback_stage; diff --git a/cpu/src/writeback_stage_b.vhd b/cpu/src/writeback_stage_b.vhd index acf0f7d..8b208b9 100755 --- a/cpu/src/writeback_stage_b.vhd +++ b/cpu/src/writeback_stage_b.vhd @@ -11,6 +11,7 @@ use work.extension_uart_pkg.all; use work.extension_7seg_pkg.all; use work.extension_imp_pkg.all; use work.extension_timer_pkg.all; +use work.extension_lcd_pkg.all; architecture behav of writeback_stage is @@ -19,8 +20,8 @@ signal data_addr : word_t; signal wb_reg, wb_reg_nxt : writeback_rec; -signal ext_uart,ext_timer,ext_gpmp,ext_7seg,ext_int,ext_imp : extmod_rec; -signal ext_uart_out, ext_timer_out, ext_gpmp_out, ext_int_out,ext_imp_out : gp_register_t; +signal ext_uart,ext_timer,ext_gpmp,ext_7seg,ext_int,ext_imp, ext_lcd : extmod_rec; +signal ext_uart_out, ext_timer_out, ext_gpmp_out, ext_int_out,ext_imp_out, ext_lcd_out : gp_register_t; --signal int_req : interrupt_t; signal uart_int : std_logic; @@ -130,6 +131,10 @@ interrupt : extension_interrupt timer : extension_timer generic map(RESET_VALUE) port map(clk, reset, ext_timer, ext_timer_out); + +lcd : extension_lcd + generic map(RESET_VALUE) + port map(clk, reset, ext_lcd, ext_lcd_out, lcd_data); syn: process(clk, reset) @@ -341,6 +346,7 @@ begin ext_uart.sel <='0'; ext_7seg.sel <='0'; ext_timer.sel <='0'; + ext_lcd.sel <='0'; ext_gpmp.sel <='0'; ext_int.sel <= '0'; ext_imp.sel <= '0'; @@ -348,6 +354,7 @@ begin ext_uart.wr_en <= wr_en; ext_7seg.wr_en <= wr_en; ext_timer.wr_en <= wr_en; + ext_lcd.wr_en <= wr_en; ext_gpmp.wr_en <= wr_en; ext_int.wr_en <= wr_en; ext_imp.wr_en <= wr_en; @@ -355,6 +362,7 @@ begin ext_uart.byte_en <= byte_en; ext_7seg.byte_en <= byte_en; ext_timer.byte_en <= byte_en; + ext_lcd.byte_en <= byte_en; ext_gpmp.byte_en <= byte_en; ext_int.byte_en <= byte_en; ext_imp.byte_en <= byte_en; @@ -362,6 +370,7 @@ begin ext_uart.addr <= addr; ext_7seg.addr <= addr; ext_timer.addr <= addr; + ext_lcd.addr <= addr; ext_gpmp.addr <= addr; ext_int.addr <= addr; ext_imp.addr <= addr; @@ -369,6 +378,7 @@ begin ext_uart.data <= data; ext_7seg.data <= data; ext_timer.data <= data; + ext_lcd.data <= data; ext_gpmp.data <= data; ext_int.data <= data; ext_imp.data <= data; @@ -453,6 +463,9 @@ begin -- when "11" => ext_timer.byte_en <= "1000"; -- when others => null; -- end case; + when EXT_LCD_ADDR => + ext_lcd.sel <= enable; + ext_anysel <= enable; -- when EXT_GPMP_ADDR => -- ext_gpmp.sel <= enable; -- ext_anysel <= enable; @@ -470,7 +483,7 @@ begin when others => ext_anysel <= '0'; end case; - data_ram_read_ext <= ext_uart_out or ext_gpmp_out or ext_timer_out; + data_ram_read_ext <= ext_uart_out or ext_gpmp_out or ext_timer_out or ext_lcd_out; end process; end behav; diff --git a/progs/Makefile b/progs/Makefile index aee6275..86817a3 100644 --- a/progs/Makefile +++ b/progs/Makefile @@ -28,6 +28,7 @@ all: fibmmem.prog fibmmem.prog: testbench.prog: deepjit.prog: +lcd.prog: %.prog: %.dthex @echo " PROG $<" ../tools/dtprog.py $< $(DPROGFLAGS) @@ -43,6 +44,7 @@ deepjit.prog: fibmmem.sim: testbench.sim: deepjit.sim: +lcd.sim: %.sim: %.dthex_sim @echo " SIM $<" cd ../3b_sim/; ./sim -f ../progs/$< diff --git a/progs/lcd.s b/progs/lcd.s new file mode 100644 index 0000000..6c7dbb9 --- /dev/null +++ b/progs/lcd.s @@ -0,0 +1,153 @@ +#include "dt_inc.s" +.text +.org 0x0 +start: + br+ main + br+ main + ret +main: + call+ u_init + call+ u_recv_byte + call u_send_newline + + ldis r1, 0x41 ; 'A' + call u_send_byte + + call lcd_init + ldis r1, 0x42 ; 'B' + call u_send_byte + + call lcd_clear + ldis r1, 0x43 ; 'C' + call u_send_byte + + call lcd_home + ldis r1, 0x44 ; 'D' + call u_send_byte + + call delay5ms ; print 'E' on LCD and UART + ldis r1, 0x45 ; 'E' + push r1 + call lcd_data + pop r1 + call+ u_send_byte + call+ u_send_newline + +loop: + call+ u_recv_byte ; print received Char on LCD + addi r1, r0, 0 + call+ lcd_data + br loop + +hang: br+ hang + + .define LCD_BASE, 0x2050 + ; http://www.mikrocontroller.net/articles/AVR-Tutorial:_LCD#Routinen_zur_LCD-Ansteuerung +lcd_data: + lrs r2, r1, 4 + andx r2, 0xf + orx r2, 0x10 + stw r2, 0(r12) + call+ lcd_enable + + andx r1, 0xf + orx r1, 0x10 + stw r1, 0(r12) + call+ lcd_enable + + call+ delay50us + ret + +lcd_command: + lrs r2, r1, 4 + andx r2, 0xf + stw r2, 0(r12) + call+ lcd_enable + + andx r1, 0xf + stw r1, 0(r12) + call+ lcd_enable + + call+ delay50us + ret + +lcd_enable: + addinv r0, r0, 0 + addinv r0, r0, 0 + addinv r0, r0, 0 + ldw r0, 0(r12) + orx r0, 0x20 + stw r0, 0(r12) + addinv r0, r0, 0 + addinv r0, r0, 0 + addinv r0, r0, 0 + addinv r0, r0, 0 + addinv r0, r0, 0 + ldw r0, 0(r12) + ldis r5, 0xffdf + and r0, r0, r5 + stw r0, 0(r12) + ret + +delay50us: ; @ 50 MHz + ldis r0, 2500/2 + ;ldis r0, 4000/2 +delay50us_: + subi r0, r0, 1 + brnz+ delay50us_ ; not zero + ret + +delay5ms: ; @ 50 MHz + ldis r0, 5 + ;ldis r0, 7 +delay5ms_1: + ldis r1, 50000/2 +delay5ms_2: + subi r1, r1, 1 + brnz+ delay5ms_2 ; not zero + subi r0, r0, 1 + brnz+ delay5ms_1 ; not zero + ret + +lcd_init: + ldis r12, LCD_BASE@lo + ldih r12, LCD_BASE@hi + ldis r3, 50 +powerupwait: + call+ delay5ms + subi r3, r3, 1 + brnz+ powerupwait + + ldis r3, 0x3 + stw r3, 0(r12) + call+ lcd_enable + call+ delay5ms + call+ lcd_enable + call+ delay5ms + call+ lcd_enable + call+ delay5ms + + ldis r3, 0x2 + stw r3, 0(r12) + call+ lcd_enable + call+ delay5ms + + ldis r1, 0x24 + call+ lcd_command + ldis r1, 0xc + call+ lcd_command + ldis r1, 0x4 + call+ lcd_command + ret + +lcd_clear: + ldis r1, 0x1 + call lcd_command + call delay5ms + ret + +lcd_home: + ldis r1, 0x2 + call lcd_command + call delay5ms + ret diff --git a/spartan3e/Makefile b/spartan3e/Makefile index c81a973..1739030 100644 --- a/spartan3e/Makefile +++ b/spartan3e/Makefile @@ -33,6 +33,12 @@ PROJ_VHDL = \ extension_imp_b.vhd \ extension_imp_pkg.vhd \ extension_imp.vhd \ + extension_timer_b.vhd \ + extension_timer_pkg.vhd \ + extension_timer.vhd \ + extension_lcd_b.vhd \ + extension_lcd_pkg.vhd \ + extension_lcd.vhd \ extension.vhd \ fetch_stage_b.vhd \ fetch_stage.vhd \ diff --git a/spartan3e/spartan3e.ucf b/spartan3e/spartan3e.ucf index e260c46..8cc3758 100644 --- a/spartan3e/spartan3e.ucf +++ b/spartan3e/spartan3e.ucf @@ -126,6 +126,20 @@ NET "led2" LOC = "E11" | IOSTANDARD = LVCMOS33 | SLEW = FAST | DRIVE = 8 ; #NET "LCD_RS" LOC = "L18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ; #NET "LCD_RW" LOC = "L17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ; # LCD data connections are shared with StrataFlash connections SF_D<11:8> +# DB4 +NET "LCD_DATA<0>" LOC = "R15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ; +# DB5 +NET "LCD_DATA<1>" LOC = "R16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ; +# DB6 +NET "LCD_DATA<2>" LOC = "P17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ; +# DB7 +NET "LCD_DATA<3>" LOC = "M15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ; +# RS +NET "LCD_DATA<4>" LOC = "L18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ; +# EN +NET "LCD_DATA<5>" LOC = "M18" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ; +# RW +NET "LCD_DATA<6>" LOC = "L17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ; #NET "SF_D<8>" LOC = "R15" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ; #NET "SF_D<9>" LOC = "R16" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ; #NET "SF_D<10>" LOC = "P17" | IOSTANDARD = LVCMOS33 | DRIVE = 4 | SLEW = SLOW ; -- 2.25.1