tests/test.sh exit code (0 → resolved); the classification below is post-hoc and cannot change it.rg --files
Chunk ID: 99fc2e Wall time: 0.0000 seconds Process exited with code 0 Original token count: 19 Output: sdiv_core/rtl/sdiv.sv sdiv_core/rtl/divp_pkg.sv sdiv_core/rtl/sdiv_top.sv
rg -n "module sdiv|package|parameter|localparam|sdiv" .
Chunk ID: ce0827 Wall time: 0.0000 seconds Process exited with code 0 Original token count: 332 Output: ./sdiv_core/rtl/sdiv.sv:2:// sdiv.sv ./sdiv_core/rtl/sdiv.sv:9:// The module ports, parameters and a small set of state registers are ./sdiv_core/rtl/sdiv.sv:15:// module name, the port list, or the parameter list. ./sdiv_core/rtl/sdiv.sv:26:module sdiv #( ./sdiv_core/rtl/sdiv.sv:27: parameter W = 16, ./sdiv_core/rtl/sdiv.sv:28: parameter N = 16 ./sdiv_core/rtl/sdiv.sv:76:endmodule : sdiv ./sdiv_core/rtl/sdiv_top.sv:2:// sdiv_top.sv ./sdiv_core/rtl/sdiv_top.sv:6:// instantiates sdiv with the project-default geometry from divp_pkg. ./sdiv_core/rtl/sdiv_top.sv:13:module sdiv_top ( ./sdiv_core/rtl/sdiv_top.sv:26: // submission needs no parameter override to elaborate correctly. ./sdiv_core/rtl/sdiv_top.sv:27: sdiv u_sdiv ( ./sdiv_core/rtl/sdiv_top.sv:39:endmodule : sdiv_top ./sdiv_core/rtl/divp_pkg.sv:16:package divp_pkg; ./sdiv_core/rtl/divp_pkg.sv:18: localparam W = 16; // operand / result word width (signed two's comp) ./sdiv_core/rtl/divp_pkg.sv:19: localparam N = 16; // result latency: clocks from accept to valid ./sdiv_core/rtl/divp_pkg.sv:23: localparam DIV0_Q_POS = 16'h7FFF; // 32767, used when dividend >= 0 ./sdiv_core/rtl/divp_pkg.sv:24: localparam DIV0_Q_NEG = 16'h8000; // -32768, used when dividend < 0 ./sdiv_core/rtl/divp_pkg.sv:26:endpackage : divp_pkg
sed -n '1,180p' rtl/sdiv.sv
Chunk ID: 105f84
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 811
Output:
//==============================================================================
// sdiv.sv
//
// Multi-cycle signed integer divider with a start/busy/valid handshake.
//
// ---------------------------------------------------------------------------
// >>> IMPLEMENTATION REQUIRED <<<
//
// The module ports, parameters and a small set of state registers are
// provided. The operand latch, the latency/handshake control and the signed
// result are left as a TODO and currently drive constant zeros, so the divider
// produces no useful result and the verifier FAILS.
//
// Implement the behaviour described in instruction.md. Do NOT change the
// module name, the port list, or the parameter list.
//
// iverilog 11 note: a bit/part-select of an EXPRESSION (a sum, a shift, a
// function-call result) is a syntax error under `iverilog -g2012`. Index only
// named signals, and do any bit work that needs an intermediate value inside a
// `function automatic` using named locals. Write negative full-scale constants
// as bit patterns (e.g. 16'h8000 for -32768), not as -16'sd32768.
// ---------------------------------------------------------------------------
//==============================================================================
`timescale 1ns/1ps
module sdiv #(
parameter W = 16,
parameter N = 16
) (
input logic clk,
input logic rst_n,
input logic start,
input logic signed [W-1:0] dividend,
input logic signed [W-1:0] divisor,
output logic signed [W-1:0] quotient,
output logic signed [W-1:0] remainder,
output logic busy,
output logic valid
);
// ---------------------------------------------------------------------------
// State registers (provided). Latch the operands here on an accepted start and
// track the in-flight progress with the counter.
// ---------------------------------------------------------------------------
logic signed [W-1:0] a_q; // latched dividend
logic signed [W-1:0] b_q; // latched divisor
logic [7:0] cnt; // in-flight progress
logic run; // a divide is in progress
// ===========================================================================
// TODO: IMPLEMENT THE DIVIDER.
// * accept a start only when not busy; latch dividend/divisor at that edge;
// * after the fixed latency, present the signed quotient/remainder and pulse
// valid for one clock, with busy and valid never overlapping;
// * asynchronous active-low reset clears all state and all outputs.
//
// The placeholder below keeps the module compilable but INCORRECT.
// ===========================================================================
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
a_q <= '0;
b_q <= '0;
cnt <= 8'd0;
run <= 1'b0;
busy <= 1'b0;
valid <= 1'b0;
quotient <= '0;
remainder <= '0;
end else begin
// TODO: replace with the real latch + latency control + result.
run <= run;
cnt <= cnt;
end
end
endmodule : sdiv
sed -n '1,140p' rtl/divp_pkg.sv
Chunk ID: fa6ac8 Wall time: 0.0000 seconds Process exited with code 0 Original token count: 303 Output: //============================================================================== // divp_pkg.sv // // Shared geometry and constants for the multi-cycle signed divider. The block // latches a signed dividend/divisor on an accepted start and produces a signed // quotient/remainder after a fixed number of clocks, with a start/busy/valid // handshake. Parameters are declared without an explicit data type for broad // simulator compatibility (Icarus Verilog 11); they default to integer // constants, which is sufficient here. // // DO NOT change this file. //============================================================================== `ifndef DIVP_PKG_SV `define DIVP_PKG_SV package divp_pkg; localparam W = 16; // operand / result word width (signed two's comp) localparam N = 16; // result latency: clocks from accept to valid // Defined divide-by-zero outputs (divisor == 0). Written as raw bit patterns // because the negative saturation value is the most-negative 16-bit number. localparam DIV0_Q_POS = 16'h7FFF; // 32767, used when dividend >= 0 localparam DIV0_Q_NEG = 16'h8000; // -32768, used when dividend < 0 endpackage : divp_pkg `endif // DIVP_PKG_SV
sed -n '1,120p' rtl/sdiv_top.sv
Chunk ID: 6e1470
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 346
Output:
//==============================================================================
// sdiv_top.sv
//
// Thin integration wrapper. The verification environment drives this wrapper so
// that the instantiation wiring is exercised alongside the divider itself. It
// instantiates sdiv with the project-default geometry from divp_pkg.
//
// DO NOT change this file.
//==============================================================================
`timescale 1ns/1ps
`include "divp_pkg.sv"
module sdiv_top (
input logic clk,
input logic rst_n,
input logic start,
input logic signed [divp_pkg::W-1:0] dividend,
input logic signed [divp_pkg::W-1:0] divisor,
output logic signed [divp_pkg::W-1:0] quotient,
output logic signed [divp_pkg::W-1:0] remainder,
output logic busy,
output logic valid
);
// Bare instantiation: the divider carries its own default geometry, so a
// submission needs no parameter override to elaborate correctly.
sdiv u_sdiv (
.clk (clk),
.rst_n (rst_n),
.start (start),
.dividend (dividend),
.divisor (divisor),
.quotient (quotient),
.remainder (remainder),
.busy (busy),
.valid (valid)
);
endmodule : sdiv_top
*** Begin Patch
*** Update File: /work/sdiv_core/rtl/sdiv.sv
@@
logic signed [W-1:0] a_q; // latched dividend
logic signed [W-1:0] b_q; // latched divisor
logic [7:0] cnt; // in-flight progress
logic run; // a divide is in progress
+
+ logic a_neg_q;
+ logic b_neg_q;
+ logic div0_q;
+ logic overflow_q;
+ logic [W-1:0] dividend_mag_q;
+ logic [W-1:0] divisor_mag_q;
+ logic [W-1:0] quot_mag_q;
+ logic [W:0] rem_mag_q;
+
+ logic [2*W:0] step_pack;
+ logic [W:0] step_rem;
+ logic [W-1:0] step_quot;
+
+ function automatic logic [W-1:0] min_neg_bits;
+ logic [W-1:0] bits;
+ begin
+ bits = {1'b1, {(W-1){1'b0}}};
+ min_neg_bits = bits;
+ end
+ endfunction
+
+ function automatic logic [W-1:0] max_pos_bits;
+ logic [W-1:0] bits;
+ begin
+ bits = {1'b0, {(W-1){1'b1}}};
+ max_pos_bits = bits;
+ end
+ endfunction
+
+ function automatic logic [W-1:0] abs_mag(input logic signed [W-1:0] value);
+ logic [W-1:0] bits;
+ begin
+ bits = value;
+ if (value[W-1]) begin
+ bits = ~bits + {{(W-1){1'b0}}, 1'b1};
+ end
+ abs_mag = bits;
+ end
+ endfunction
+
+ function automatic logic signed [W-1:0] signed_from_mag(
+ input logic negative,
+ input logic [W-1:0] magnitude
+ );
+ logic [W-1:0] bits;
+ begin
+ bits = magnitude;
+ if (negative) begin
+ bits = ~bits + {{(W-1){1'b0}}, 1'b1};
+ end
+ signed_from_mag = bits;
+ end
+ endfunction
+
+ function automatic logic [2*W:0] div_step(
+ input logic [W:0] rem_i,
+ input logic [W-1:0] quot_i,
+ input logic [W-1:0] dividend_mag_i,
+ input logic [W-1:0] divisor_mag_i,
+ input logic [7:0] idx_i
+ );
+ integer bit_idx;
+ logic [W:0] rem_next;
+ logic [W:0] divisor_ext;
+ logic [W-1:0] quot_next;
+ begin
+ bit_idx = W - 1 - idx_i;
+ rem_next = {rem_i[W-1:0], dividend_mag_i[bit_idx]};
+ divisor_ext = {1'b0, divisor_mag_i};
+ quot_next = quot_i;
+
+ if ((divisor_mag_i != '0) && (rem_next >= divisor_ext)) begin
+ rem_next = rem_next - divisor_ext;
+ quot_next[bit_idx] = 1'b1;
+ end else begin
+ quot_next[bit_idx] = 1'b0;
+ end
+
+ div_step = {rem_next, quot_next};
+ end
+ endfunction
+
+ function automatic logic signed [W-1:0] final_quotient(
+ input logic a_neg_i,
+ input logic b_neg_i,
+ input logic div0_i,
+ input logic overflow_i,
+ input logic signed [W-1:0] a_i,
+ input logic [W-1:0] quot_mag_i,
+ input logic [W-1:0] rem_mag_i
+ );
+ logic signed [W-1:0] q_trunc;
+ begin
+ if (div0_i) begin
+ if (a_i[W-1]) begin
+ final_quotient = min_neg_bits();
+ end else begin
+ final_quotient = max_pos_bits();
+ end
+ end else if (overflow_i) begin
+ final_quotient = max_pos_bits();
+ end else begin
+ q_trunc = signed_from_mag(a_neg_i ^ b_neg_i, quot_mag_i);
+ if ((rem_mag_i != '0) && (a_neg_i ^ b_neg_i)) begin
+ final_quotient = q_trunc - 1;
+ end else begin
+ final_quotient = q_trunc;
+ end
+ end
+ end
+ endfunction
+
+ function automatic logic signed [W-1:0] final_remainder(
+ input logic a_neg_i,
+ input logic b_neg_i,
+ input logic div0_i,
+ input logic overflow_i,
+ input logic signed [W-1:0] a_i,
+ input logic signed [W-1:0] b_i,
+ input logic [W-1:0] rem_mag_i
+ );
+ logic signed [W-1:0] r_trunc;
+ begin
+ if (div0_i) begin
+ final_remainder = a_i;
+ end else if (overflow_i) begin
+ final_remainder = '0;
+ end else begin
+ r_trunc = signed_from_mag(a_neg_i, rem_mag_i);
+ if ((rem_mag_i != '0) && (a_neg_i ^ b_neg_i)) begin
+ final_remainder = r_trunc + b_i;
+ end else begin
+ final_remainder = r_trunc;
+ end
+ end
+ end
+ endfunction
+
+ always_comb begin
+ step_pack = div_step(rem_mag_q, quot_mag_q, dividend_mag_q, divisor_mag_q, cnt);
+ step_rem = step_pack[2*W:W];
+ step_quot = step_pack[W-1:0];
+ end
// ===========================================================================
- // TODO: IMPLEMENT THE DIVIDER.
- // * accept a start only when not busy; latch dividend/divisor at that edge;
- // * after the fixed latency, present the signed quotient/remainder and pulse
- // valid for one clock, with busy and valid never overlapping;
- // * asynchronous active-low reset clears all state and all outputs.
- //
- // The placeholder below keeps the module compilable but INCORRECT.
+ // Fixed-latency handshake and one-bit-per-cycle restoring divider.
// ===========================================================================
always_ff @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
a_q <= '0;
b_q <= '0;
cnt <= 8'd0;
run <= 1'b0;
+ a_neg_q <= 1'b0;
+ b_neg_q <= 1'b0;
+ div0_q <= 1'b0;
+ overflow_q <= 1'b0;
+ dividend_mag_q <= '0;
+ divisor_mag_q <= '0;
+ quot_mag_q <= '0;
+ rem_mag_q <= '0;
busy <= 1'b0;
valid <= 1'b0;
quotient <= '0;
remainder <= '0;
end else begin
- // TODO: replace with the real latch + latency control + result.
- run <= run;
- cnt <= cnt;
+ if (run) begin
+ if (cnt == (N - 1)) begin
+ run <= 1'b0;
+ cnt <= 8'd0;
+ busy <= 1'b0;
+ valid <= 1'b1;
+ quot_mag_q <= step_quot;
+ rem_mag_q <= step_rem;
+ quotient <= final_quotient(
+ a_neg_q,
+ b_neg_q,
+ div0_q,
+ overflow_q,
+ a_q,
+ step_quot,
+ step_rem[W-1:0]
+ );
+ remainder <= final_remainder(
+ a_neg_q,
+ b_neg_q,
+ div0_q,
+ overflow_q,
+ a_q,
+ b_q,
+ step_rem[W-1:0]
+ );
+ end else begin
+ run <= 1'b1;
+ cnt <= cnt + 8'd1;
+ busy <= 1'b1;
+ valid <= 1'b0;
+ quot_mag_q <= step_quot;
+ rem_mag_q <= step_rem;
+ end
+ end else begin
+ busy <= 1'b0;
+ valid <= 1'b0;
+
+ if (start) begin
+ a_q <= dividend;
+ b_q <= divisor;
+ cnt <= 8'd0;
+ run <= 1'b1;
+ a_neg_q <= dividend[W-1];
+ b_neg_q <= divisor[W-1];
+ div0_q <= (divisor == '0);
+ overflow_q <= ((dividend == min_neg_bits()) && (divisor == {W{1'b1}}));
+ dividend_mag_q <= abs_mag(dividend);
+ divisor_mag_q <= abs_mag(divisor);
+ quot_mag_q <= '0;
+ rem_mag_q <= '0;
+ end
+ end
end
end
endmodule : sdiv
*** End Patch
Exit code: 0
Wall time: 0 seconds
Output:
Success. Updated the following files:
M /work/sdiv_core/rtl/sdiv.sv
iverilog -g2012 -Wall -o /tmp/sdiv_compile.out rtl/sdiv.sv rtl/sdiv_top.sv
Chunk ID: 28db8e Wall time: 0.0000 seconds Process exited with code 0 Original token count: 104 Output: rtl/sdiv_top.sv:12: Include file divp_pkg.sv not found rtl/sdiv.sv:188: sorry: constant selects in always_* processes are not currently supported (all bits will be included). rtl/sdiv.sv:188: sorry: constant selects in always_* processes are not currently supported (all bits will be included). rtl/sdiv.sv:188: sorry: constant selects in always_* processes are not currently supported (all bits will be included).
git diff -- rtl/sdiv.sv
Chunk ID: a08d09 Wall time: 0.0000 seconds Process exited with code 127 Original token count: 11 Output: /bin/bash: line 1: git: command not found
*** Begin Patch *** Update File: /work/sdiv_core/rtl/sdiv.sv @@ - always_comb begin - step_pack = div_step(rem_mag_q, quot_mag_q, dividend_mag_q, divisor_mag_q, cnt); - step_rem = step_pack[2*W:W]; - step_quot = step_pack[W-1:0]; - end + assign step_pack = div_step(rem_mag_q, quot_mag_q, dividend_mag_q, divisor_mag_q, cnt); + assign step_rem = step_pack[2*W:W]; + assign step_quot = step_pack[W-1:0]; *** End Patch Exit code: 0 Wall time: 0 seconds Output: Success. Updated the following files: M /work/sdiv_core/rtl/sdiv.sv
iverilog -g2012 -Wall -Irtl -o /tmp/sdiv_compile.out rtl/sdiv.sv rtl/sdiv_top.sv
Chunk ID: bdd39e Wall time: 0.0001 seconds Process exited with code 0 Original token count: 35 Output: rtl/divp_pkg.sv:16: warning: timescale for divp_pkg inherited from another file. rtl/sdiv_top.sv:10: ...: The inherited timescale is here.
*** Begin Patch
*** Add File: /work/sdiv_core/tb_sdiv_selfcheck.sv
+`timescale 1ns/1ps
+
+module tb_sdiv_selfcheck;
+ localparam int W = 16;
+ localparam int N = 16;
+
+ logic clk;
+ logic rst_n;
+ logic start;
+ logic signed [W-1:0] dividend;
+ logic signed [W-1:0] divisor;
+ logic signed [W-1:0] quotient;
+ logic signed [W-1:0] remainder;
+ logic busy;
+ logic valid;
+
+ int cycle;
+ int valid_seen;
+
+ sdiv dut (
+ .clk (clk),
+ .rst_n (rst_n),
+ .start (start),
+ .dividend (dividend),
+ .divisor (divisor),
+ .quotient (quotient),
+ .remainder (remainder),
+ .busy (busy),
+ .valid (valid)
+ );
+
+ initial clk = 1'b0;
+ always #5 clk = ~clk;
+
+ always @(posedge clk or negedge rst_n) begin
+ if (!rst_n) begin
+ cycle <= 0;
+ end else begin
+ cycle <= cycle + 1;
+ end
+ end
+
+ function automatic int floor_q(input int a, input int b);
+ int q;
+ int r;
+ begin
+ if (b == 0) begin
+ floor_q = (a < 0) ? -32768 : 32767;
+ end else if ((a == -32768) && (b == -1)) begin
+ floor_q = 32767;
+ end else begin
+ q = a / b;
+ r = a % b;
+ if ((r != 0) && ((a < 0) != (b < 0))) begin
+ q = q - 1;
+ end
+ floor_q = q;
+ end
+ end
+ endfunction
+
+ function automatic int floor_r(input int a, input int b);
+ int q;
+ begin
+ if (b == 0) begin
+ floor_r = a;
+ end else if ((a == -32768) && (b == -1)) begin
+ floor_r = 0;
+ end else begin
+ q = floor_q(a, b);
+ floor_r = a - (q * b);
+ end
+ end
+ endfunction
+
+ task automatic pulse_start(input int a, input int b);
+ begin
+ @(negedge clk);
+ dividend = a;
+ divisor = b;
+ start = 1'b1;
+ @(negedge clk);
+ start = 1'b0;
+ dividend = 16'sd1234;
+ divisor = -16'sd9;
+ end
+ endtask
+
+ task automatic check_div(input int a, input int b);
+ int accept_cycle;
+ int i;
+ begin
+ pulse_start(a, b);
+ accept_cycle = cycle;
+ valid_seen = 0;
+
+ for (i = 1; i <= N; i = i + 1) begin
+ @(posedge clk);
+ #1;
+ if (i < N) begin
+ if (!busy) begin
+ $display("FAIL busy low at i=%0d a=%0d b=%0d", i, a, b);
+ $finish;
+ end
+ if (valid) begin
+ $display("FAIL early valid at i=%0d a=%0d b=%0d", i, a, b);
+ $finish;
+ end
+ end else begin
+ if (busy) begin
+ $display("FAIL busy overlaps valid edge a=%0d b=%0d", a, b);
+ $finish;
+ end
+ if (!valid) begin
+ $display("FAIL valid missing a=%0d b=%0d", a, b);
+ $finish;
+ end
+ if ((quotient !== floor_q(a, b)) || (remainder !== floor_r(a, b))) begin
+ $display("FAIL result a=%0d b=%0d got q=%0d r=%0d exp q=%0d r=%0d",
+ a, b, quotient, remainder, floor_q(a, b), floor_r(a, b));
+ $finish;
+ end
+ valid_seen = valid_seen + 1;
+ end
+ end
+
+ @(posedge clk);
+ #1;
+ if (valid) begin
+ $display("FAIL valid held high a=%0d b=%0d", a, b);
+ $finish;
+ end
+ if (busy) begin
+ $display("FAIL busy after valid a=%0d b=%0d", a, b);
+ $finish;
+ end
+ if (valid_seen != 1) begin
+ $display("FAIL valid count a=%0d b=%0d count=%0d accept=%0d",
+ a, b, valid_seen, accept_cycle);
+ $finish;
+ end
+ end
+ endtask
+
+ task automatic check_ignored_start;
+ begin
+ pulse_start(100, 7);
+ @(posedge clk);
+ #1;
+ if (!busy || valid) begin
+ $display("FAIL first busy state before ignored start");
+ $finish;
+ end
+
+ @(negedge clk);
+ dividend = -7;
+ divisor = 3;
+ start = 1'b1;
+ @(negedge clk);
+ start = 1'b0;
+ dividend = 16'sd55;
+ divisor = 16'sd5;
+
+ repeat (14) @(posedge clk);
+ #1;
+ if (!valid || busy || quotient !== floor_q(100, 7) || remainder !== floor_r(100, 7)) begin
+ $display("FAIL ignored start changed result got q=%0d r=%0d", quotient, remainder);
+ $finish;
+ end
+
+ @(posedge clk);
+ #1;
+ if (valid || busy) begin
+ $display("FAIL state after ignored-start result");
+ $finish;
+ end
+ end
+ endtask
+
+ initial begin
+ rst_n = 1'b0;
+ start = 1'b0;
+ dividend = '0;
+ divisor = '0;
+ valid_seen = 0;
+
+ #2;
+ if (busy || valid || quotient !== '0 || remainder !== '0) begin
+ $display("FAIL async reset outputs");
+ $finish;
+ end
+
+ repeat (2) @(posedge clk);
+ @(negedge clk);
+ rst_n = 1'b1;
+
+ check_div(7, 3);
+ check_div(-7, 3);
+ check_div(7, -3);
+ check_div(-7, -3);
+ check_div(0, 5);
+ check_div(32767, 1);
+ check_div(-32768, 1);
+ check_div(-32768, -1);
+ check_div(123, 0);
+ check_div(-123, 0);
+ check_div(32767, -32768);
+ check_div(-32768, 32767);
+ check_ignored_start();
+
+ $display("PASS");
+ $finish;
+ end
+endmodule
*** End Patch
Exit code: 0
Wall time: 0 seconds
Output:
Success. Updated the following files:
A /work/sdiv_core/tb_sdiv_selfcheck.sv
iverilog -g2012 -Wall -Irtl -o /tmp/sdiv_selfcheck.out rtl/sdiv.sv tb_sdiv_selfcheck.sv && vvp /tmp/sdiv_selfcheck.out
Chunk ID: 002cf0 Wall time: 0.0000 seconds Process exited with code 0 Original token count: 2 Output: PASS
*** Begin Patch *** Delete File: /work/sdiv_core/tb_sdiv_selfcheck.sv *** End Patch Exit code: 0 Wall time: 0 seconds Output: Success. Updated the following files: D /work/sdiv_core/tb_sdiv_selfcheck.sv
iverilog -g2012 -Wall -Irtl -o /tmp/sdiv_compile.out rtl/sdiv.sv rtl/sdiv_top.sv
Chunk ID: cb9acc Wall time: 0.0000 seconds Process exited with code 0 Original token count: 35 Output: rtl/divp_pkg.sv:16: warning: timescale for divp_pkg inherited from another file. rtl/sdiv_top.sv:10: ...: The inherited timescale is here.
nl -ba rtl/sdiv.sv | sed -n '1,280p'
Chunk ID: d998b7
Wall time: 0.0000 seconds
Process exited with code 0
Original token count: 2658
Output:
1 //==============================================================================
2 // sdiv.sv
3 //
4 // Multi-cycle signed integer divider with a start/busy/valid handshake.
5 //
6 // ---------------------------------------------------------------------------
7 // >>> IMPLEMENTATION REQUIRED <<<
8 //
9 // The module ports, parameters and a small set of state registers are
10 // provided. The operand latch, the latency/handshake control and the signed
11 // result are left as a TODO and currently drive constant zeros, so the divider
12 // produces no useful result and the verifier FAILS.
13 //
14 // Implement the behaviour described in instruction.md. Do NOT change the
15 // module name, the port list, or the parameter list.
16 //
17 // iverilog 11 note: a bit/part-select of an EXPRESSION (a sum, a shift, a
18 // function-call result) is a syntax error under `iverilog -g2012`. Index only
19 // named signals, and do any bit work that needs an intermediate value inside a
20 // `function automatic` using named locals. Write negative full-scale constants
21 // as bit patterns (e.g. 16'h8000 for -32768), not as -16'sd32768.
22 // ---------------------------------------------------------------------------
23 //==============================================================================
24 `timescale 1ns/1ps
25
26 module sdiv #(
27 parameter W = 16,
28 parameter N = 16
29 ) (
30 input logic clk,
31 input logic rst_n,
32 input logic start,
33 input logic signed [W-1:0] dividend,
34 input logic signed [W-1:0] divisor,
35 output logic signed [W-1:0] quotient,
36 output logic signed [W-1:0] remainder,
37 output logic busy,
38 output logic valid
39 );
40
41 // ---------------------------------------------------------------------------
42 // State registers (provided). Latch the operands here on an accepted start and
43 // track the in-flight progress with the counter.
44 // ---------------------------------------------------------------------------
45 logic signed [W-1:0] a_q; // latched dividend
46 logic signed [W-1:0] b_q; // latched divisor
47 logic [7:0] cnt; // in-flight progress
48 logic run; // a divide is in progress
49
50 logic a_neg_q;
51 logic b_neg_q;
52 logic div0_q;
53 logic overflow_q;
54 logic [W-1:0] dividend_mag_q;
55 logic [W-1:0] divisor_mag_q;
56 logic [W-1:0] quot_mag_q;
57 logic [W:0] rem_mag_q;
58
59 logic [2*W:0] step_pack;
60 logic [W:0] step_rem;
61 logic [W-1:0] step_quot;
62
63 function automatic logic [W-1:0] min_neg_bits;
64 logic [W-1:0] bits;
65 begin
66 bits = {1'b1, {(W-1){1'b0}}};
67 min_neg_bits = bits;
68 end
69 endfunction
70
71 function automatic logic [W-1:0] max_pos_bits;
72 logic [W-1:0] bits;
73 begin
74 bits = {1'b0, {(W-1){1'b1}}};
75 max_pos_bits = bits;
76 end
77 endfunction
78
79 function automatic logic [W-1:0] abs_mag(input logic signed [W-1:0] value);
80 logic [W-1:0] bits;
81 begin
82 bits = value;
83 if (value[W-1]) begin
84 bits = ~bits + {{(W-1){1'b0}}, 1'b1};
85 end
86 abs_mag = bits;
87 end
88 endfunction
89
90 function automatic logic signed [W-1:0] signed_from_mag(
91 input logic negative,
92 input logic [W-1:0] magnitude
93 );
94 logic [W-1:0] bits;
95 begin
96 bits = magnitude;
97 if (negative) begin
98 bits = ~bits + {{(W-1){1'b0}}, 1'b1};
99 end
100 signed_from_mag = bits;
101 end
102 endfunction
103
104 function automatic logic [2*W:0] div_step(
105 input logic [W:0] rem_i,
106 input logic [W-1:0] quot_i,
107 input logic [W-1:0] dividend_mag_i,
108 input logic [W-1:0] divisor_mag_i,
109 input logic [7:0] idx_i
110 );
111 integer bit_idx;
112 logic [W:0] rem_next;
113 logic [W:0] divisor_ext;
114 logic [W-1:0] quot_next;
115 begin
116 bit_idx = W - 1 - idx_i;
117 rem_next = {rem_i[W-1:0], dividend_mag_i[bit_idx]};
118 divisor_ext = {1'b0, divisor_mag_i};
119 quot_next = quot_i;
120
121 if ((divisor_mag_i != '0) && (rem_next >= divisor_ext)) begin
122 rem_next = rem_next - divisor_ext;
123 quot_next[bit_idx] = 1'b1;
124 end else begin
125 quot_next[bit_idx] = 1'b0;
126 end
127
128 div_step = {rem_next, quot_next};
129 end
130 endfunction
131
132 function automatic logic signed [W-1:0] final_quotient(
133 input logic a_neg_i,
134 input logic b_neg_i,
135 input logic div0_i,
136 input logic overflow_i,
137 input logic signed [W-1:0] a_i,
138 input logic [W-1:0] quot_mag_i,
139 input logic [W-1:0] rem_mag_i
140 );
141 logic signed [W-1:0] q_trunc;
142 begin
143 if (div0_i) begin
144 if (a_i[W-1]) begin
145 final_quotient = min_neg_bits();
146 end else begin
147 final_quotient = max_pos_bits();
148 end
149 end else if (overflow_i) begin
150 final_quotient = max_pos_bits();
151 end else begin
152 q_trunc = signed_from_mag(a_neg_i ^ b_neg_i, quot_mag_i);
153 if ((rem_mag_i != '0) && (a_neg_i ^ b_neg_i)) begin
154 final_quotient = q_trunc - 1;
155 end else begin
156 final_quotient = q_trunc;
157 end
158 end
159 end
160 endfunction
161
162 function automatic logic signed [W-1:0] final_remainder(
163 input logic a_neg_i,
164 input logic b_neg_i,
165 input logic div0_i,
166 input logic overflow_i,
167 input logic signed [W-1:0] a_i,
168 input logic signed [W-1:0] b_i,
169 input logic [W-1:0] rem_mag_i
170 );
171 logic signed [W-1:0] r_trunc;
172 begin
173 if (div0_i) begin
174 final_remainder = a_i;
175 end else if (overflow_i) begin
176 final_remainder = '0;
177 end else begin
178 r_trunc = signed_from_mag(a_neg_i, rem_mag_i);
179 if ((rem_mag_i != '0) && (a_neg_i ^ b_neg_i)) begin
180 final_remainder = r_trunc + b_i;
181 end else begin
182 final_remainder = r_trunc;
183 end
184 end
185 end
186 endfunction
187
188 assign step_pack = div_step(rem_mag_q, quot_mag_q, dividend_mag_q, divisor_mag_q, cnt);
189 assign step_rem = step_pack[2*W:W];
190 assign step_quot = step_pack[W-1:0];
191
192 // ===========================================================================
193 // Fixed-latency handshake and one-bit-per-cycle restoring divider.
194 // ===========================================================================
195 always_ff @(posedge clk or negedge rst_n) begin
196 if (!rst_n) begin
197 a_q <= '0;
198 b_q <= '0;
199 cnt <= 8'd0;
200 run <= 1'b0;
201 a_neg_q <= 1'b0;
202 b_neg_q <= 1'b0;
203 div0_q <= 1'b0;
204 overflow_q <= 1'b0;
205 dividend_mag_q <= '0;
206 divisor_mag_q <= '0;
207 quot_mag_q <= '0;
208 rem_mag_q <= '0;
209 busy <= 1'b0;
210 valid <= 1'b0;
211 quotient <= '0;
212 remainder <= '0;
213 end else begin
214 if (run) begin
215 if (cnt == (N - 1)) begin
216 run <= 1'b0;
217 cnt <= 8'd0;
218 busy <= 1'b0;
219 valid <= 1'b1;
220 quot_mag_q <= step_quot;
221 rem_mag_q <= step_rem;
222 quotient <= final_quotient(
223 a_neg_q,
224 b_neg_q,
225 div0_q,
226 overflow_q,
227 a_q,
228 step_quot,
229 step_rem[W-1:0]
230 );
231 remainder <= final_remainder(
232 a_neg_q,
233 b_neg_q,
234 div0_q,
235 overflow_q,
236 a_q,
237 b_q,
238 step_rem[W-1:0]
239 );
240 end else begin
241 run <= 1'b1;
242 cnt <= cnt + 8'd1;
243 busy <= 1'b1;
244 valid <= 1'b0;
245 quot_mag_q <= step_quot;
246 rem_mag_q <= step_rem;
247 end
248 end else begin
249 busy <= 1'b0;
250 valid <= 1'b0;
251
252 if (start) begin
253 a_q <= dividend;
254 b_q <= divisor;
255 cnt <= 8'd0;
256 run <= 1'b1;
257 a_neg_q <= dividend[W-1];
258 b_neg_q <= divisor[W-1];
259 div0_q <= (divisor == '0);
260 overflow_q <= ((dividend == min_neg_bits()) && (divisor == {W{1'b1}}));
261 dividend_mag_q <= abs_mag(dividend);
262 divisor_mag_q <= abs_mag(divisor);
263 quot_mag_q <= '0;
264 rem_mag_q <= '0;
265 end
266 end
267 end
268 end
269
270 endmodule : sdiv
find . -maxdepth 3 -type f | sort
Chunk ID: 40cf28 Wall time: 0.0000 seconds Process exited with code 0 Original token count: 13 Output: ./rtl/divp_pkg.sv ./rtl/sdiv.sv ./rtl/sdiv_top.sv
No file changes, the agent left the workspace untouched.
Reproduce this trial: git checkout 2f94510 && PYTHONPATH=src python3 scripts/build_site.py , then open trial/trial_d2e8267697c34681. Re-running the agent live requires EVAL_PLATFORM_ENABLE_OAUTH_SMOKE=1 and is non-deterministic.
Trial trial_d2e8267697c34681 · verifier authoritative; classifier explanatory.