diff --git a/common.vhdl b/common.vhdl index f08ecd1..31bd920 100644 --- a/common.vhdl +++ b/common.vhdl @@ -244,6 +244,7 @@ package common is others => (others => '0')); type Loadstore1ToExecute1Type is record + busy : std_ulogic; exception : std_ulogic; invalid : std_ulogic; perm_error : std_ulogic; diff --git a/control.vhdl b/control.vhdl index 55f5649..5e557c4 100644 --- a/control.vhdl +++ b/control.vhdl @@ -15,7 +15,8 @@ entity control is complete_in : in std_ulogic; valid_in : in std_ulogic; flush_in : in std_ulogic; - stall_in : in std_ulogic; + busy_in : in std_ulogic; + deferred : in std_ulogic; sgl_pipe_in : in std_ulogic; stop_mark_in : in std_ulogic; @@ -23,6 +24,9 @@ entity control is gpr_write_in : in gspr_index_t; gpr_bypassable : in std_ulogic; + update_gpr_write_valid : in std_ulogic; + update_gpr_write_reg : in gspr_index_t; + gpr_a_read_valid_in : in std_ulogic; gpr_a_read_in : in gspr_index_t; @@ -72,7 +76,11 @@ begin ) port map ( clk => clk, - stall_in => stall_in, + busy_in => busy_in, + deferred => deferred, + complete_in => complete_in, + flush_in => flush_in, + issuing => valid_out, gpr_write_valid_in => gpr_write_valid, gpr_write_in => gpr_write_in, @@ -80,6 +88,9 @@ begin gpr_read_valid_in => gpr_a_read_valid_in, gpr_read_in => gpr_a_read_in, + ugpr_write_valid => update_gpr_write_valid, + ugpr_write_reg => update_gpr_write_reg, + stall_out => stall_a_out, use_bypass => gpr_bypass_a ); @@ -90,7 +101,11 @@ begin ) port map ( clk => clk, - stall_in => stall_in, + busy_in => busy_in, + deferred => deferred, + complete_in => complete_in, + flush_in => flush_in, + issuing => valid_out, gpr_write_valid_in => gpr_write_valid, gpr_write_in => gpr_write_in, @@ -98,6 +113,9 @@ begin gpr_read_valid_in => gpr_b_read_valid_in, gpr_read_in => gpr_b_read_in, + ugpr_write_valid => update_gpr_write_valid, + ugpr_write_reg => update_gpr_write_reg, + stall_out => stall_b_out, use_bypass => gpr_bypass_b ); @@ -110,7 +128,11 @@ begin ) port map ( clk => clk, - stall_in => stall_in, + busy_in => busy_in, + deferred => deferred, + complete_in => complete_in, + flush_in => flush_in, + issuing => valid_out, gpr_write_valid_in => gpr_write_valid, gpr_write_in => gpr_write_in, @@ -118,6 +140,9 @@ begin gpr_read_valid_in => gpr_c_read_valid_in, gpr_read_in => gpr_c_read_in_fmt, + ugpr_write_valid => update_gpr_write_valid, + ugpr_write_reg => update_gpr_write_reg, + stall_out => stall_c_out, use_bypass => gpr_bypass_c ); @@ -128,7 +153,11 @@ begin ) port map ( clk => clk, - stall_in => stall_in, + busy_in => busy_in, + deferred => deferred, + complete_in => complete_in, + flush_in => flush_in, + issuing => valid_out, cr_read_in => cr_read_in, cr_write_in => cr_write_valid, @@ -139,7 +168,8 @@ begin control0: process(clk) begin if rising_edge(clk) then - assert r_int.outstanding >= 0 and r_int.outstanding <= (PIPELINE_DEPTH+1) report "Outstanding bad " & integer'image(r_int.outstanding) severity failure; + assert rin_int.outstanding >= 0 and rin_int.outstanding <= (PIPELINE_DEPTH+1) + report "Outstanding bad " & integer'image(rin_int.outstanding) severity failure; r_int <= rin_int; end if; end process; @@ -152,17 +182,18 @@ begin v_int := r_int; -- asynchronous - valid_tmp := valid_in and not flush_in and not stall_in; - stall_tmp := stall_in; + valid_tmp := valid_in and not flush_in; + stall_tmp := '0'; - if complete_in = '1' then + if flush_in = '1' then + -- expect to see complete_in next cycle + v_int.outstanding := 1; + elsif complete_in = '1' then v_int.outstanding := r_int.outstanding - 1; end if; if rst = '1' then - v_int.state := IDLE; - v_int.outstanding := 0; - stall_tmp := '0'; + v_int := reg_internal_init; valid_tmp := '0'; end if; @@ -227,7 +258,9 @@ begin end if; if valid_tmp = '1' then - v_int.outstanding := v_int.outstanding + 1; + if deferred = '0' then + v_int.outstanding := v_int.outstanding + 1; + end if; gpr_write_valid <= gpr_write_valid_in; cr_write_valid <= cr_write_in; else @@ -237,7 +270,7 @@ begin -- update outputs valid_out <= valid_tmp; - stall_out <= stall_tmp; + stall_out <= stall_tmp or deferred; -- update registers rin_int <= v_int; diff --git a/core.vhdl b/core.vhdl index 4d84b4a..13f3ce7 100644 --- a/core.vhdl +++ b/core.vhdl @@ -82,11 +82,10 @@ architecture behave of core is signal icache_stall_out : std_ulogic; signal icache_stall_in : std_ulogic; signal decode1_stall_in : std_ulogic; - signal decode2_stall_in : std_ulogic; + signal decode2_busy_in : std_ulogic; signal decode2_stall_out : std_ulogic; signal ex1_icache_inval: std_ulogic; - signal ex1_stall_out: std_ulogic; - signal ls1_stall_out: std_ulogic; + signal ex1_busy_out: std_ulogic; signal dcache_stall_out: std_ulogic; signal flush: std_ulogic; @@ -235,7 +234,7 @@ begin port map ( clk => clk, rst => rst_dec2, - stall_in => decode2_stall_in, + busy_in => decode2_busy_in, stall_out => decode2_stall_out, flush_in => flush, complete_in => complete, @@ -248,7 +247,7 @@ begin c_out => decode2_to_cr_file, log_out => log_data(119 downto 110) ); - decode2_stall_in <= ex1_stall_out or ls1_stall_out; + decode2_busy_in <= ex1_busy_out; register_file_0: entity work.register_file generic map ( @@ -289,7 +288,7 @@ begin clk => clk, rst => rst_ex1, flush_out => flush, - stall_out => ex1_stall_out, + busy_out => ex1_busy_out, e_in => decode2_to_execute1, l_in => loadstore1_to_execute1, ext_irq_in => ext_irq, @@ -317,7 +316,6 @@ begin m_out => loadstore1_to_mmu, m_in => mmu_to_loadstore1, dc_stall => dcache_stall_out, - stall_out => ls1_stall_out, log_out => log_data(149 downto 140) ); diff --git a/cr_hazard.vhdl b/cr_hazard.vhdl index f6c5f3f..4b79020 100644 --- a/cr_hazard.vhdl +++ b/cr_hazard.vhdl @@ -4,11 +4,15 @@ use ieee.numeric_std.all; entity cr_hazard is generic ( - PIPELINE_DEPTH : natural := 2 + PIPELINE_DEPTH : natural := 1 ); port( clk : in std_ulogic; - stall_in : in std_ulogic; + busy_in : in std_ulogic; + deferred : in std_ulogic; + complete_in : in std_ulogic; + flush_in : in std_ulogic; + issuing : in std_ulogic; cr_read_in : in std_ulogic; cr_write_in : in std_ulogic; @@ -22,7 +26,7 @@ architecture behaviour of cr_hazard is end record; constant pipeline_entry_init : pipeline_entry_type := (valid => '0'); - type pipeline_t is array(0 to PIPELINE_DEPTH-1) of pipeline_entry_type; + type pipeline_t is array(0 to PIPELINE_DEPTH) of pipeline_entry_type; constant pipeline_t_init : pipeline_t := (others => pipeline_entry_init); signal r, rin : pipeline_t := pipeline_t_init; @@ -30,9 +34,7 @@ begin cr_hazard0: process(clk) begin if rising_edge(clk) then - if stall_in = '0' then - r <= rin; - end if; + r <= rin; end if; end process; @@ -41,22 +43,23 @@ begin begin v := r; - stall_out <= '0'; - loop_0: for i in 0 to PIPELINE_DEPTH-1 loop - if (r(i).valid = cr_read_in) then - stall_out <= '1'; - end if; - end loop; - - v(0).valid := cr_write_in; - loop_1: for i in 0 to PIPELINE_DEPTH-2 loop - -- propagate to next slot - v(i+1) := r(i); - end loop; + -- XXX assumes PIPELINE_DEPTH = 1 + if complete_in = '1' then + v(1).valid := '0'; + end if; + stall_out <= cr_read_in and (v(0).valid or v(1).valid); - -- asynchronous output - if cr_read_in = '0' then - stall_out <= '0'; + -- XXX assumes PIPELINE_DEPTH = 1 + if busy_in = '0' then + v(1) := r(0); + v(0).valid := '0'; + end if; + if deferred = '0' and issuing = '1' then + v(0).valid := cr_write_in; + end if; + if flush_in = '1' then + v(0).valid := '0'; + v(1).valid := '0'; end if; -- update registers diff --git a/decode2.vhdl b/decode2.vhdl index 2c02a75..5b8cbc1 100644 --- a/decode2.vhdl +++ b/decode2.vhdl @@ -17,7 +17,7 @@ entity decode2 is rst : in std_ulogic; complete_in : in std_ulogic; - stall_in : in std_ulogic; + busy_in : in std_ulogic; stall_out : out std_ulogic; stopped_out : out std_ulogic; @@ -45,6 +45,8 @@ architecture behaviour of decode2 is signal r, rin : reg_type; + signal deferred : std_ulogic; + signal log_data : std_ulogic_vector(9 downto 0); type decode_input_reg_t is record @@ -200,6 +202,9 @@ architecture behaviour of decode2 is signal gpr_write : gspr_index_t; signal gpr_bypassable : std_ulogic; + signal update_gpr_write_valid : std_ulogic; + signal update_gpr_write_reg : gspr_index_t; + signal gpr_a_read_valid : std_ulogic; signal gpr_a_read :gspr_index_t; signal gpr_a_bypass : std_ulogic; @@ -224,7 +229,8 @@ begin complete_in => complete_in, valid_in => control_valid_in, - stall_in => stall_in, + busy_in => busy_in, + deferred => deferred, flush_in => flush_in, sgl_pipe_in => control_sgl_pipe, stop_mark_in => d_in.stop_mark, @@ -233,6 +239,9 @@ begin gpr_write_in => gpr_write, gpr_bypassable => gpr_bypassable, + update_gpr_write_valid => update_gpr_write_valid, + update_gpr_write_reg => update_gpr_write_reg, + gpr_a_read_valid_in => gpr_a_read_valid, gpr_a_read_in => gpr_a_read, @@ -254,13 +263,17 @@ begin gpr_bypass_c => gpr_c_bypass ); + deferred <= r.e.valid and busy_in; + decode2_0: process(clk) begin if rising_edge(clk) then - if rin.e.valid = '1' then - report "execute " & to_hstring(rin.e.nia); + if rst = '1' or flush_in = '1' or deferred = '0' then + if rin.e.valid = '1' then + report "execute " & to_hstring(rin.e.nia); + end if; + r <= rin; end if; - r <= rin; end if; end process; @@ -358,6 +371,8 @@ begin if EX1_BYPASS and d_in.decode.unit = ALU then gpr_bypassable <= '1'; end if; + update_gpr_write_valid <= d_in.decode.update; + update_gpr_write_reg <= decoded_reg_a.reg; gpr_a_read_valid <= decoded_reg_a.reg_valid; gpr_a_read <= decoded_reg_a.reg; @@ -375,7 +390,7 @@ begin v.e.insn_type := OP_ILLEGAL; end if; - if rst = '1' then + if rst = '1' or flush_in = '1' then v.e := Decode2ToExecute1Init; end if; diff --git a/execute1.vhdl b/execute1.vhdl index 0009699..c234725 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -20,7 +20,7 @@ entity execute1 is -- asynchronous flush_out : out std_ulogic; - stall_out : out std_ulogic; + busy_out : out std_ulogic; e_in : in Decode2ToExecute1Type; l_in : in Loadstore1ToExecute1Type; @@ -48,6 +48,8 @@ end entity execute1; architecture behaviour of execute1 is type reg_type is record e : Execute1ToWritebackType; + busy: std_ulogic; + terminate: std_ulogic; lr_update : std_ulogic; next_lr : std_ulogic_vector(63 downto 0); mul_in_progress : std_ulogic; @@ -62,7 +64,7 @@ architecture behaviour of execute1 is log_addr_spr : std_ulogic_vector(31 downto 0); end record; constant reg_type_init : reg_type := - (e => Execute1ToWritebackInit, lr_update => '0', + (e => Execute1ToWritebackInit, busy => '0', lr_update => '0', terminate => '0', mul_in_progress => '0', div_in_progress => '0', cntz_in_progress => '0', slow_op_insn => OP_ILLEGAL, slow_op_rc => '0', slow_op_oe => '0', slow_op_xerc => xerc_init, next_lr => (others => '0'), ldst_nia => (others => '0'), others => (others => '0')); @@ -71,6 +73,7 @@ architecture behaviour of execute1 is signal a_in, b_in, c_in : std_ulogic_vector(63 downto 0); + signal valid_in : std_ulogic; signal ctrl: ctrl_t := (irq_state => WRITE_SRR0, others => (others => '0')); signal ctrl_tmp: ctrl_t := (irq_state => WRITE_SRR0, others => (others => '0')); signal right_shift, rot_clear_left, rot_clear_right: std_ulogic; @@ -241,6 +244,11 @@ begin b_in <= r.e.write_data when EX1_BYPASS and e_in.bypass_data2 = '1' else e_in.read_data2; c_in <= r.e.write_data when EX1_BYPASS and e_in.bypass_data3 = '1' else e_in.read_data3; + busy_out <= l_in.busy or r.busy; + valid_in <= e_in.valid and not busy_out; + + terminate_out <= r.terminate; + execute1_0: process(clk) begin if rising_edge(clk) then @@ -251,7 +259,7 @@ begin else r <= rin; ctrl <= ctrl_tmp; - assert not (r.lr_update = '1' and e_in.valid = '1') + assert not (r.lr_update = '1' and valid_in = '1') report "LR update collision with valid in EX1" severity failure; if r.lr_update = '1' then @@ -423,9 +431,9 @@ begin end if; end if; - terminate_out <= '0'; + v.terminate := '0'; icache_inval <= '0'; - stall_out <= '0'; + v.busy := '0'; f_out <= Execute1ToFetch1TypeInit; -- send MSR[IR] and ~MSR[PR] up to fetch1 f_out.virt_mode <= ctrl.msr(MSR_IR); @@ -463,10 +471,10 @@ begin f_out.virt_mode <= '0'; f_out.priv_mode <= '1'; f_out.redirect_nia <= ctrl.irq_nia; - v.e.valid := e_in.valid; + v.e.valid := '1'; report "Writing SRR1: " & to_hstring(ctrl.srr1); - elsif irq_valid = '1' and e_in.valid = '1' then + elsif irq_valid = '1' and valid_in = '1' then -- we need two cycles to write srr0 and 1 -- will need more when we have to write HEIR -- Don't deliver the interrupt until we have a valid instruction @@ -474,7 +482,7 @@ begin exception := '1'; ctrl_tmp.srr1 <= msr_copy(ctrl.msr); - elsif e_in.valid = '1' and ctrl.msr(MSR_PR) = '1' and + elsif valid_in = '1' and ctrl.msr(MSR_PR) = '1' and instr_is_privileged(e_in.insn_type, e_in.insn) then -- generate a program interrupt exception := '1'; @@ -484,7 +492,7 @@ begin ctrl_tmp.srr1(63 - 45) <= '1'; report "privileged instruction"; - elsif e_in.valid = '1' and e_in.unit = ALU then + elsif valid_in = '1' and e_in.unit = ALU then report "execute nia " & to_hstring(e_in.nia); @@ -519,7 +527,7 @@ begin -- check bits 1-10 of the instruction to make sure it's attn -- if not then it is illegal if e_in.insn(10 downto 1) = "0100000000" then - terminate_out <= '1'; + v.terminate := '1'; report "ATTN"; else illegal := '1'; @@ -674,7 +682,7 @@ begin when OP_CNTZ => v.e.valid := '0'; v.cntz_in_progress := '1'; - stall_out <= '1'; + v.busy := '1'; when OP_EXTS => -- note data_len is a 1-hot encoding negative := (e_in.data_len(0) and c_in(7)) or @@ -876,21 +884,21 @@ begin when OP_MUL_L64 | OP_MUL_H64 | OP_MUL_H32 => v.e.valid := '0'; v.mul_in_progress := '1'; - stall_out <= '1'; + v.busy := '1'; x_to_multiply.valid <= '1'; when OP_DIV | OP_DIVE | OP_MOD => v.e.valid := '0'; v.div_in_progress := '1'; - stall_out <= '1'; + v.busy := '1'; x_to_divider.valid <= '1'; when others => - terminate_out <= '1'; + v.terminate := '1'; report "illegal"; end case; - v.e.rc := e_in.rc and e_in.valid; + v.e.rc := e_in.rc and valid_in; -- Update LR on the next cycle after a branch link -- @@ -908,10 +916,10 @@ begin v.next_lr := next_nia; v.e.valid := '0'; report "Delayed LR update to " & to_hstring(next_nia); - stall_out <= '1'; + v.busy := '1'; end if; - elsif e_in.valid = '1' then + elsif valid_in = '1' then -- instruction for other units, i.e. LDST v.ldst_nia := e_in.nia; v.e.valid := '0'; @@ -967,7 +975,7 @@ begin end if; v.e.valid := '1'; else - stall_out <= '1'; + v.busy := '1'; v.mul_in_progress := r.mul_in_progress; v.div_in_progress := r.div_in_progress; end if; @@ -988,7 +996,8 @@ begin v.e.exc_write_data := next_nia; end if; ctrl_tmp.irq_state <= WRITE_SRR1; - v.e.valid := '1'; + v.busy := '1'; + v.e.valid := '0'; end if; v.e.write_data := result; @@ -1020,7 +1029,6 @@ begin v.e.exc_write_data := r.ldst_nia; report "ldst exception writing srr0=" & to_hstring(r.ldst_nia); ctrl_tmp.irq_state <= WRITE_SRR1; - v.e.valid := '1'; -- complete the original load or store end if; -- Outputs to loadstore1 (async) @@ -1072,7 +1080,7 @@ begin r.e.write_enable & r.e.valid & f_out.redirect & - stall_out & + r.busy & flush_out; end if; end process; diff --git a/gpr_hazard.vhdl b/gpr_hazard.vhdl index de4f7d2..0fa66c5 100644 --- a/gpr_hazard.vhdl +++ b/gpr_hazard.vhdl @@ -4,11 +4,15 @@ use ieee.numeric_std.all; entity gpr_hazard is generic ( - PIPELINE_DEPTH : natural := 2 + PIPELINE_DEPTH : natural := 1 ); port( clk : in std_ulogic; - stall_in : in std_ulogic; + busy_in : in std_ulogic; + deferred : in std_ulogic; + complete_in : in std_ulogic; + flush_in : in std_ulogic; + issuing : in std_ulogic; gpr_write_valid_in : in std_ulogic; gpr_write_in : in std_ulogic_vector(5 downto 0); @@ -16,6 +20,9 @@ entity gpr_hazard is gpr_read_valid_in : in std_ulogic; gpr_read_in : in std_ulogic_vector(5 downto 0); + ugpr_write_valid : in std_ulogic; + ugpr_write_reg : in std_ulogic_vector(5 downto 0); + stall_out : out std_ulogic; use_bypass : out std_ulogic ); @@ -25,10 +32,13 @@ architecture behaviour of gpr_hazard is valid : std_ulogic; bypass : std_ulogic; gpr : std_ulogic_vector(5 downto 0); + ugpr_valid : std_ulogic; + ugpr : std_ulogic_vector(5 downto 0); end record; - constant pipeline_entry_init : pipeline_entry_type := (valid => '0', bypass => '0', gpr => (others => '0')); + constant pipeline_entry_init : pipeline_entry_type := (valid => '0', bypass => '0', gpr => (others => '0'), + ugpr_valid => '0', ugpr => (others => '0')); - type pipeline_t is array(0 to PIPELINE_DEPTH-1) of pipeline_entry_type; + type pipeline_t is array(0 to PIPELINE_DEPTH) of pipeline_entry_type; constant pipeline_t_init : pipeline_t := (others => pipeline_entry_init); signal r, rin : pipeline_t := pipeline_t_init; @@ -45,50 +55,46 @@ begin begin v := r; + if complete_in = '1' then + v(PIPELINE_DEPTH).valid := '0'; + v(PIPELINE_DEPTH).ugpr_valid := '0'; + end if; + stall_out <= '0'; use_bypass <= '0'; if gpr_read_valid_in = '1' then - if r(0).valid = '1' and r(0).gpr = gpr_read_in then - if r(0).bypass = '1' and stall_in = '0' then - use_bypass <= '1'; - else - stall_out <= '1'; - end if; - end if; - loop_0: for i in 1 to PIPELINE_DEPTH-1 loop - if r(i).valid = '1' and r(i).gpr = gpr_read_in then + loop_0: for i in 0 to PIPELINE_DEPTH loop + if v(i).valid = '1' and r(i).gpr = gpr_read_in then if r(i).bypass = '1' then use_bypass <= '1'; else stall_out <= '1'; end if; end if; + if v(i).ugpr_valid = '1' and r(i).ugpr = gpr_read_in then + stall_out <= '1'; + end if; end loop; end if; - if stall_in = '0' then + -- XXX assumes PIPELINE_DEPTH = 1 + if busy_in = '0' then + v(1) := v(0); + v(0).valid := '0'; + v(0).ugpr_valid := '0'; + end if; + if deferred = '0' and issuing = '1' then v(0).valid := gpr_write_valid_in; v(0).bypass := bypass_avail; v(0).gpr := gpr_write_in; - loop_1: for i in 1 to PIPELINE_DEPTH-1 loop - -- propagate to next slot - v(i).valid := r(i-1).valid; - v(i).bypass := r(i-1).bypass; - v(i).gpr := r(i-1).gpr; - end loop; - - else - -- stage 0 stalled, so stage 1 becomes empty - loop_1b: for i in 1 to PIPELINE_DEPTH-1 loop - -- propagate to next slot - if i = 1 then - v(i).valid := '0'; - else - v(i).valid := r(i-1).valid; - v(i).bypass := r(i-1).bypass; - v(i).gpr := r(i-1).gpr; - end if; - end loop; + v(0).ugpr_valid := ugpr_write_valid; + v(0).ugpr := ugpr_write_reg; + end if; + if flush_in = '1' then + v(0).valid := '0'; + v(0).ugpr_valid := '0'; + v(1).valid := '0'; + v(1).ugpr_valid := '0'; end if; -- update registers diff --git a/loadstore1.vhdl b/loadstore1.vhdl index 6e71df9..4140244 100644 --- a/loadstore1.vhdl +++ b/loadstore1.vhdl @@ -25,7 +25,6 @@ entity loadstore1 is m_in : in MmuToLoadstore1Type; dc_stall : in std_ulogic; - stall_out : out std_ulogic; log_out : out std_ulogic_vector(9 downto 0) ); @@ -47,6 +46,7 @@ architecture behave of loadstore1 is ); type reg_stage_t is record + busy : std_ulogic; -- latch most of the input request load : std_ulogic; tlbie : std_ulogic; @@ -123,6 +123,7 @@ begin if rising_edge(clk) then if rst = '1' then r.state <= IDLE; + r.busy <= '0'; else r <= rin; end if; @@ -499,6 +500,7 @@ begin l_out.store_done <= d_in.store_done; -- update exception info back to execute1 + e_out.busy <= r.busy; e_out.exception <= exception; e_out.instr_fault <= r.instr_fault; e_out.invalid <= m_in.invalid; @@ -513,7 +515,7 @@ begin end if; end if; - stall_out <= stall; + v.busy := stall; -- Update registers rin <= v; @@ -523,7 +525,7 @@ begin ls1_log: process(clk) begin if rising_edge(clk) then - log_data <= stall_out & + log_data <= r.busy & e_out.exception & l_out.valid & m_out.valid & diff --git a/writeback.vhdl b/writeback.vhdl index 60afebb..d02a0b1 100644 --- a/writeback.vhdl +++ b/writeback.vhdl @@ -22,27 +22,33 @@ end entity writeback; architecture behaviour of writeback is begin - writeback_1: process(all) + writeback_0: process(clk) variable x : std_ulogic_vector(0 downto 0); variable y : std_ulogic_vector(0 downto 0); variable w : std_ulogic_vector(0 downto 0); + begin + if rising_edge(clk) then + -- Do consistency checks only on the clock edge + x(0) := e_in.valid; + y(0) := l_in.valid; + assert (to_integer(unsigned(x)) + to_integer(unsigned(y))) <= 1 severity failure; + + x(0) := e_in.write_enable or e_in.exc_write_enable; + y(0) := l_in.write_enable; + assert (to_integer(unsigned(x)) + to_integer(unsigned(y))) <= 1 severity failure; + + w(0) := e_in.write_cr_enable; + x(0) := (e_in.write_enable and e_in.rc); + assert (to_integer(unsigned(w)) + to_integer(unsigned(x))) <= 1 severity failure; + end if; + end process; + + writeback_1: process(all) variable cf: std_ulogic_vector(3 downto 0); variable zero : std_ulogic; variable sign : std_ulogic; variable scf : std_ulogic_vector(3 downto 0); begin - x(0) := e_in.valid; - y(0) := l_in.valid; - assert (to_integer(unsigned(x)) + to_integer(unsigned(y))) <= 1 severity failure; - - x(0) := e_in.write_enable or e_in.exc_write_enable; - y(0) := l_in.write_enable; - assert (to_integer(unsigned(x)) + to_integer(unsigned(y))) <= 1 severity failure; - - w(0) := e_in.write_cr_enable; - x(0) := (e_in.write_enable and e_in.rc); - assert (to_integer(unsigned(w)) + to_integer(unsigned(x))) <= 1 severity failure; - w_out <= WritebackToRegisterFileInit; c_out <= WritebackToCrFileInit;