Embedded Systems Spring 2024
Lab 6 2's complement adder/subtractor.
Name:
Mason Brady
Email: mrbrady1@fortlewis.edu

2's Complement Adder / Subtractor


Introduction: This lab was to learn how to implement more complex circuits with all the techniques we've learned
Materials GVIM, Vivado, Basys 3
Methods / Results:

I am going to just copy my entire code for the two main modules for this code below here since I did it all in one go and kind of forgot to doccument how I was changing the code and I'm not really sure about everything I changed at this point. Most of it was fairly straight forward based off of the given instructions/what we've done in the past/ and the book/PicoBlaze documentation so it was just a lot of bug fixing.

Main Pico Button File
module pico_btn
   (
    input wire clk, reset,
    input wire [7:0] sw,
    input wire btnL,
    input wire btnR,
    output wire [3:0] an,
    output wire [7:0] seg,
    output wire [15:0] led,
    output [7:0] JA,
    output [7:0] JB
   );

   // signal declaration
   // KCPSM3/ROM signals
   wire [11:0] address;
   wire [17:0] instruction;
   wire [7:0] port_id, out_port;
   reg [7:0] in_port;
   wire  write_strobe, read_strobe;
   wire bram_enable;
   wire rdl;
   wire interrupt_ack;
   wire k_write_strobe;
   // I/O port signals
   // output enable
   reg [3:0] en_d;
   // four-digit seven-segment led display
   reg [7:0] ds3_reg, ds2_reg, ds1_reg, ds0_reg;
   // two pushbuttons
   reg btnc_flag_reg, btns_flag_reg;
   wire btnc_flag_next, btns_flag_next;
   wire set_btnc_flag, set_btns_flag, clr_btn_flag;

   //body
   // =====================================================
   //  I/O modules
   // =====================================================
   disp_mux disp_unit
      (.clk(clk),
       .in3(ds3_reg), .in2(ds2_reg), .in1(ds1_reg),
       .in0(ds0_reg), .an(an), .sseg(seg), .led(led), .JA(JA), .JB(JB));
   debounce btnc_unit
      (.clk(clk), .sw(btnL),
       .db_level(), .db_tick(set_btnc_flag));
   debounce btns_unit
      (.clk(clk), .sw(btnR),
       .db_level(), .db_tick(set_btns_flag));
   // =====================================================
   //  KCPSM and ROM instantiation
   // =====================================================
   kcpsm6 #(.interrupt_vector (12'h3FF), .scratch_pad_memory_size (64), .hwbuild (8'h00))
   processor (.address (address), .instruction(instruction), .bram_enable(bram_enable), .port_id(port_id), .write_strobe(write_strobe), .k_write_strobe (k_write_strobe),
   .out_port(out_port), .read_strobe (read_strobe), .in_port(in_port), .interrupt (1'b0), . interrupt_ack (interrupt_ack), .reset (rdl), .sleep (1'b0), .clk(clk));
   btn_rom #(.C_FAMILY("7S"), .C_RAM_SIZE_KWORDS(1), .C_JTAG_LOADER_ENABLE (1))
   program_rob (.rdl (rdl), .enable (bram_enable), .address (address), .instruction(instruction), .clk(clk));
   // =====================================================
   //  output interface
   // =====================================================
   //    outport port id:
   //      0x00: ds0
   //      0x01: ds1
   //      0x02: ds2
   //      0x03: ds3
   // =====================================================
   // registers
   always @(posedge clk)
      begin
         if (en_d[0])
            ds0_reg <= out_port;
         if (en_d[1])
            ds1_reg <= out_port;
         if (en_d[2])
            ds2_reg <= out_port;
         if (en_d[3])
            ds3_reg <= out_port;
      end
   // decoding circuit for enable signals
   always @*
      if (write_strobe)
         case (port_id[1:0])
            2'b00: en_d = 4'b0001;
            2'b01: en_d = 4'b0010;
            2'b10: en_d = 4'b0100;
            2'b11: en_d = 4'b1000;
         endcase
      else
         en_d = 4'b0000;

   // =====================================================
   //  input interface
   // =====================================================
   //    input port id
   //      0x00: flag
   //      0x01: switch
   // =====================================================
   // input register (for flags)
   always @(posedge clk)
      begin
         btnc_flag_reg <= btnc_flag_next;
         btns_flag_reg <= btns_flag_next;
      end
   assign btnc_flag_next = (set_btnc_flag) ? 1'b1 :
                           (clr_btn_flag)  ? 1'b0 :
                            btnc_flag_reg;
   assign btns_flag_next = (set_btns_flag) ? 1'b1 :
                           (clr_btn_flag)  ? 1'b0 :
                            btns_flag_reg;
   // decoding circuit for clear signals
   assign clr_btn_flag = read_strobe && (port_id[0]==1'b0);
   // input multiplexing
   always @*
      case(port_id[0])
         1'b0: in_port = {6'b0, btns_flag_reg, btnc_flag_reg};
         1'b1: in_port = sw;
      endcase

endmodule


DISP MUX File

// Listing 4.13
module LCD_driver (clk, reset, wr_en, data_in, data_out, en, rs);
input clk;
input reset;
input wr_en;
input [7:0] data_in;
output reg [7:0] data_out;
output reg en;
output reg rs;
parameter clk_param = 100000;
localparam INIT=2'b00, WAIT=2'b01, WRITE=2'b10;
reg [2:0] state = INIT;
localparam init_index=3;
localparam char_index=15;
reg [3:0] init_count=0;
integer limit_count=0;
reg [7:0] init [3:0];
reg [3:0] clear=0;
initial begin
init [0]=8'h30; // 1 Line, 5x8 Dots
init [1]=8'h01; // Clear display
init [2]=8'h06; // Increment cursor (Shift cursor to right)
init [3]=8'h0F; // Display on cursor blinking
rs=1'b1;
end
always @ (negedge clk)
begin
rs <=1'b1;
en <=1'b1;
if (reset)
begin
state <= INIT;
init_count <= 0;
limit_count <= 0;
clear <= 0; end
else begin
case (state)
INIT:
begin
rs <= 0;
data_out <= init [init_count];
if (limit_count == clk_param) begin
en <= 0;
limit_count <= 0;
init_count <= init_count + 1'b1;
if (init_count == init_index) begin
init_count <= 0;
state <= WAIT;
end
end
else
limit_count <= limit_count + 1;
end
WAIT:
if (wr_en)
state <= WRITE;
WRITE :
begin
data_out <= data_in;
if (limit_count == clk_param)
begin
en <= 0;
limit_count <= 0;
clear <= clear + 1'b1;
if (clear == char_index)
begin
state <= INIT;
clear <= 0;
end
else
state <= WAIT;
end else
limit_count <= limit_count + 1;
end
endcase
end
end
endmodule

module disp_mux
   (
    input wire clk, reset,
    input [7:0] in3, in2, in1, in0,
    output reg [3:0] an,   // enable, 1-out-of-4 asserted low
    output reg [7:0] sseg,  // led segments
    output reg [15:0] led,
    output [7:0] JA,
    output [7:0] JB,
    input [15:0] sw
   );

   // constant declaration
   // refreshing rate around 800 Hz (50 MHz/2^16)
   localparam N = 18;

   // signal declaration
   reg [N-1:0] q_reg;
   wire [N-1:0] q_next;
  
    parameter clk_param = 1600000;
    reg [7:0] data [15:0];
    reg [7:0] character;
    wire [7:0] data_in;
    integer counter=0;
    reg [3:0] index=0;
    reg wr_en=0;
    integer digit0, digit1, digit2, digit3;
    LCD_driver lcdl(.clk(clk), .reset(sw[15]), .wr_en(wr_en), .data_in(character), .data_out(JA), .en(JB[0]), .rs(JB[2]));
   // N-bit counter
   // register
   always @(posedge clk,  posedge reset)
      if (reset)
         q_reg <= 0;
      else
         q_reg <= q_next;

   // next-state logic
   assign q_next = q_reg + 1;

   // 2 MSBs of counter to control 4-to-1 multiplexing
   // and to generate active-low enable signal
   always @* begin
      case (q_reg[N-1:N-2])
         2'b00:
            begin
               an = 4'b1110;
               sseg = in0;
               case(in0)
                    192: begin led[3:0] = 0; digit0 = 48; end
                    249: begin led[3:0] = 1; digit0 = 49; end
                    164: begin led[3:0] = 2; digit0 = 50; end
                    176: begin led[3:0] = 3; digit0 = 51; end
                    153: begin led[3:0] = 4; digit0 = 52; end
                    146: begin led[3:0] = 5; digit0 = 53; end
                    130: begin led[3:0] = 6; digit0 = 54; end
                    248: begin led[3:0] = 7; digit0 = 55; end
                    128: begin led[3:0] = 8; digit0 = 56; end
                    132: begin led[3:0] = 9; digit0 = 57; end
                    144: begin led[3:0] = 10; digit0 = 65; end
                    131: begin led[3:0] = 11; digit0 = 66; end
                    198: begin led[3:0] = 12; digit0 = 67; end
                    261: begin led[3:0] = 13; digit0 = 68; end
                    134: begin led[3:0] = 14; digit0 = 69; end
                    142: begin led[3:0] = 15; digit0 = 70; end
                endcase
            end
         2'b01:
            begin
               an =  4'b1101;
               sseg = in1;
               case(in1)
                    192: begin led[7:4] = 0; digit1 = 48; end
                    249: begin led[7:4] = 1; digit1 = 49; end
                    164: begin led[7:4] = 2; digit1 = 50; end
                    176: begin led[7:4] = 3; digit1 = 51; end
                    153: begin led[7:4] = 4; digit1 = 52; end
                    146: begin led[7:4] = 5; digit1 = 53; end
                    130: begin led[7:4] = 6; digit1 = 54; end
                    248: begin led[7:4] = 7; digit1 = 55; end
                    128: begin led[7:4] = 8; digit1 = 56; end
                    132: begin led[7:4] = 9; digit1 = 57; end
                    144: begin led[7:4] = 10; digit1 = 65; end
                    131: begin led[7:4] = 11; digit1 = 66; end
                    198: begin led[7:4] = 12; digit1 = 67; end
                    261: begin led[7:4] = 13; digit1 = 68; end
                    134: begin led[7:4] = 14; digit1 = 69; end
                    142: begin led[7:4] = 15; digit1 = 70; end
                endcase
            end
         2'b10:
            begin
               an =  4'b1011;
               sseg = in2;
               case(in2)
                    192: begin led[11:8] = 0; digit2 = 48; end
                    249: begin led[11:8] = 1; digit2 = 49; end
                    164: begin led[11:8] = 2; digit2 = 50; end
                    176: begin led[11:8] = 3; digit2 = 51; end
                    153: begin led[11:8] = 4; digit2 = 52; end
                    146: begin led[11:8] = 5; digit2 = 53; end
                    130: begin led[11:8] = 6; digit2 = 54; end
                    248: begin led[11:8] = 7; digit2 = 55; end
                    128: begin led[11:8] = 8; digit2 = 56; end
                    132: begin led[11:8] = 9; digit2 = 57; end
                    144: begin led[11:8] = 10; digit2 = 65; end
                    131: begin led[11:8] = 11; digit2 = 66; end
                    198: begin led[11:8] = 12; digit2 = 67; end
                    261: begin led[11:8] = 13; digit2 = 68; end
                    134: begin led[11:8] = 14; digit2 = 69; end
                    142: begin led[11:8] = 15; digit2 = 70; end
                endcase
            end
         default:
            begin
               an =  4'b0111;
               sseg = in3;
              
               case(in3)
                    192: begin led[15:12] = 0; digit3 = 48; end
                    249: begin led[15:12] = 1; digit3 = 49; end
                    164: begin led[15:12] = 2; digit3 = 50; end
                    176: begin led[15:12] = 3; digit3 = 51; end
                    153: begin led[15:12] = 4; digit3 = 52; end
                    146: begin led[15:12] = 5; digit3 = 53; end
                    130: begin led[15:12] = 6; digit3 = 54; end
                    248: begin led[15:12] = 7; digit3 = 55; end
                    128: begin led[15:12] = 8; digit3 = 56; end
                    132: begin led[15:12] = 9; digit3 = 57; end
                    144: begin led[15:12] = 10; digit3 = 65; end
                    131: begin led[15:12] = 11; digit3 = 66; end
                    198: begin led[15:12] = 12; digit3 = 67; end
                    261: begin led[15:12] = 13; digit3 = 68; end
                    134: begin led[15:12] = 14; digit3 = 69; end
                    142: begin led[15:12] = 15; digit3 = 70; end
                endcase
            end
       endcase
     
       
       
    end
    always @ (posedge clk) begin
        data[0]<=digit3; data [1] <=digit2; data [2] <=digit1; data [3] <=digit0; data [4] <= " "; data [5] <=" "; data [6]<=" "; data [7]<=" "; data [8]<=" "; data [9]<=" "; data [10] <=" "; data [11]<=" "; data [12] <=" "; data [13]<=" "; data [14] <=" "; data [15] <=" ";
       
        if (counter == clk_param) begin
            counter <= 0;
            wr_en <= 1'b1;
            character <= data[index];
            index <= index + 1'b1;
        end else begin
            wr_en <= 0;
            counter <= counter + 1;
        if (index > 15) index <= 0;
        end
    end
endmodule

1) Part 1 and 2

I implemented these parts at the same time to reduce the time it took to compuile and upload youtube videos since that usually slows down the process quite a bit. Implementing the LED display was fairly straight forward and then I just used the third decimal point as the last LED. The video can be seen below.
I was kinda stupid so I ended up inverting the entire binary string instead of everything but the last bit and that took me too long to realize.



2) Part 3

For part 3 I copied my code from the LCD display lab into the top of the MUX module before integrating it by copying more of my code from last time and then just adding the digits into the case statements from the first part LEDs to change my digits. This worked out pretty good but for some reason I had to invert my digits from what I thought they would be.



Discussion: Easy Peasy just a ton of typing