diff --git a/DialogueCPU.vhd b/DialogueCPU.vhd index 36fae135fb3a6a0a7c7023e563c93a4e04292afc..f33db23efd438f959229582ee5e8f6b0d4547176 100644 --- a/DialogueCPU.vhd +++ b/DialogueCPU.vhd @@ -35,8 +35,8 @@ architecture archDialogueCPU of DialogueCPU is begin - sortie <= '0' when (WR = '1') and (RD = '0') and (A0 = '0') and ((D_RW = Least) or (D_RW = Most) or (D_RW = LeastMost)) else '1'; - --sortie <= '0' when (WR = '1') and (RD = '0') and ( ((A0 = '1') and ((D_RW = Least) or (D_RW = Most) or (D_RW = LeastMost))) or (A0 = '0') ) else '1'; + --sortie <= '0' when (WR = '1') and (RD = '0') and (A0 = '0') and ((D_RW = Least) or (D_RW = Most) or (D_RW = LeastMost)) else '1'; + sortie <= '0' when (WR = '1') and (RD = '0') and ( ((A0 = '1') and ((D_RW = Least) or (D_RW = Most) or (D_RW = LeastMost))) or (A0 = '0') ) else '1'; ReceptData : process(CS) begin @@ -129,13 +129,9 @@ architecture archImplantation of DialogueCPU is signal EtatW_q, EtatR_q : state := L; signal EtatW, EtatR : state; - signal ctrlWord : std_logic_vector(7 downto 0) ; + signal ctrlWord : std_logic_vector(7 downto 0) := x"00"; alias RW_op : std_logic_vector(1 downto 0) is ctrlWord(5 downto 4); - alias D_RW : std_logic_vector(1 downto 0) is D(5 downto 4); - - alias d_buf_inMSB : std_logic_vector(7 downto 0) is d_buf_in(15 downto 8); - alias d_buf_inLSB : std_logic_vector(7 downto 0) is d_buf_in( 7 downto 0); - + alias d_buf_outMSB : std_logic_vector(7 downto 0) is d_buf_out(15 downto 8); alias d_buf_outLSB : std_logic_vector(7 downto 0) is d_buf_out( 7 downto 0); @@ -144,7 +140,7 @@ architecture archImplantation of DialogueCPU is constant Most : std_logic_vector(1 downto 0) := "10"; constant LeastMost : std_logic_vector(1 downto 0) := "11"; - constant inputVectWidth : integer := 29; + constant inputVectWidth : integer := 46; COMPONENT DFFEXb generic(width : integer := inputVectWidth); @@ -156,28 +152,101 @@ architecture archImplantation of DialogueCPU is end COMPONENT; signal inputVect : std_logic_vector((inputVectWidth-1) downto 0) ; + signal outputVect : std_logic_vector((inputVectWidth-1) downto 0) := (OTHERS => '0'); + signal latch_d_temp : std_logic; + signal d_buf_in_temp : std_logic_vector(15 downto 0) ; + + alias D_q : std_logic_vector(7 downto 0) is outputVect(7 downto 0); + alias D_RW_q : std_logic_vector(1 downto 0) is outputVect(5 downto 4) ; + alias RD_q : std_logic is outputVect(8) ; + alias WR_q : std_logic is outputVect(9) ; + alias A0_q : std_logic is outputVect(10) ; + alias d_buf_q : std_logic_vector(15 downto 0) is outputVect(26 downto 11) ; + alias RW_op_q : std_logic_vector(1 downto 0) is outputVect(28 downto 27) ; + alias latch_d_q : std_logic is outputVect(29); + alias d_buf_inLSB_q : std_logic_vector(7 downto 0) is outputVect(37 downto 30) ; + alias d_buf_inMSB_q : std_logic_vector(7 downto 0) is outputVect(45 downto 38) ; + + alias d_buf_in_tempLSB : std_logic_vector(7 downto 0) is d_buf_in_temp( 7 downto 0); + alias d_buf_in_tempMSB : std_logic_vector(7 downto 0) is d_buf_in_temp(15 downto 8); - alias D_q : std_logic_vector(7 downto 0) is inputVect(7 downto 0) ; - alias RD_q : std_logic is inputVect(8); - alias WR_q : std_logic is inputVect(9); - alias A0_q : std_logic is inputVect(10); - alias d_buf_q : std_logic_vector(15 downto 0) is inputVect(26 downto 11) ; - alias RW_op_q : std_logic_vector(1 downto 0) is inputVect(28 downto 27) ; - - begin + -- avoid using a buffer in the declaration of the entity + latch_d <= latch_d_temp; + d_buf_in <= d_buf_in_temp; + -- signals required to set the output signal of the entity stored in the same vector (whitout EtatW annd EtatR because there aren't std_logic) + inputVect <= (d_buf_in_temp & latch_d_temp & RW_op & d_buf_out & A0 & WR & RD & D) ; - inputVect <= ( RW_op & d_buf_out & A0 & WR & RD & D) ; + bascule_D_CS : DFFEXb + PORT MAP(CS, inputVect, outputVect); + -- dedicated DFF to store EtatR and EtatW DFF_Etats_W_R : process( CS ) begin if rising_edge(CS) then - EtatW_q <= EtatW_q; - EtatR_q <= EtatR_q; + EtatW_q <= EtatW; + EtatR_q <= EtatR; end if ; end process ; -- DFF_Etats_W_R + + + -- output functions + -- '0' force the output of the timer to 0, '1' allow the counter to modify the output of the timer + Sortie <= '0' when ((WR_q='1') and (RD_q='0') and ( + ((A0_q = '1') and (not(D_RW_q=Latch))) --Receive controle word without counter latch command + or (A0_q = '0') --Load data in the counter + )) + else '1'; + -- '0' = false, '1' = true + charg_d <= '1' when ((WR_q='1') and (RD_q='0') and (A0_q = '0') and ( -- test if instruction is a load of counter + ((EtatW_q = L) and (RW_op_q = Least)) -- if instruction load only lsb bytes + or ((EtatW_q = M) and ((RW_op_q = Most) or (RW_op_q = LeastMost))) -- if instruction load only msb bytes or all bytes (and reading MSB bytes) + )) + else '0'; + + latch_d_temp <= '1' + when ((WR_q='1') and (RD_q='0') and (A0_q = '1') and (D_RW_q=Latch)) -- if instruction is writing a control world + else '0' when (((WR_q='0') and (RD_q='1') and (A0_q = '0') and ( -- test if instruction is a read of counter + ((EtatW_q = L) and (RW_op_q = Least)) -- if instruction readonly lsb bytes + or ((EtatW_q = M) and ((RW_op_q = Most) or (RW_op_q = LeastMost))) -- if instruction readonly msb bytes or all bytes (and reading MSB bytes) + )) + or ((WR_q='1') and (RD_q='0') and (A0_q = '1') and (not(D_RW_q=Latch))) -- if instruction is writing a control world without latch as RW command + ) + else latch_d_q; -- keep the previous value of latch + + + RW_op <= D_RW_q when ((WR_q='1') and (RD_q='0') and (A0_q = '1') and (not(D_RW_q=Latch))) -- if instruction is writing a control world without latch as RW command + else RW_op_q; -- keep the previous value of RW_op + + d_buf_in_tempLSB <= D_q when ((WR_q='1') and (RD_q='0') and (A0_q = '0') and (EtatW_q = L)) -- transfer of the LSB from D to d_buf_in(7 downto 0) + else "00000000" when ((WR_q='1') and (RD_q='0') and (A0_q = '0') and (EtatW_q = M) and (RW_op_q = Most)) -- if we only load the MSB force x"00" to d_buf_in(7 downto 0) + else d_buf_inLSB_q; -- keep the previous value of the variable + + d_buf_in_tempMSB <= D_q when ((WR_q='1') and (RD_q='0') and (A0_q = '0') and (EtatW_q = M)) -- transfer of the MSB from D to d_buf_in(15 downto 8) + else "00000000" when ((WR_q='1') and (RD_q='0') and (A0_q = '0') and (EtatW_q = L) and (RW_op_q = Least)) -- if we only load the MSB force x"00" to d_buf_in(15 downto 8) + else d_buf_inMSB_q; -- keep the previous value of the variable + -- the CPU maintain (WR='0') and (RD='1') to keep value of dbuf_out on D if the CPU prepare an other instruction dialogue CPU set D as HiZ so the CPU can write on it + D <= d_buf_outLSB when ((WR_q='0') and (RD_q='1') and (A0_q = '0') and (EtatW_q = L) and (WR='0') and (RD='1')) -- transfer of the LSB from d_buf_out( 7 downto 0) to D + else d_buf_outMSB when ((WR_q='0') and (RD_q='1') and (A0_q = '0') and (EtatW_q = M) and (WR='0') and (RD='1')) -- transfer of the MSB from d_buf_out(15 downto 8) to D + else "ZZZZZZZZ"; -- other instruction does not impact the bus + + EtatW <= M when (((WR_q='1') and (RD_q='0') and (A0_q = '0') and (EtatW_q = L) and (RW_op_q = LeastMost)) -- if loading in leastMost mode and EtatW_q = L + or ((WR_q='1') and (RD_q='0') and (A0_q = '1') and (D_RW_q = Most))) -- if writing control word D_RW and mode is leastMost or Least + + else L when (((WR_q='1') and (RD_q='0') and (A0_q = '0') and (EtatW_q = M) and (RW_op_q = LeastMost)) -- if loading in leastMost mode and EtatW_q = M + or ((WR_q='1') and (RD_q='0') and (A0_q = '1') and ((D_RW_q = LeastMost) or (D_RW_q = Least)))) -- if writing control word D_RW and mode is Most + + else EtatW_q; -- keep previous value + + EtatR <= M when (((WR_q='0') and (RD_q='1') and (A0_q = '0') and (EtatW_q = L) and (RW_op_q = LeastMost)) -- if reading in leastMost mode and EtatW_q = L + or ((WR_q='1') and (RD_q='0') and (A0_q = '1') and (D_RW_q = Most))) -- if writing control word D_RW and mode is leastMost or Least + + else L when (((WR_q='0') and (RD_q='1') and (A0_q = '0') and (EtatW_q = M) and (RW_op_q = LeastMost)) -- if reading in leastMost mode and EtatW_q = M + or ((WR_q='1') and (RD_q='0') and (A0_q = '1') and ((D_RW_q = LeastMost) or (D_RW_q = Least)))) -- if writing control word D_RW and mode is Most + + else EtatR_q; -- keep previous value end archImplantation ; -- archImplantation diff --git a/Reg16b.vhd b/Reg16b.vhd index ee442157be432d91294fc635439e1afdc33fe963..94d4d54af099803cffc0d5572971a08761481b41 100644 --- a/Reg16b.vhd +++ b/Reg16b.vhd @@ -12,7 +12,6 @@ end Reg16b ; architecture archReg16b of Reg16b is - begin Reg : process( clk, ena) @@ -23,3 +22,18 @@ begin end process ; -- Reg end architecture ; -- archReg16b + +architecture archLatch16b of Reg16b is + + +begin + + Q <= Din when (ena = '1'); + -- latch : process(clk, ) + -- begin + -- if ena = '1' then + + -- end if ; + -- end process ; -- latch + +end archLatch16b ; -- archLatch16b \ No newline at end of file diff --git a/Simulation/TestTimer8254.do b/Simulation/TestTimer8254.do index 89e4941f255e588520e2b56dafea6ce8750ce106..cd589b6a0b05905ea75b66eef7275d182ad3bc33 100644 --- a/Simulation/TestTimer8254.do +++ b/Simulation/TestTimer8254.do @@ -62,7 +62,7 @@ proc wave_cfg { } { # #> main cmd: add wave signal-name - restart all + restart -nowave all wave_cfg @@ -72,9 +72,9 @@ proc wave_cfg { } { add wave -label " clk " test_timer/clk add wave -divider " | Cmd CPU | " - add wave -label " A0 " test_timer/A0 add wave -label " WR " test_timer/WR add wave -label " RD " test_timer/RD + add wave -label " A0 " test_timer/A0 add wave -label " Gate " test_timer/Gate add wave -divider " | Controle World | " @@ -102,6 +102,24 @@ proc wave_cfg { } { add wave -label " Latch " test_timer/timer/latch_d + add wave -divider " | Sortie registre Dialogue CPU | " + add wave -label " WR_q " test_timer/timer/D_CPU/WR_q + add wave -label " RD_q " test_timer/timer/D_CPU/RD_q + add wave -label " A0_q " test_timer/timer/D_CPU/A0_q + + add wave -divider " | Bus sauvegardés | " + add wave -hex -label " d_buf_q " test_timer/timer/D_CPU/d_buf_q + add wave -label " D_RW_q " test_timer/timer/D_CPU/D_RW_q + + add wave -divider " | input internes Dialogue CPU | " + + add wave -label " EtatW_q " test_timer/timer/D_CPU/EtatW_q + add wave -label " EtatR_q " test_timer/timer/D_CPU/EtatR_q + add wave -label " RW_op_q " test_timer/timer/D_CPU/RW_op_q + add wave -label " latch_d_q " test_timer/timer/D_CPU/latch_d_q + add wave -label " latch_d_temp " test_timer/timer/D_CPU/latch_d_temp + + #----- # signal assignments # diff --git a/Test_timer.vhd b/Test_timer.vhd index 7405c31acab5b65c064321adfc37623479f5f2db..9f3e4bd057ae8fce8769e48898e55fc60a553e06 100644 --- a/Test_timer.vhd +++ b/Test_timer.vhd @@ -18,8 +18,8 @@ ARCHITECTURE archTestTimer OF Test_timer IS ); END COMPONENT; - signal clk, RD, WR, A0, CS, gate, sortie : std_logic; - signal D : std_logic_vector(7 downto 0) ; + signal clk, RD, WR, A0, CS, gate, sortie : std_logic := '0'; + signal D : std_logic_vector(7 downto 0) := "ZZZZZZZZ"; BEGIN @@ -27,13 +27,14 @@ BEGIN timer : Timer8254 PORT MAP(clk, RD, WR, A0, CS, gate ,sortie, D); - A0 <= '1', '0' after 100 ns, '1' after 900 ns, '0' after 1000 ns ; - WR <= '1'; --, '1' after 100 ns, '1' after 900 ns, '1' after 1000 ns ; - RD <= '0'; - CS <= '0', '1' after 50 ns, '0' after 100 ns, '1' after 150 ns, '0' after 200 ns, '1' after 250 ns, '0' after 900 ns, '1' after 950 ns, '0' after 1000 ns, '1' after 1050 ns; + WR <= '1' , '0' after 1600 ns, '1' after 2000 ns; --, '1' after 100 ns, '1' after 900 ns, '1' after 1000 ns ; + RD <= '0' , '1' after 1600 ns, '0' after 2000 ns; + A0 <= '1', '0' after 100 ns, '1' after 900 ns, '0' after 1000 ns, '1' after 1500 ns, '0' after 1600 ns, '1' after 2000 ns; + + CS <= '0', '1' after 50 ns, '0' after 100 ns, '1' after 150 ns, '0' after 200 ns, '1' after 250 ns, '0' after 900 ns, '1' after 950 ns, '0' after 1000 ns, '1' after 1050 ns, '0' after 1100 ns, '1' after 1550 ns, '0' after 1600 ns, '1' after 1650 ns, '0' after 1700 ns, '1' after 2050 ns, '0' after 2100 ns; gate <= '1' after 275 ns; -- D <= x"7C", x"06" after 100 ns, x"00" after 200 ns, "ZZZZZZZZ" after 285 ns; - D <= x"1C", x"06" after 100 ns, "ZZZZZZZZ" after 200 ns, x"2C" after 900 ns, x"01" after 1000 ns, "ZZZZZZZZ" after 1100 ns; + D <= x"1C", x"06" after 100 ns, "ZZZZZZZZ" after 200 ns, x"2C" after 900 ns, x"01" after 1000 ns, "ZZZZZZZZ" after 1100 ns, x"1C" after 1500 ns, "ZZZZZZZZ" after 1600 ns, x"05" after 2000 ns; clock : process diff --git a/Timer8254.vhd b/Timer8254.vhd index bff7d51292f35d9aabfd27ee44d35d70b0e529ff..3d756986e41b02938c894292ae8f6872319a8573 100644 --- a/Timer8254.vhd +++ b/Timer8254.vhd @@ -16,7 +16,7 @@ architecture archTimer of Timer8254 is signal d_buf_out, d_buf_in, count_val: std_logic_vector(15 downto 0); - signal charg_d_dcpu, charg_d, latch_d, Reset_ask, out_cpt, out_DCPU: std_logic; + signal charg_d_dcpu, charg_d, latch_d, Reset_ask, out_cpt, out_DCPU, ena : std_logic; component Decompt_Mode_0 IS GENERIC (width : integer := 16); @@ -55,17 +55,20 @@ architecture archTimer of Timer8254 is begin - D_CPU : entity work.DialogueCPU(archDialogueCPU) + D_CPU : entity work.DialogueCPU(archImplantation) PORT MAP(RD, WR, A0, CS, out_DCPU, D, d_buf_out, d_buf_in, charg_d_dcpu, latch_d); CptM0 : Decompt_Mode_0 PORT MAP(clk,gate, charg_d, CS, d_buf_in, count_val, out_cpt, Reset_ask); charg_d <= (charg_d_dcpu and (not Reset_ask)); - - Latch : Reg16b - PORT MAP(clk, latch_d, count_val, d_buf_out); + ena <= not latch_d; + Latch : entity work.Reg16b(archReg16b) + PORT MAP(CS, ena, count_val, d_buf_out); + + Sortie <= ((out_DCPU or Reset_Ask) and out_cpt); +-- output of the timer is force to 0 if out_DCPU = 0 and Reset_Ask = 0 +-- <=> the timer is configured (write of control word or load constant in timer) AND no load is pending +-- A load is in pending when the counter is waiting for a rising edge to set a new value - Sortie <= (out_DCPU and out_cpt); - end architecture ; -- archTimer \ No newline at end of file