--- tags: homework --- # Digital Circuit Design MP#4 ## GTKWave ![](https://hackmd.io/_uploads/S1O3ZtqB2.png) ## Code ### Explanation 1. Change the parameter `A_sel_B` to `A_sel_B_sub_A` and `A_sel_Sub` to `A_sel_A_sub_B`. 2. Add wire `A_sub_B_out[W-1:0]` and rename `sub_out[W-1:0]` to `B_sub_A_out[W-1:0]`. 3. Assign `B_sub_A_out = B - A` and `A_sub_B_out = A - B`. 3. Modify the always block in the datapath ```verilog! always @(*) case (A_sel) A_sel_In: A_out = operand_A ; A_sel_B_sub_A: A_out = B_sub_A_out; A_sel_A_sub_B: A_out = A_sub_B_out; default: A_out = 16'bx ; endcase ``` ### Full code ```verilog! `timescale 1ns/10ps module GCD_cntrl (idle, result_rdy, A_en, B_en, B_sel, clk, reset_, input_available, result_taken, B_zero, A_lt_B, A_sel); output reg idle, result_rdy, A_en, B_en, B_sel; input clk, reset_, input_available, result_taken, B_zero, A_lt_B; output reg [1:0] A_sel ; parameter WAIT = 2'd0, CALC = 2'd1, DONE = 2'd2; parameter A_sel_In= 2'b00, A_sel_B_sub_A=2'b01, A_sel_A_sub_B=2'b10, A_sel_X=2'bxx; parameter B_sel_In= 1'b0, B_sel_A= 1'b1, B_sel_X=1'bx; parameter W = 16; reg [1:0] next_state; reg [1:0] state; always @(*) begin next_state = state; case ( state ) WAIT : if ( input_available ) next_state = CALC; CALC : if ( B_zero ) next_state = DONE; DONE : if ( result_taken ) next_state = WAIT; default: next_state = 2'bxx; endcase end always @(posedge clk or negedge reset_) if(!reset_) state = WAIT ; else state = next_state ; always @(*) begin //Default control signals A_sel = A_sel_X; A_en = 1'b0; B_sel = B_sel_X; B_en = 1'b0; idle = 1'b1; result_rdy = 1'b0; case ( state ) WAIT: begin A_sel = A_sel_In; A_en = 1'b1; B_sel = B_sel_In; B_en = 1'b1; idle = 1'b1; end CALC: if ( A_lt_B ) begin A_sel = A_sel_B_sub_A; A_en = 1'b1; B_sel = B_sel_A; B_en = 1'b1; idle = 1'b0; end else if ( !B_zero ) begin A_sel = A_sel_A_sub_B; A_en = 1'b1; idle = 1'b0; end DONE: begin result_rdy = 1'b1; end endcase end endmodule module GCDdatapath (clk, operand_A, operand_B, result_data, A_en, B_en, A_sel, B_sel, B_zero, A_lt_B); parameter A_sel_In= 2'b00; parameter A_sel_B_sub_A=2'b01; parameter A_sel_A_sub_B=2'b10; parameter A_sel_X=2'bxx; parameter B_sel_In= 1'b0; parameter B_sel_A= 1'b1; parameter B_sel_X=1'bx; parameter W = 16; input clk; // Data signals input [W-1:0] operand_A, operand_B; output [W-1:0] result_data; // Control signals (ctrl->dpath) input A_en, B_en; input [1:0] A_sel; input B_sel; // Control signals (dpath->ctrl) output B_zero, A_lt_B; reg [W-1:0] A_out; reg [W-1:0] A; reg [W-1:0] B_out; reg [W-1:0] B; wire [W-1:0] B_sub_A_out; wire [W-1:0] A_sub_B_out; always @(*) case (A_sel) A_sel_In: A_out = operand_A ; A_sel_B_sub_A: A_out = B_sub_A_out; A_sel_A_sub_B: A_out = A_sub_B_out; default: A_out = 16'bx ; endcase always @(*) case(B_sel) B_sel_In: B_out = operand_B ; B_sel_A: B_out = A ; default: B_out = 16'bx ; endcase always @(posedge clk) if (A_en) A = A_out; always @(posedge clk) if (B_en) B = B_out ; assign B_zero = (B == 0); assign A_lt_B = (A < B); assign B_sub_A_out = B - A; assign A_sub_B_out = A - B; assign result_data = A; endmodule module in_mdl (operand_A, operand_B, input_available, idle); parameter W = 16; output reg [W-1:0] operand_A, operand_B; output reg input_available; input idle ; initial begin operand_A = 36; operand_B = 15; input_available = 1; #40 input_available = 0; end always begin #40 if (idle) begin operand_A = operand_A * 5; operand_B = operand_B * 2; input_available = 1; end else input_available = 0; end endmodule module out_mdl (result_data, result_rdy, result_taken); parameter W = 16; input [W-1:0] result_data; input result_rdy; output reg result_taken; reg [W-1:0] result; initial result_taken = 0; always @ (result_rdy) if (result_rdy) begin result = result_data; result_taken = 1 ; end else result_taken = 0 ; endmodule module testfixture ; parameter W = 16; //GCD instances wire [1:0] A_sel ; wire [W-1:0] operand_A, operand_B, result_data; reg clk, reset_; GCD_cntrl C1 (idle, result_rdy, A_en, B_en, B_sel, clk, reset_, input_available, result_taken, B_zero, A_lt_B, A_sel) ; GCDdatapath D1 (clk, operand_A, operand_B, result_data, A_en, B_en, A_sel, B_sel, B_zero, A_lt_B) ; in_mdl I1 (operand_A, operand_B, input_available, idle) ; out_mdl O1(result_data, result_rdy, result_taken) ; //Stimulus initial begin clk = 1'b0 ; repeat(80) #10 clk = ~clk ; $finish ; end initial begin reset_ = 0; #15 reset_ = 1'b1; end initial begin $dumpfile("GCD1.vcd"); $dumpvars; end endmodule ```