Skip to content
Snippets Groups Projects
Commit 7d7f7d03 authored by Roberto Hexsel's avatar Roberto Hexsel
Browse files

changes to STATUS.IE delay IRQs to avoi hazards. new baud rates for UART

parent 1ffcdd18
No related branches found
No related tags found
No related merge requests found
......@@ -26,6 +26,7 @@ unset WAVE
length=1
unit=m
gtkwconf=pipe
synth=
touch input.data input.txt serial.inp
......@@ -42,6 +43,7 @@ OPTIONS:
-n send simulator output do /dev/null, else to v_cMIPS.vcd
-w invoke GTKWAVE -- stdin will not read input from keyboard
-v F gtkwave configuration file (e.g. pipe.sav, default v.sav)
-syn run simulation with synthesis RAM/ROM addresses
EOF
}
......@@ -60,6 +62,8 @@ while true ; do
;;
-w) WAVE=true
;;
-syn | -mif ) synth="-syn"
;;
-v) gtkwconf=$2
shift
;;
......@@ -78,7 +82,7 @@ gfile=${gtkwconf%%.sav}
sav="${tree}"/${gfile}.sav
"${bin}"/build.sh || exit 1
"${bin}"/build.sh $synth || exit 1
options="--ieee-asserts=disable --stop-time=${length}${unit}s --vcd=${visual}"
......
......@@ -22,12 +22,13 @@
#define IO_DSP7SEG_ADDR (x_IO_BASE_ADDR + 9 * x_IO_ADDR_RANGE)
#define IO_KEYBD_ADDR (x_IO_BASE_ADDR +10 * x_IO_ADDR_RANGE)
#define IO_LCD_ADDR (x_IO_BASE_ADDR +11 * x_IO_ADDR_RANGE)
#define IO_SDCARD_ADDR (x_IO_BASE_ADDR +12 * x_IO_ADDR_RANGE)
#define IO_SDC_ADDR (x_IO_BASE_ADDR +12 * x_IO_ADDR_RANGE)
extern void exit(int);
extern void cmips_delay(int);
extern void delay_cycle(int);
extern void delay_us(int);
extern void delay_ms(int);
......@@ -79,6 +80,11 @@ extern void DSP7SEGput(int, int, int, int, int);
extern int KBDget(void);
extern int SWget(void);
// RGB led color for DSP7SEGput (color must be in [0,7]
#define l_RED 0x4
#define l_GREEN 0x2
#define l_BLUE 0x1
// struct to access the cache system statistics "peripheral"
typedef struct sStats {
......
......@@ -19,7 +19,7 @@
.set HW_dsp7seg_addr,(x_IO_BASE_ADDR + 9 * x_IO_ADDR_RANGE)
.set HW_keybd_addr, (x_IO_BASE_ADDR + 10 * x_IO_ADDR_RANGE)
.set HW_lcd_addr, (x_IO_BASE_ADDR + 11 * x_IO_ADDR_RANGE)
.set HW_SDcard_addr, (x_IO_BASE_ADDR + 12 * x_IO_ADDR_RANGE)
.set HW_sdc_addr, (x_IO_BASE_ADDR + 12 * x_IO_ADDR_RANGE)
# see vhdl/packageMemory.vhd for addresses
.set x_EXCEPTION_0000,0x00000130
......
......@@ -69,21 +69,23 @@ extCounter:
# interrupt handler for UART attached to IP6=HW4
# for UART's address see vhdl/packageMemory.vhd
#
.global Ud, _uart_buff
.bss
.align 2
.global Ud
Ud:
rx_hd: .space 4
rx_tl: .space 4
rx_q: .space 16 # reception queue and pointers
tx_hd: .space 4
tx_tl: .space 4
tx_q: .space 16 # transmission queue and pointers
rx_hd: .space 4 # reception queue head index
rx_tl: .space 4 # tail index
rx_q: .space 16 # reception queue
tx_hd: .space 4 # transmission queue head index
tx_tl: .space 4 # tail index
tx_q: .space 16 # transmission queue
nrx: .space 4 # characters in RX_queue
ntx: .space 4 # spaces left in TX_queue
_uart_buff: .space 16*4 # up to 16 registers to be saved here
# _uart_buff[0]=UARTstatus, [1]=UARTcontrol, [2]=data_inp, [3]=new,
# [4]=$ra, [5]=$a0, [6]=$a1, [7]=$a2, [8]=$a3
.set UART_rx_irq,0x08
.set UART_tx_irq,0x10
......@@ -91,9 +93,6 @@ _uart_buff: .space 16*4 # up to 16 registers to be saved here
.set noreorder
.global UARTinterr
.ent UARTinterr
# _uart_buff[0]=UARTstatus, [1]=UARTcontrol, [2]=data_inp, [3]=new,
# [4]=$ra, [5]=$a0, [6]=$a1, [7]=$a2, [8]=$a3
UARTinterr:
lui $k0, %hi(_uart_buff) # get buffer's address
......@@ -101,12 +100,12 @@ UARTinterr:
sw $a0, 5*4($k0) # save registers $a0,$a1, others?
sw $a1, 6*4($k0)
sw $a2, 7*4($k0)
lui $a0, %hi(HW_uart_addr)# get device's address
ori $a0, $a0, %lo(HW_uart_addr)
lw $k1, 0($a0) # Read status, remove interrupt request
nop
sw $k1, 0*4($k0) # and save UART status to memory
#----------------------------------
......@@ -121,12 +120,16 @@ UARTinterr:
# handle reception
lw $a1, 4($a0) # Read data from device
nop # and store it to UART's buffer
sw $a1, 2*4($k0) # and return from interrupt
lui $a2, %hi(Ud) # get address for data & flag
ori $a2, $a2, %lo(Ud)
sw $a1, 0*4($a2) # and return from interrupt
addiu $a1, $zero, 1
sw $a1, 3*4($k0) # Signal new arrival
sw $a1, 1*4($a2) # set flag to signal new arrival
UARTret:
lw $a2, 7*4($k0)
lw $a1, 6*4($k0) # restore registers $a0,$a1, others?
lw $a0, 5*4($k0)
......@@ -153,6 +156,7 @@ countCompare:
mfc0 $k0, c0_status # Read STATUS register
ori $k0, $k0, M_StatusIEn # but do not modify its contents
mtc0 $k0, c0_status # except for re-enabling interrupts
ehb
eret # Return from interrupt
.end countCompare
#----------------------------------------------------------------
......@@ -171,8 +175,10 @@ startCount:
lui $v1, 0xf7ff
ori $v1, $v1, 0xffff
and $v0, $v0, $v1
jr $ra
mtc0 $v0, c0_cause
ehb
jr $ra
nop
.end startCount
#----------------------------------------------------------------
......@@ -220,7 +226,7 @@ enableInterr:
mfc0 $v0, c0_status # Read STATUS register
ori $v0, $v0, 1 # and enable interrupts
mtc0 $v0, c0_status
nop
ehb
jr $ra # return updated STATUS
nop
.end enableInterr
......@@ -231,7 +237,7 @@ disableInterr:
addiu $v1, $zero, -2 # and disable interrupts
and $v0, $v0, $v1 # -2 = 0xffff.fffe
mtc0 $v0, c0_status
nop
ehb
jr $ra # return updated STATUS
nop
.end disableInterr
......@@ -481,11 +487,13 @@ pu_miss: jr $ra
.ent cmips_delay
delay_cycle:
cmips_delay:
addiu $a0, $a0, -1
beq $a0, $zero, _d_cye
nop
_d_cy: addiu $a0, $a0, -1
nop
bne $a0, $zero, cmips_delay
bne $a0, $zero, _d_cy
nop
jr $ra
_d_cye: jr $ra
nop
.end cmips_delay
#----------------------------------------------------------------
......@@ -498,6 +506,8 @@ cmips_delay:
.set noreorder
.ent delay_us
delay_us:
beq $a0, $zero, _d_use
nop
li $v0, 10
mult $v0, $a0
nop
......@@ -508,7 +518,7 @@ _d_us: addiu $a0, $a0, -1
nop
bne $a0, $zero, _d_us
nop
jr $ra
_d_use: jr $ra
nop
.end delay_us
#----------------------------------------------------------------
......@@ -522,6 +532,8 @@ _d_us: addiu $a0, $a0, -1
.set noreorder
.ent delay_ms
delay_ms:
beq $a0, $zero, _d_mse
nop
li $v0, 10000
mul $a0, $v0, $a0
nop
......@@ -530,7 +542,7 @@ _d_ms: addiu $a0, $a0, -1
nop
bne $a0, $zero, _d_ms
nop
jr $ra
_d_mse: jr $ra
nop
.end delay_ms
#----------------------------------------------------------------
......
......@@ -24,19 +24,22 @@ void main(void) {
LCDtopLine();
#if 1
LCDput('c');
LCDput('M');
LCDput('I');
LCDput('P');
LCDput('S');
LCDput(' ');
LCDput('H');
LCDput('t');
LCDput('i');
LCDput('m');
LCDput('e');
LCDput('l');
LCDput('l');
LCDput('o');
LCDput(' ');
LCDput('w');
LCDput('o');
LCDput('r');
LCDput('l');
LCDput('d');
LCDput('!');
LCDput('[');
LCDput('h');
LCDput('e');
LCDput('x');
LCDput(']');
#else
LCDprint( print_sp() ); // for debugging only
#endif
......
......@@ -13,18 +13,20 @@
#include "uart_defs.c"
extern int _uart_buff[16]; // declared in include/handlers.s
#define U_DATA 0
#define U_FLAG 1
#define SPEED 2 // operate at 1/4 of the highest data rate
int main(void) { // receive a string through the UART serial interface
int main(void) { // receive a string through the UART serial interface
volatile Tserial *uart; // tell GCC not to optimize away code
Tcontrol ctrl;
volatile int *bfr = &(_uart_buff[0]);
extern int Ud[2]; // declared in include/handlers.s
volatile int *bfr;
volatile char c;
bfr = (int *)Ud;
uart = (void *)IO_UART_ADDR; // bottom of UART address range
ctrl.ign = 0;
......@@ -36,7 +38,7 @@ int main(void) { // receive a string through the UART serial interface
// handler sets flag=bfr[3] to 1 after new character is received;
// this program resets the flag on fetching a new character from buffer
bfr[3] = 0; // reset flag
bfr[U_FLAG] = 0; // reset flag
ctrl.ign = 0;
ctrl.rts = 1; // make RTS=1 to activate remote unit
......@@ -46,12 +48,12 @@ int main(void) { // receive a string through the UART serial interface
uart->cs.ctl = ctrl;
do {
while ( (c = (char)bfr[3]) == 0 )
{}; // nothing new
c = (char)bfr[2]; // get new character
bfr[3] = 0; // and reset flag
to_stdout( (int)c ); // and print new char
} while (c != '\0'); // end of string?
while ( (c = (char)bfr[U_FLAG]) == 0 ) // check flag in Ud[1]
{}; // nothing new
c = (char)bfr[U_DATA]; // get new character
bfr[U_FLAG] = 0; // and reset flag
to_stdout( (int)c ); // and print new char
} while (c != '\0'); // end of string?
return c;
......
This diff is collapsed.
......@@ -1809,8 +1809,17 @@ begin
-- delay the IRQ to make sure the interrupted instruction completes;
-- This is needed to ensure forward-progress: at least one instruction
-- must complete before another interrupt may be taken.
-- Also, delay the interrupt requests to avoid hazards while
-- the interrupt-enable bit is changed in the STATUS register.
dly_i0 <= '1' when is_exception = exERET else '0';
dly_i0 <= '1' when ( (EX_exception = exERET) or -- forward progress
(EX_exception = exEI) or -- interrupt hazard
(EX_exception = exDI) or -- interrupt hazard
(EX_exception = exEHB) or -- interrupt hazard
(EX_exception = exMTC0 -- interrupt hazard
and EX_cop0_reg = cop0reg_STATUS) ) else
'0';
U_DLY_INT1: FFD port map (clk, rst, '1',dly_i0, dly_i1);
U_DLY_INT2: FFD port map (clk, rst, '1',dly_i1, dly_i2);
dly_interr <= dly_i0 or dly_i1 or dly_i2;
......@@ -1864,7 +1873,7 @@ begin
-- STATUS -- pg 79 -- cop0_12 --------------------
COP0_DECODE_EXCEPTION_AND_UPDATE_STATUS:
process (MM_a_rt, is_exception, cop0_inp,
MM_cop0_reg, MM_cop0_sel, MM_int_req,
MM_cop0_reg, MM_cop0_sel,
RF_is_delayslot, EX_is_delayslot, MM_is_delayslot, WB_is_delayslot,
rom_stall,ram_stall, MM_is_mfc0,
INDEX, RANDOM, EntryLo0, EntryLo1, CONTEXT, PAGEMASK, WIRED,
......
......@@ -977,14 +977,14 @@ entity SDcard is
sel : in std_logic;
rdy : out std_logic;
wr : in std_logic;
addr : in reg2; -- a03, a02
addr : in reg2; -- a03, a02
data_inp : in reg32;
data_out : out reg32;
sdc_cs : out std_logic; -- SDcard chip-select
sdc_clk : out std_logic; -- SDcard serial clock
sdc_mosi_o : out std_logic; -- SDcard serial data out (to card)
sdc_mosi_i : in std_logic; -- SDcard serial data inp (fro card)
irq : out std_logic); -- interrupt request (not yet used)
sdc_cs : out std_logic; -- SDcard chip-select
sdc_clk : out std_logic; -- SDcard serial clock
sdc_mosi_o : out std_logic; -- SDcard serial data out (to card)
sdc_miso_i : in std_logic; -- SDcard serial data inp (fro card)
irq : out std_logic); -- interrupt request (not yet used)
end SDCard;
architecture behavioral of SDcard is
......@@ -1033,27 +1033,30 @@ architecture behavioral of SDcard is
cs_bo : out std_logic; -- Active-low chip-select.
sclk_o : out std_logic; -- Serial clock to SD card.
mosi_o : out std_logic; -- Serial data output to SD card.
miso_i : in std_logic); -- Serial data input from SD card.
miso_i : in std_logic; -- Serial data input from SD card.
state : out std_logic_vector); -- state, debugging only
end component SdCardCtrl;
signal s_addr, s_stat, s_ctrl, s_read, s_write : std_logic;
signal continue, busy, hndShk_i, hndShk_o, wr_i, rd_i : std_logic;
signal wait1, waiting, new_trans, new_data_rd, sdc_rst : std_logic;
signal ctrl_err, set_wr_i, clr_wr_i, set_rd_i, clr_rd_i : std_logic;
signal ctrl_err, set_wr_i, set_rd_i : std_logic;
signal do_reset, do_reset1 : std_logic;
signal data_rd, data_rd_reg, data_wr_reg : reg8;
signal error_o : reg16;
signal addr_reg : reg32;
signal sel_data_out : reg3;
signal state : reg5;
signal w : reg5;
begin
U_SDcard: SdCardCtrl
generic map (50.0, 0.400, 25.0, 512, SD_CARD_E)
-- generic map (50.0, 0.400, 12.5, 512, SD_CARD_E)
generic map (50.0, 25.0, 25.0, 512, SD_CARD_E)
port map (clk, sdc_rst, rd_i, wr_i, '0', addr_reg,
data_wr_reg, data_rd, busy, hndshk_i, open, error_o,
-- data_wr_reg, data_rd, busy, hndshk_i, hndshk_o, error_o,
sdc_cs, sdc_clk, sdc_mosi_o, sdc_mosi_i);
sdc_cs, sdc_clk, sdc_mosi_o, sdc_miso_i, state);
hndshk_i <= waiting;
......@@ -1076,7 +1079,7 @@ begin
waiting <= w;
end process U_WAIT;
rdy <= not(wait1 or waiting); -- wait for 260ns
rdy <= not(wait1 or waiting); -- wait for controller
new_data_rd <= not(hndshk_o);
U_W1: FFDsimple port map (clk, rst, wait1, w(0));
......@@ -1103,25 +1106,21 @@ begin
s_write <= '0' when sel = '0' and addr = b"01" and wr = '0' else '1';
s_read <= '0' when sel = '0' and addr = b"01" and wr = '1' else '1';
s_ctrl <= '1' when sel = '0' and addr = b"10" and wr = '1' else '0';
s_ctrl <= '1' when sel = '0' and addr = b"10" and wr = '0' else '0';
s_stat <= '1' when sel = '0' and addr = b"11" and wr = '1' else '0';
do_reset <= '1' when s_ctrl = '1' and data_inp(4) = '1' else '0';
U_RESET1: FFDsimple port map (clk, rst, do_reset, do_reset1);
sdc_rst <= not(rst) or do_reset or do_reset1; -- held for 2 cycles
-- set_wr_i <= '1' when else '0';
-- clr_wr_i <= rst and s_write;
set_wr_i <= (s_ctrl and data_inp(0)) or (wr_i and s_write);
U_WR_STROBE: FFDsimple port map (clk, clr_wr_i, set_wr_i, wr_i);
sdc_rst <= not(rst) or do_reset or do_reset1; -- held HI for 2 cycles
-- set_rd_i <= '1' when s_ctrl = '1' and data_inp(1) = '1' else '0';
-- clr_rd_i <= rst and s_read;
-- hold wr_i active until first access to WR-register
set_wr_i <= ((s_ctrl and data_inp(0)) or (wr_i and s_write)) and s_write;
U_WR_STROBE: FFDsimple port map (clk, rst, set_wr_i, wr_i);
set_rd_i <= (s_ctrl and data_inp(1)) or (rd_i and s_read);
U_RD_STROBE: FFDsimple port map (clk, clr_rd_i, set_rd_i, rd_i);
-- hold rd_i active until first access to RD-register
set_rd_i <= ((s_ctrl and data_inp(1)) or (rd_i and s_read)) and s_read;
U_RD_STROBE: FFDsimple port map (clk, rst, set_rd_i, rd_i);
ctrl_err <= wr_i and rd_i; -- cannot both read AND write
......@@ -1140,7 +1139,7 @@ begin
data_out <= addr_reg when "000",
x"000000" & data_rd_reg when "001",
x"000000" & b"000" & ctrl_err & b"00" & rd_i & wr_i when "010",
busy & ctrl_err & b"00" & x"000" & error_o when "011",
busy & ctrl_err & b"00" & b"000" & state & x"0" & error_o when "011",
(others => 'X') when others;
end behavioral;
......
......@@ -41,13 +41,13 @@ architecture TB of tb_cMIPS is
sel : in std_logic;
rdy : out std_logic;
wr : in std_logic;
addr : in std_logic_vector; -- a03, a02
addr : in std_logic_vector; -- a03, a02
data_inp : in std_logic_vector;
data_out : out std_logic_vector;
sdc_cs : out std_logic; -- SDcard chip-select
sdc_clk : out std_logic; -- SDcard serial clock
sdc_mosi_o : out std_logic; -- SDcard serial data out (to card)
sdc_mosi_i : in std_logic; -- SDcard serial data inp (fro card)
sdc_miso_i : in std_logic; -- SDcard serial data inp (fro card)
irq : out std_logic); -- interrupt request (not yet used)
end component SDCard;
......@@ -477,7 +477,7 @@ architecture TB of tb_cMIPS is
signal LCD_DATA : std_logic_vector(7 downto 0); -- LCD data bus
signal LCD_RS, LCD_RW, LCD_EN, LCD_BLON : std_logic; -- LCD control
signal uart_txd, uart_rxd, uart_rts, uart_cts, uart_irq : std_logic;
signal sdc_cs, sdc_clk, sdc_mosi_o, sdc_mosi_i : std_logic;
signal sdc_cs, sdc_clk, sdc_mosi_o, sdc_miso_i : std_logic;
signal sdcke, sdscs, sdras, sdcas, sdwe : std_logic; -- SDRAM
......@@ -659,7 +659,7 @@ begin -- TB
U_sdcard: SDcard
port map (rst, clk, io_sdc_sel, io_sdc_wait,
wr, d_addr(3 downto 2), cpu_data, sdc_d_out,
sdc_cs, sdc_clk, sdc_mosi_o, sdc_mosi_i, open);
sdc_cs, sdc_clk, sdc_mosi_o, sdc_miso_i, open);
U_FPU: FPU
port map (rst,clk, io_FPU_sel, io_FPU_wait, wr, d_addr(5 downto 2),
......
......@@ -21,15 +21,16 @@
-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- control register, least significant byte only
-- b0..b2: transmit/receive clock speed
-- b2..b0: transmit/receive clock speed
-- 000: 1/4 CPU clock rate -- for VHDL/C debugging only
-- 001: 1/8 CPU clock rate -- for VHDL/C debugging only
-- 010: 1/16 CPU clock rate -- for VHDL/C debugging only
-- 011: 115.200 baud
-- 100: 57.600 baud
-- 101: 38.400 baud
-- 110: 28.800 baud
-- 111: 19.200 baud
-- 011: 1/32 CPU clock rate -- for VHDL/C debugging only
-- 100: 230.400 baud
-- 100: 115.200 baud
-- 101: 57.600 baud
-- 110: 19.200 baud
-- 111: 9.600 baus
-- b3=1: signal interrupt on RX buffer full, when a new octet is available
-- b4=1: signal interrupt on TX buffer empty, when TX space is available
-- b5,b6: ignored, not used
......@@ -566,23 +567,22 @@ begin
tx_baud_div <= 4/2 when b"000",
8/2 when b"001",
16/2 when b"010",
434/2 when b"011",
868/2 when b"100",
1302/2 when b"101",
1736/2 when b"110",
-- 2604/2 when others;
-- 3472/2 when b"110",
5208/2 when others;
32/2 when b"011",
217/2 when b"100", -- 230.400
434/2 when b"101", -- 115.200
868/2 when b"110", -- 57.600
2604/2 when b"110", -- 19.200
5208/2 when others; -- 9.600
-- 000: 1/4 CPU clock rate -- for VHDL/C debugging only
-- 001: 1/8 CPU clock rate -- for VHDL/C debugging only
-- 010: 1/16 CPU clock rate -- for VHDL/C debugging only
-- 011: 115.200 baud
-- 100: 57.600 baud
-- 101: 38.400 baud
-- 110: 28.800 baud
-- 111: 9.600 baus -- 19.200 baud
-- 011: 1/32 CPU clock rate -- for VHDL/C debugging only
-- 100: 230.400 baud
-- 100: 115.200 baud
-- 101: 57.600 baud
-- 110: 19.200 baud
-- 111: 9.600 baus
-- max divisor would be 50,000,000 / 1,200 bps = 46.667 < 64k-1
U_bit_rt_tx: process(clk, rst, tx_ld, en_tx_clk)
......@@ -618,13 +618,12 @@ begin
rx_baud_div <= 4/2 when b"000",
8/2 when b"001",
16/2 when b"010",
434/2 when b"011",
868/2 when b"100",
1302/2 when b"101",
1736/2 when b"110",
-- 2604/2 when others;
-- 3472/2 when b"110",
5208/2 when others;
32/2 when b"011",
217/2 when b"100", -- 230.400
434/2 when b"101", -- 115.200
868/2 when b"110", -- 57.600
2604/2 when b"110", -- 19.200
5208/2 when others; -- 9.600
U_bit_rt_rx: process(clk, rst, reset_rxck, en_rx_clk)
variable baud_cnt : integer range 0 to 65535;
......@@ -1062,13 +1061,12 @@ begin
tx_baud_div <= 4/2 when b"000",
8/2 when b"001",
16/2 when b"010",
434/2 when b"011",
868/2 when b"100",
1302/2 when b"101",
1736/2 when b"110",
-- 2604/2 when others;
-- 3472/2 when b"110",
5208/2 when others;
32/2 when b"011",
217/2 when b"100", -- 230.400
434/2 when b"101", -- 115.200
868/2 when b"110", -- 57.600
2604/2 when b"110", -- 19.200
5208/2 when others; -- 9.600
U_bit_rt_tx: process(clk, rst)
variable baud_cnt : integer;
......@@ -1092,13 +1090,12 @@ begin
rx_baud_div <= 4/2 when b"000",
8/2 when b"001",
16/2 when b"010",
434/2 when b"011",
868/2 when b"100",
1302/2 when b"101",
1736/2 when b"110",
-- 2604/2 when others;
-- 3472/2 when b"110",
5208/2 when others;
32/2 when b"011",
217/2 when b"100", -- 230.400
434/2 when b"101", -- 115.200
868/2 when b"110", -- 57.600
2604/2 when b"110", -- 19.200
5208/2 when others; -- 9.600
U_bit_rt_rx: process(clk, rst, reset_rxck, rx_run)
variable baud_cnt : integer;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment