`timescale 1ns / 1ps module modinv_helper_invert_update ( clk, rst_n, ena, rdy, u_gt_v, v_eq_1, u_is_even, v_is_even, r_addr, r_wren, r_dout, s_addr, s_wren, s_dout, u_addr, u_wren, u_dout, v_addr, v_wren, v_dout, r_dbl_addr, r_dbl_din, s_dbl_addr, s_dbl_din, r_plus_s_addr, r_plus_s_din, u_half_addr, u_half_din, v_half_addr, v_half_din, u_minus_v_half_addr, u_minus_v_half_din, v_minus_u_half_addr, v_minus_u_half_din ); // // Parameters // parameter BUFFER_NUM_WORDS = 9; parameter BUFFER_ADDR_BITS = 4; // // clog2 // `include "..\modinv_clog2.v" // // Constants // localparam PROC_NUM_CYCLES = BUFFER_NUM_WORDS + 3; localparam PROC_CNT_BITS = clog2(PROC_NUM_CYCLES); // // Ports // input wire clk; input wire rst_n; input wire ena; output wire rdy; input wire u_gt_v; input wire v_eq_1; input wire u_is_even; input wire v_is_even; output wire [BUFFER_ADDR_BITS-1:0] r_addr; output wire [BUFFER_ADDR_BITS-1:0] s_addr; output wire [BUFFER_ADDR_BITS-1:0] u_addr; output wire [BUFFER_ADDR_BITS-1:0] v_addr; output wire r_wren; output wire s_wren; output wire u_wren; output wire v_wren; output wire [ 32-1:0] r_dout; output wire [ 32-1:0] s_dout; output wire [ 32-1:0] u_dout; output wire [ 32-1:0] v_dout; output wire [BUFFER_ADDR_BITS-1:0] r_dbl_addr; output wire [BUFFER_ADDR_BITS-1:0] s_dbl_addr; output wire [BUFFER_ADDR_BITS-1:0] r_plus_s_addr; output wire [BUFFER_ADDR_BITS-1:0] u_half_addr; output wire [BUFFER_ADDR_BITS-1:0] v_half_addr; output wire [BUFFER_ADDR_BITS-1:0] u_minus_v_half_addr; output wire [BUFFER_ADDR_BITS-1:0] v_minus_u_half_addr; input wire [ 32-1:0] r_dbl_din; input wire [ 32-1:0] s_dbl_din; input wire [ 32-1:0] r_plus_s_din; input wire [ 32-1:0] u_half_din; input wire [ 32-1:0] v_half_din; input wire [ 32-1:0] u_minus_v_half_din; input wire [ 32-1:0] v_minus_u_half_din; // // Counter // reg [PROC_CNT_BITS-1:0] proc_cnt; wire [PROC_CNT_BITS-1:0] proc_cnt_max = PROC_NUM_CYCLES - 1; wire [PROC_CNT_BITS-1:0] proc_cnt_zero = {PROC_CNT_BITS{1'b0}}; wire [PROC_CNT_BITS-1:0] proc_cnt_next = (proc_cnt < proc_cnt_max) ? proc_cnt + 1'b1 : proc_cnt_zero; // // Addresses // reg [BUFFER_ADDR_BITS-1:0] addr_in; wire [BUFFER_ADDR_BITS-1:0] addr_in_max = BUFFER_NUM_WORDS - 1; wire [BUFFER_ADDR_BITS-1:0] addr_in_zero = {BUFFER_ADDR_BITS{1'b0}}; wire [BUFFER_ADDR_BITS-1:0] addr_in_next = (addr_in < addr_in_max) ? addr_in + 1'b1 : addr_in_zero; reg [BUFFER_ADDR_BITS-1:0] addr_out; wire [BUFFER_ADDR_BITS-1:0] addr_out_max = BUFFER_NUM_WORDS - 1; wire [BUFFER_ADDR_BITS-1:0] addr_out_zero = {BUFFER_ADDR_BITS{1'b0}}; wire [BUFFER_ADDR_BITS-1:0] addr_out_next = (addr_out < addr_out_max) ? addr_out + 1'b1 : addr_out_zero; assign r_addr = addr_out; assign s_addr = addr_out; assign u_addr = addr_out; assign v_addr = addr_out; assign r_dbl_addr = addr_in; assign s_dbl_addr = addr_in; assign r_plus_s_addr = addr_in; assign u_half_addr = addr_in; assign v_half_addr = addr_in; assign u_minus_v_half_addr = addr_in; assign v_minus_u_half_addr = addr_in; // // Ready Flag // assign rdy = (proc_cnt == proc_cnt_zero); // // Address Increment Logic // wire inc_addr_in; wire inc_addr_out; wire [PROC_CNT_BITS-1:0] cnt_inc_addr_in_start = 1; wire [PROC_CNT_BITS-1:0] cnt_inc_addr_in_stop = BUFFER_NUM_WORDS; wire [PROC_CNT_BITS-1:0] cnt_inc_addr_out_start = 2; wire [PROC_CNT_BITS-1:0] cnt_inc_addr_out_stop = BUFFER_NUM_WORDS + 1; assign inc_addr_in = (proc_cnt >= cnt_inc_addr_in_start) && (proc_cnt <= cnt_inc_addr_in_stop); assign inc_addr_out = (proc_cnt >= cnt_inc_addr_out_start) && (proc_cnt <= cnt_inc_addr_out_stop); always @(posedge clk) begin // if (inc_addr_in) addr_in <= addr_in_next; else addr_in <= addr_in_zero; // if (inc_addr_out) addr_out <= addr_out_next; else addr_out <= addr_out_zero; // end // // Write Enable Logic // wire wren_out; wire [PROC_CNT_BITS-1:0] cnt_wren_out_start = 2; wire [PROC_CNT_BITS-1:0] cnt_wren_out_stop = BUFFER_NUM_WORDS + 1; assign wren_out = (proc_cnt >= cnt_wren_out_start) && (proc_cnt <= cnt_wren_out_stop); reg r_wren_allow; reg s_wren_allow; reg u_wren_allow; reg v_wren_allow; assign r_wren = wren_out && r_wren_allow && !v_eq_1 && !rdy; assign s_wren = wren_out && s_wren_allow && !v_eq_1 && !rdy; assign u_wren = wren_out && u_wren_allow && !v_eq_1 && !rdy; assign v_wren = wren_out && v_wren_allow && !v_eq_1 && !rdy; // // Data Logic // reg [31: 0] r_dout_mux; reg [31: 0] s_dout_mux; reg [31: 0] u_dout_mux; reg [31: 0] v_dout_mux; assign r_dout = r_dout_mux; assign s_dout = s_dout_mux; assign u_dout = u_dout_mux; assign v_dout = v_dout_mux; always @(*) begin // // r, s, u, v // if (u_is_even) begin // u_dout_mux = u_half_din; v_dout_mux = {32{1'bX}}; r_dout_mux = {32{1'bX}}; s_dout_mux = s_dbl_din; // u_wren_allow = 1'b1; v_wren_allow = 1'b0; r_wren_allow = 1'b0; s_wren_allow = 1'b1; // end else begin // if (v_is_even) begin // u_dout_mux = {32{1'bX}}; v_dout_mux = v_half_din; r_dout_mux = r_dbl_din; s_dout_mux = {32{1'bX}}; // u_wren_allow = 1'b0; v_wren_allow = 1'b1; r_wren_allow = 1'b1; s_wren_allow = 1'b0; // end else begin // u_dout_mux = u_gt_v ? u_minus_v_half_din : {32{1'bX}}; v_dout_mux = u_gt_v ? {32{1'bX}} : v_minus_u_half_din; r_dout_mux = u_gt_v ? r_plus_s_din : r_dbl_din; s_dout_mux = u_gt_v ? s_dbl_din : r_plus_s_din; // u_wren_allow = u_gt_v; v_wren_allow = !u_gt_v; r_wren_allow = 1'b1; s_wren_allow = 1'b1; // end // end // end // // Primary Counter Logic // always @(posedge clk or negedge rst_n) // if (rst_n == 1'b0) proc_cnt <= proc_cnt_zero; else begin if (!rdy) proc_cnt <= proc_cnt_next; else if (ena) proc_cnt <= proc_cnt_next; end endmodule