From 6a1c04608090cc8fc88aafac0b4899e4cbb9cae9 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Mon, 5 Apr 2021 10:20:02 -0700 Subject: Change our simulator timing model to use continuous assignment guards. Instead of depending on verilator getting $past right, this (ab-)uses the SystemVerilog scheduling model which allows us to get a consistent view of the universe by "isolating" the blocking updates. Easier to code to and seems to be more reliable in verilator. --- hdl/top.sv | 115 ++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 65 insertions(+), 50 deletions(-) (limited to 'hdl/top.sv') diff --git a/hdl/top.sv b/hdl/top.sv index 34b9769..54cfdc5 100644 --- a/hdl/top.sv +++ b/hdl/top.sv @@ -13,14 +13,14 @@ bit have_reset = 0; always_ff @(posedge clk) if (reset) have_reset <= 1; assign reset = !reset_n || !have_reset; -bit mem_ready; `define mem_ready `past(mem_ready) +bit mem_ready; bit mem_valid; bit mem_write; bit [ADDR_BITS-1:0] mem_address; bit [DATA_BITS-1:0] mem_write_data; -bit mem_read_valid; `define mem_read_valid `past(mem_read_valid) -bit [DATA_BITS-1:0] mem_read_data; `define mem_read_data `past(mem_read_data) +bit mem_read_valid; +bit [DATA_BITS-1:0] mem_read_data; mem #( .ADDR_BITS(ADDR_BITS) @@ -41,6 +41,14 @@ mem , .read_data(mem_read_data) ); +`input(mem_ready) +`output(mem_valid) +`output(mem_address) +`output(mem_write) +`output(mem_write_data) +`input(mem_read_valid) +`input(mem_read_data) + bit rx_ready; bit rx_valid; bit [7:0] rx_data; @@ -56,14 +64,21 @@ jtag_uart , .reset(reset) , .rx_ready(rx_ready) - , .rx_valid(rx_valid) `define rx_valid `past(rx_valid) - , .rx_data(rx_data) `define rx_data `past(rx_data) + , .rx_valid(rx_valid) + , .rx_data(rx_data) - , .tx_ready(tx_ready) `define tx_ready `past(tx_ready) + , .tx_ready(tx_ready) , .tx_valid(tx_valid) , .tx_data(tx_data) ); +`output(rx_ready) +`input(rx_valid) +`input(rx_data) +`input(tx_ready) +`output(tx_valid) +`output(tx_data) + bit [ADDR_BITS-1:0] pc; bit [3:0] opcode; bit [7:0] operand; @@ -84,33 +99,33 @@ enum always_ff @(posedge clk) begin if (reset) begin - mem_valid = 0; - rx_ready = 0; - tx_valid = 0; - tx_data = 0; + mem_valid_ = 0; + rx_ready_ = 0; + tx_valid_ = 0; + tx_data_ = 0; pc = 0; acc = 0; state = state.first; end else begin - if (`tx_ready) tx_valid = 0; + if (tx_ready_) tx_valid_ = 0; case (state) FETCH: begin - mem_valid = 1; + mem_valid_ = 1; mem_address_ = pc; - mem_write = 0; - if (`mem_ready) begin + mem_write_ = 0; + if (mem_ready_) begin state = DECODE; ++pc; end end DECODE: begin - mem_valid = 0; - mem_write = 0; - if (`mem_read_valid) begin + mem_valid_ = 0; + mem_write_ = 0; + if (mem_read_valid_) begin state = FETCH; - {opcode, operand} = `mem_read_data; + {opcode, operand} = mem_read_data_; sign_extended_operand = {{(DATA_BITS-8){operand[7]}}, operand}; case (opcode) 'h0: begin @@ -135,7 +150,7 @@ always_ff @(posedge clk) begin end end 'h6: begin - mem_write_data = acc % 10 + 'h30; + mem_write_data_ = acc % 10 + 'h30; acc = acc / 10; address = {7'b0, operand[6:0]}; state = operand[7] ? INDIRECT : AGEN; @@ -145,70 +160,70 @@ always_ff @(posedge clk) begin end INDIRECT: begin - mem_valid = 1; - mem_write = 0; - mem_address = address; - state = `mem_ready ? INDIRECTED : INDIRECT; + mem_valid_ = 1; + mem_write_ = 0; + mem_address_ = address; + state = mem_ready_ ? INDIRECTED : INDIRECT; end INDIRECTED: begin - if (`mem_ready) begin - mem_valid = 0; - mem_write = 0; + if (mem_ready_) begin + mem_valid_ = 0; + mem_write_ = 0; end - if (`mem_read_valid) begin - address = {{(ADDR_BITS - DATA_BITS){1'b0}}, `mem_read_data}; + if (mem_read_valid_) begin + address = {{(ADDR_BITS - DATA_BITS){1'b0}}, mem_read_data_}; state = AGEN; end end AGEN: begin - mem_valid = 0; - mem_write = 0; + mem_valid_ = 0; + mem_write_ = 0; state = FETCH; case (opcode) 'h2: begin - mem_valid = 1; - mem_address = address; - state = `mem_ready ? MEMORY : AGEN; + mem_valid_ = 1; + mem_address_ = address; + state = mem_ready_ ? MEMORY : AGEN; end 'h3: begin - mem_valid = 1; - mem_address = address; - mem_write = 1; - mem_write_data = acc; - state = `mem_ready ? FETCH : AGEN; + mem_valid_ = 1; + mem_address_ = address; + mem_write_ = 1; + mem_write_data_ = acc; + state = mem_ready_ ? FETCH : AGEN; end 'h5: pc = address; 'h6: begin - mem_valid = 1; - mem_address = address; - mem_write = 1; - state = `mem_ready ? FETCH : AGEN; + mem_valid_ = 1; + mem_address_ = address; + mem_write_ = 1; + state = mem_ready_ ? FETCH : AGEN; end endcase end MEMORY: begin - if (`mem_ready) begin - mem_valid = 0; - mem_write = 0; + if (mem_ready_) begin + mem_valid_ = 0; + mem_write_ = 0; end state = FETCH; case (opcode) 'h0: begin if (operand[6]) begin - if (tx_valid) begin + if (tx_valid_) begin state = MEMORY; end else begin - tx_valid = 1; - tx_data = acc[7:0]; + tx_valid_ = 1; + tx_data_ = acc[7:0]; end end end 'h2: begin - if (`mem_read_valid) begin - acc = acc + `mem_read_data; + if (mem_read_valid_) begin + acc = acc + mem_read_data_; end else begin state = MEMORY; end -- cgit v1.2.3