diff --git a/crates/fayalite/examples/blinky.rs b/crates/fayalite/examples/blinky.rs index 94c7910..87b77c1 100644 --- a/crates/fayalite/examples/blinky.rs +++ b/crates/fayalite/examples/blinky.rs @@ -17,15 +17,15 @@ fn blinky(clock_frequency: u64) { let max_value = clock_frequency / 2 - 1; let int_ty = UInt::range_inclusive(0..=max_value); #[hdl] - let counter: UInt = reg_builder().clock_domain(cd).reset(0u8.cast_to(int_ty)); + let counter_reg: UInt = reg_builder().clock_domain(cd).reset(0u8.cast_to(int_ty)); #[hdl] let output_reg: Bool = reg_builder().clock_domain(cd).reset(false); #[hdl] - if counter.cmp_eq(max_value) { - connect_any(counter, 0u8); + if counter_reg.cmp_eq(max_value) { + connect_any(counter_reg, 0u8); connect(output_reg, !output_reg); } else { - connect_any(counter, counter + 1_hdl_u1); + connect_any(counter_reg, counter_reg + 1_hdl_u1); } #[hdl] let led: Bool = m.output(); diff --git a/crates/fayalite/src/_docs/modules/module_bodies/hdl_let_statements/registers.rs b/crates/fayalite/src/_docs/modules/module_bodies/hdl_let_statements/registers.rs index 5a81c5b..2876389 100644 --- a/crates/fayalite/src/_docs/modules/module_bodies/hdl_let_statements/registers.rs +++ b/crates/fayalite/src/_docs/modules/module_bodies/hdl_let_statements/registers.rs @@ -9,6 +9,9 @@ //! //! Registers follow [connection semantics], which are unlike assignments in software, so you should read it. //! +//! By convention, register names end in `_reg` -- this helps you tell which values are written +//! immediately or on the next clock edge when connecting to them. +//! //! ``` //! # use fayalite::prelude::*; //! # #[hdl_module] @@ -18,11 +21,11 @@ //! #[hdl] //! let cd: ClockDomain = m.input(); //! #[hdl] -//! let my_register: UInt<8> = reg_builder().clock_domain(cd).reset(8_hdl_u8); +//! let my_reg: UInt<8> = reg_builder().clock_domain(cd).reset(8_hdl_u8); //! #[hdl] //! if v { -//! // my_register is only changed when both `v` is set and `cd`'s clock edge occurs. -//! connect(my_register, 0x45_hdl_u8); +//! // my_reg is only changed when both `v` is set and `cd`'s clock edge occurs. +//! connect(my_reg, 0x45_hdl_u8); //! } //! # } //! ``` diff --git a/crates/fayalite/src/util/ready_valid.rs b/crates/fayalite/src/util/ready_valid.rs index f3d5653..4fe480d 100644 --- a/crates/fayalite/src/util/ready_valid.rs +++ b/crates/fayalite/src/util/ready_valid.rs @@ -69,11 +69,11 @@ pub fn queue( let count: UInt = m.output(count_ty); #[hdl] - let inp_index = reg_builder().clock_domain(cd).reset(0.cast_to(index_ty)); + let inp_index_reg = reg_builder().clock_domain(cd).reset(0.cast_to(index_ty)); #[hdl] - let out_index = reg_builder().clock_domain(cd).reset(0.cast_to(index_ty)); + let out_index_reg = reg_builder().clock_domain(cd).reset(0.cast_to(index_ty)); #[hdl] - let maybe_full = reg_builder().clock_domain(cd).reset(false); + let maybe_full_reg = reg_builder().clock_domain(cd).reset(false); #[hdl] let mut mem = memory(ty); @@ -89,18 +89,18 @@ pub fn queue( connect(out_fire, ReadyValid::fire(out)); #[hdl] let indexes_equal: Bool = wire(); - connect(indexes_equal, inp_index.cmp_eq(out_index)); + connect(indexes_equal, inp_index_reg.cmp_eq(out_index_reg)); #[hdl] let empty: Bool = wire(); - connect(empty, indexes_equal & !maybe_full); + connect(empty, indexes_equal & !maybe_full_reg); #[hdl] let full: Bool = wire(); - connect(full, indexes_equal & maybe_full); + connect(full, indexes_equal & maybe_full_reg); - connect(read_port.addr, out_index); + connect(read_port.addr, out_index_reg); connect(read_port.en, true); connect(read_port.clk, cd.clk); - connect(write_port.addr, inp_index); + connect(write_port.addr, inp_index_reg); connect(write_port.en, inp_fire); connect(write_port.clk, cd.clk); connect(write_port.data, HdlOption::unwrap_or(inp.data, ty.uninit())); @@ -127,33 +127,33 @@ pub fn queue( #[hdl] if inp_fire.cmp_ne(out_fire) { - connect(maybe_full, inp_fire); + connect(maybe_full_reg, inp_fire); } #[hdl] if inp_fire { #[hdl] - if inp_index.cmp_eq(capacity.get() - 1) { - connect_any(inp_index, 0_hdl_u0); + if inp_index_reg.cmp_eq(capacity.get() - 1) { + connect_any(inp_index_reg, 0_hdl_u0); } else { - connect_any(inp_index, inp_index + 1_hdl_u1); + connect_any(inp_index_reg, inp_index_reg + 1_hdl_u1); } } #[hdl] if out_fire { #[hdl] - if out_index.cmp_eq(capacity.get() - 1) { - connect_any(out_index, 0_hdl_u0); + if out_index_reg.cmp_eq(capacity.get() - 1) { + connect_any(out_index_reg, 0_hdl_u0); } else { - connect_any(out_index, out_index + 1_hdl_u1); + connect_any(out_index_reg, out_index_reg + 1_hdl_u1); } } #[hdl] if indexes_equal { #[hdl] - if maybe_full { + if maybe_full_reg { connect_any(count, capacity); } else { connect_any(count, 0_hdl_u0); @@ -163,15 +163,18 @@ pub fn queue( debug_assert_eq!(count_ty.width(), index_ty.width() + 1); #[hdl] let count_lower = wire(index_ty); - connect(count_lower, (inp_index - out_index).cast_to(index_ty)); // wrap + connect( + count_lower, + (inp_index_reg - out_index_reg).cast_to(index_ty), + ); // wrap connect(count, count_lower.cast_to(count_ty)); } else { debug_assert_eq!(count_ty.width(), index_ty.width()); #[hdl] - if inp_index.cmp_lt(out_index) { - connect(count, inp_index + capacity - out_index); + if inp_index_reg.cmp_lt(out_index_reg) { + connect(count, inp_index_reg + capacity - out_index_reg); } else { - connect(count, inp_index - out_index); + connect(count, inp_index_reg - out_index_reg); } } } @@ -249,89 +252,101 @@ mod tests { ); #[hdl] - let expected_count = reg_builder().clock_domain(cd).reset(0u32); + let expected_count_reg = reg_builder().clock_domain(cd).reset(0u32); #[hdl] let next_expected_count = wire(); - connect(next_expected_count, expected_count); - connect(expected_count, next_expected_count); + connect(next_expected_count, expected_count_reg); + connect(expected_count_reg, next_expected_count); #[hdl] if ReadyValid::fire(dut.inp) & !ReadyValid::fire(dut.out) { - connect_any(next_expected_count, expected_count + 1u8); + connect_any(next_expected_count, expected_count_reg + 1u8); } else if !ReadyValid::fire(dut.inp) & ReadyValid::fire(dut.out) { - connect_any(next_expected_count, expected_count - 1u8); + connect_any(next_expected_count, expected_count_reg - 1u8); } - hdl_assert(cd.clk, expected_count.cmp_eq(dut.count), ""); + hdl_assert(cd.clk, expected_count_reg.cmp_eq(dut.count), ""); #[hdl] - let prev_out_ready = reg_builder().clock_domain(cd).reset(!0_hdl_u3); + let prev_out_ready_reg = reg_builder().clock_domain(cd).reset(!0_hdl_u3); connect_any( - prev_out_ready, - (prev_out_ready << 1) | out_ready.cast_to(UInt[1]), + prev_out_ready_reg, + (prev_out_ready_reg << 1) | out_ready.cast_to(UInt[1]), ); #[hdl] - let prev_inp_valid = reg_builder().clock_domain(cd).reset(!0_hdl_u3); + let prev_inp_valid_reg = reg_builder().clock_domain(cd).reset(!0_hdl_u3); connect_any( - prev_inp_valid, - (prev_inp_valid << 1) | HdlOption::is_some(inp_data).cast_to(UInt[1]), + prev_inp_valid_reg, + (prev_inp_valid_reg << 1) | HdlOption::is_some(inp_data).cast_to(UInt[1]), + ); + hdl_assume( + clk, + (prev_out_ready_reg & prev_inp_valid_reg).cmp_ne(0u8), + "", ); - hdl_assume(clk, (prev_out_ready & prev_inp_valid).cmp_ne(0u8), ""); #[hdl] - let inp_index = reg_builder().clock_domain(cd).reset(index_ty.zero()); + let inp_index_reg = reg_builder().clock_domain(cd).reset(index_ty.zero()); #[hdl] - let stored_inp_data = reg_builder().clock_domain(cd).reset(0u8); + let stored_inp_data_reg = reg_builder().clock_domain(cd).reset(0u8); #[hdl] if let HdlSome(data) = ReadyValid::fire_data(dut.inp) { #[hdl] - if inp_index.cmp_lt(index_max) { - connect_any(inp_index, inp_index + 1u8); + if inp_index_reg.cmp_lt(index_max) { + connect_any(inp_index_reg, inp_index_reg + 1u8); #[hdl] - if inp_index.cmp_eq(index_to_check) { - connect(stored_inp_data, data); + if inp_index_reg.cmp_eq(index_to_check) { + connect(stored_inp_data_reg, data); } } } #[hdl] - if inp_index.cmp_lt(index_to_check) { - hdl_assert(clk, stored_inp_data.cmp_eq(0u8), ""); + if inp_index_reg.cmp_lt(index_to_check) { + hdl_assert(clk, stored_inp_data_reg.cmp_eq(0u8), ""); } #[hdl] - let out_index = reg_builder().clock_domain(cd).reset(index_ty.zero()); + let out_index_reg = reg_builder().clock_domain(cd).reset(index_ty.zero()); #[hdl] - let stored_out_data = reg_builder().clock_domain(cd).reset(0u8); + let stored_out_data_reg = reg_builder().clock_domain(cd).reset(0u8); #[hdl] if let HdlSome(data) = ReadyValid::fire_data(dut.out) { #[hdl] - if out_index.cmp_lt(index_max) { - connect_any(out_index, out_index + 1u8); + if out_index_reg.cmp_lt(index_max) { + connect_any(out_index_reg, out_index_reg + 1u8); #[hdl] - if out_index.cmp_eq(index_to_check) { - connect(stored_out_data, data); + if out_index_reg.cmp_eq(index_to_check) { + connect(stored_out_data_reg, data); } } } #[hdl] - if out_index.cmp_lt(index_to_check) { - hdl_assert(clk, stored_out_data.cmp_eq(0u8), ""); + if out_index_reg.cmp_lt(index_to_check) { + hdl_assert(clk, stored_out_data_reg.cmp_eq(0u8), ""); } - hdl_assert(clk, inp_index.cmp_ge(out_index), ""); + hdl_assert(clk, inp_index_reg.cmp_ge(out_index_reg), ""); #[hdl] - if inp_index.cmp_lt(index_max) & out_index.cmp_lt(index_max) { - hdl_assert(clk, expected_count.cmp_eq(inp_index - out_index), ""); + if inp_index_reg.cmp_lt(index_max) & out_index_reg.cmp_lt(index_max) { + hdl_assert( + clk, + expected_count_reg.cmp_eq(inp_index_reg - out_index_reg), + "", + ); } else { - hdl_assert(clk, expected_count.cmp_ge(inp_index - out_index), ""); + hdl_assert( + clk, + expected_count_reg.cmp_ge(inp_index_reg - out_index_reg), + "", + ); } #[hdl] - if inp_index.cmp_gt(index_to_check) & out_index.cmp_gt(index_to_check) { - hdl_assert(clk, stored_inp_data.cmp_eq(stored_out_data), ""); + if inp_index_reg.cmp_gt(index_to_check) & out_index_reg.cmp_gt(index_to_check) { + hdl_assert(clk, stored_inp_data_reg.cmp_eq(stored_out_data_reg), ""); } } } diff --git a/crates/fayalite/tests/module.rs b/crates/fayalite/tests/module.rs index 0d690f2..69438f2 100644 --- a/crates/fayalite/tests/module.rs +++ b/crates/fayalite/tests/module.rs @@ -41,13 +41,13 @@ pub fn my_module(width: usize) { #[hdl] let m2 = instance(module2()); #[hdl] - let r: UInt<8> = reg_builder().clock_domain(clock_domain).reset(8_hdl_u8); + let r_reg: UInt<8> = reg_builder().clock_domain(clock_domain).reset(8_hdl_u8); connect(m2.i, i); - connect(r, m2.o); + connect(r_reg, m2.o); connect( o, #[hdl] - [r, r, b'\r'_hdl], + [r_reg, r_reg, b'\r'_hdl], ); connect(o[1], 30_hdl_u8); connect(o2, i2); @@ -109,12 +109,12 @@ circuit my_module: connect _bundle_literal_expr.`1`, SInt<5>(-0h3) connect o3, _bundle_literal_expr @[module-XXXXXXXXXX.rs 12:1] inst m2 of module2 @[module-XXXXXXXXXX.rs 13:1] - regreset r: UInt<8>, clock_domain.clk, clock_domain.rst, UInt<8>(0h8) @[module-XXXXXXXXXX.rs 14:1] + regreset r_reg: UInt<8>, clock_domain.clk, clock_domain.rst, UInt<8>(0h8) @[module-XXXXXXXXXX.rs 14:1] connect m2.i, i @[module-XXXXXXXXXX.rs 15:1] - connect r, m2.o @[module-XXXXXXXXXX.rs 16:1] + connect r_reg, m2.o @[module-XXXXXXXXXX.rs 16:1] wire _array_literal_expr: UInt<8>[3] - connect _array_literal_expr[0], r - connect _array_literal_expr[1], r + connect _array_literal_expr[0], r_reg + connect _array_literal_expr[1], r_reg connect _array_literal_expr[2], UInt<8>(0hD) connect o, _array_literal_expr @[module-XXXXXXXXXX.rs 17:1] connect o[1], UInt<8>(0h1E) @[module-XXXXXXXXXX.rs 18:1]