Monday, December 27, 2021

Arduino Low Power battery operated motion activated switch

blogging after 5 years 

As long as I could remember I wanted to make a motion activated switch which can run on batteries for days/months.

2016 I gave it first short . with Arduino pro mini , 18650 3.7V battery , PIR sensor , LDR , servo and dual H bridge driver . After full charge ~4.2V the circuit worked as expected i.e switching ON when it detects motion and turn OFF when there is no motion detected for ~1min .

then once the battery drained to a point around ~3.7V , Arduino started getting reset when ever the servo motor moves . battery didn't have enough power to drive servo and maintain stable voltage . Note I didn't have voltage regulator to save power .

here is the video 


 After the above v1.0 his I have made below changes for v2.0 

instead of one bulky 18650 battery switched to 4 AAA 800mAh 

swapped dual H bridge driver with a single N-channel enhancement MOSFET

v2.0 idle/standby current is 350micro Amps , batteries should easily last for 1-2months 


fritzing  schematic 

this is how the prototype is looking  , working on creating a custom PCB 



//Arduino code for v2.0 goes something like this . will post video and schematic at later time 

#include <LowPower.h>

static const uint8_t LDRPin = A7 ;

static const uint8_t LDRPin_source = 7 ;

static const uint8_t pirPin = 2;

static const uint8_t mosfet_pin = 5;

static const uint8_t servoPin = 8;

uint8_t cnt = 0;

bool is_light_on = false;

byte val;


void ServoOn () {

  digitalWrite(mosfet_pin, HIGH);

  LowPower.powerDown(SLEEP_120MS, ADC_OFF, BOD_OFF);

}

void ServoOff() {

  digitalWrite(mosfet_pin, LOW);

  LowPower.powerDown(SLEEP_120MS, ADC_OFF, BOD_OFF);

}


void ServoInitialize() {

  pinMode(servoPin, OUTPUT);

}

void PirInitialize() {

  pinMode(pirPin, INPUT);

}

void LdrInitialize() {

  pinMode(LDRPin_source, OUTPUT);

  digitalWrite(LDRPin_source, LOW);

}

void MotorModuleInitialize () {

  pinMode(mosfet_pin, OUTPUT);

}

void setup() {

  LdrInitialize();

  PirInitialize();

  ServoInitialize();

  MotorModuleInitialize ();

  readAnalogValue();

  delay(30);


  pinMode(LED_BUILTIN, OUTPUT);

  for (cnt = 0 ; cnt < 3 ; cnt++ ) {

    if ( cnt % 2 == 0 ) {

            digitalWrite(LED_BUILTIN, LOW);

    } else {

            digitalWrite(LED_BUILTIN, HIGH);

    }

    delay(1000);

  }


  switch_on();

}

int LdrReading = 0;

void readAnalogValue () {

  digitalWrite(LDRPin_source, HIGH);

  delayMicroseconds(50);

  LdrReading = analogRead(LDRPin);

  delayMicroseconds(5);

  digitalWrite(LDRPin_source, LOW);

}

unsigned long my_time;


void set_angle(int val, int cnt) {

  for ( int i = 0 ; i < cnt ; i++ ) {

    digitalWrite(servoPin, HIGH);

    delayMicroseconds(val);

    digitalWrite(servoPin, LOW);

    LowPower.powerDown(SLEEP_30MS, ADC_OFF, BOD_OFF);

  }

}


void switch_mid() {

  ServoOn ();

  set_angle(100 * 16, 2 * 16 );

  ServoOff();

}

void switch_on() {

  is_light_on = true ;

  ServoOn ();

  set_angle(93 * 16, 2 * 16 );

  ServoOff();

}


void switch_off() {

  is_light_on = false ;

  ServoOn ();

  set_angle(40 * 16, 2 * 16 + 2 );

  ServoOff();

}


void motionDetection()

{

  val = digitalRead(pirPin);

  

  if (val == HIGH && is_light_on == false) {

    readAnalogValue();

    if ( LdrReading > 985 ) {

      switch_on();

    } 

  } else if ( val == LOW && is_light_on == true )   {

    switch_off();

  } 

}


void wakeUp () {  }


void loop () {


  attachInterrupt(digitalPinToInterrupt(pirPin), wakeUp, CHANGE);

  LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);

  detachInterrupt(digitalPinToInterrupt(pirPin));

  motionDetection();delay(100);


}


Friday, June 17, 2016

MATLAB SOM Code - Self Organizing Maps Character recognition

SOM is a type of Artificial Neural Network , I've used this for character recognition along with character segmentation in Matlab 
Here goes the code for SOM , below code will train the network for Alphabets  

f=imread('009.jpg');
BW1 = roicolor(f(:,:,1),180,255);
BW2 = roicolor(f(:,:,2),180,255);
BW3 = roicolor(f(:,:,3),180,255);
b=~(BW1|BW2|BW3);
se1=[0 1 0 ; 1 1 1 ;0 1 0];
b=imdilate(b,se1);
s=size(b);
p=1;q=1;start=1;maxe(1)=0;
for i=1:s(1,2)
    count=0;

    for j=30:s(1,1)
        if(b(j,i)==1)
            count=count+1;
  
        end
        if(start==0)
            if(maxe(p)<count)
                maxe(p)=count;
                loc(p)=i-L(q-1);
            end
        end
        histo1(i)=count;
    end

    if(count>0 && start==1)
         
        
         L(q)=i;
          q=q+1;
          start=0;
     end
     if(count==0 && start==0)
         R(p)=i;
         p=p+1;
         start=1;
         maxe(p)=0;
     end
        
end

p=1;q=1;start=1;maxe1(1)=0;
for i=20:s(1,1)-20
    count=0;
    for j=10:s(1,2)-20
        if(b(i,j)==1)
            count=count+1;
        end
        if(start==0)
            if(maxe1(p)<count)
                maxe1(p)=count;
            end
        end
        histo2(i)=count;
    end
    if(count>0 && start==1)
         
        
         L1(q)=i;
          q=q+1;
          start=0;
     end
     if(count==0 && start==0)
         R1(p)=i;
         p=p+1;
         start=1;
         maxe1(p)=0;
     end
end

data(:,1)=double(reshape(imresize(b(L1(1):R1(1),L(1):R(1)),[25,25]),625,1));
data(:,2)=double(reshape(imresize(b(L1(1):R1(1),L(2):R(2)),[25,25]),625,1));
data(:,3)=double(reshape(imresize(b(L1(1):R1(1),L(3):R(3)),[25,25]),625,1));
data(:,4)=double(reshape(imresize(b(L1(1):R1(1),L(4):R(4)),[25,25]),625,1));

totalW = 100;
[I,J] = ind2sub([10, 10], 1:100);
N = size(data,2);
w = rand(625, totalW);
eta0 = 50;
etaN = eta0;
tau2 = 100;


sig0 = 1;
sigN = sig0;
tau1 = 10;

for po=1:100
    for j=1:N

      x = data(:,j);
       dist = sum( sqrt((w - repmat(x,1,totalW)).^2),1);
       [v ind] = min(dist);
        
      ri = [I(ind), J(ind)];
      dist = 1/(sqrt(2*pi)*sigN).* exp( sum(( ([I( : ), J( : )] - repmat(ri, totalW,1)) .^2) ,2)/(-2*sigN))*etaN;

      for rr = 1:100
           w(:,rr) = w(:,rr) + dist(rr).*( x - w(:,rr));
      end
     
    end
    etaN = eta0 * exp(-po/tau2);
    sigN = sig0*exp(-po/tau1); 
     
   
   if mod(po,100) == 1
        figure;
        axis off;
       hold on;
       for ab = 1:100
            
            subplot(10,10,ab);
            axis off;
            imagesc(reshape(w(:,ab),25,25));
            
         axis off;
       end
       hold off;
   end

end




   
        

Wednesday, June 15, 2016

Synthesizable Verilog RISC processor design with Direct/Indirect memory access

Hello ,
         Sharing my old processor :) CISC processor is coming soon .

Verilog code synthesized/mapped/Place&Routed in Xilinx ISE , Device Vertex 4/XC4VSX25
This in a 16-bit RISC with Hardwired Control UNIT , take 4 cycles for execution .
Capable of Arithmetic/Logic/Branch/Memory instructions with direct and indirect access to RAM locations via general purpose registers 0:15

Memory instructions , address can be stored in one the general purpose registers and can be used to store result at the location
Branch instructions can be unconditional and conditional based on Carry-out flag or Zero-Flag .

Below simulation shows RISC processor running Fibonacci series in
gen_reg[1] = 1 2 3 5 8 13 21 34 55 89 ... (loop) 1 2 3 4 .....


Here goes the code and test-bench for Fibonacci series

ALU Code
module mini_alu (a,b,cin,result,sel,cout);
    input [15:0] a,b;
    input cin;
    output cout;
    input [4:0]sel;
    output [15:0]result;
    reg [15:0] result;
    reg cout ;
    
    always @ ( sel or a or b or cin ) 
    begin
        case (sel)
            5'd0:{cout,result} = a ;
            5'd1:{cout,result} = a+1;
            5'd2:{cout,result} = a+b;
            5'd3:{cout,result} = a+b+cin;            
            5'd4:{cout,result} = a-1;
            5'd5:{cout,result} = a-b;
            5'd6:{cout,result} = a-b-cin;
            5'd7:{cout,result} = 16'd0;
            5'd8:{cout,result} = a|b;
            5'd9:{cout,result} = a^b;
            5'd10:{cout,result} = a&b;
            5'd11:{cout,result} = ~a;
            default: {cout,result} = 16'd0;
        endcase 
    end
       
endmodule
 Single Port SRAM with single cycle read and write

module sram(datain,dataout,wr_add,rd_add,clk,enable,read,write);
    input clk,enable,read,write;
    output [15:0] dataout;
    input [15:0]datain;
    input [7:0]wr_add,rd_add;
    reg [15:0]dataout;
    reg [15:0]MEM[255:0];
    
    always @ ( posedge clk )
    begin
        if (enable == 1'd1 && write == 1'd1)
        begin
            MEM[wr_add] <= datain ;
        end
    end
    
    always @ ( posedge clk )
    begin
     if ( enable == 1'd1 && read == 1'd1 )
        begin
             dataout <=  MEM[rd_add];
        end
        else
        begin
           dataout <= dataout;
        end
    end
    
endmodule
Program ROM , from where PC will get Instruction Register to execute commands
module program_rom (clk,add,data,enable,rst);
  input clk , enable,rst;
  input [7:0]add;
  output [31:0]data;
  wire [31:0]data_wire[255:0];
  reg [31:0]data;
  
  // Arithmetic Instructions 
  assign data_wire[0] = {16'd1,4'd0,4'd0,4'd1,4'b0001};
  assign data_wire[1] = {16'd1,4'd0,4'd1,4'd1,4'b0001};
  assign data_wire[2] = {16'd2,4'd0,4'd2,4'd1,4'b0001};
  assign data_wire[3] = {16'd3,4'd0,4'd3,4'd1,4'b0001};
  assign data_wire[4] = {16'd4,4'd0,4'd4,4'd1,4'b0001};
  assign data_wire[5] = {16'd5,4'd0,4'd5,4'd1,4'b0001};
  assign data_wire[6] = {16'd6,4'd0,4'd6,4'd1,4'b0001};
  assign data_wire[7] = {16'd7,4'd0,4'd7,4'd1,4'b0001};
  // r8 <- r7
  assign data_wire[8] = {16'd7,4'd7,4'd8,4'd1,4'b0001};
  //r0 <- r0 + r8
  assign data_wire[9] = {16'd0,4'd8,4'd0,4'd2,4'b0001};
  // ADI r1 <- r1 + 4
  assign data_wire[10] = {16'd4,4'd0,4'd1,4'd8,4'b0001};
  //  INC r7
  assign data_wire[11] = {16'd0,4'd0,4'd7,4'd6,4'b0001};
  // DEC r5
  assign data_wire[12] = {16'd0,4'd0,4'd5,4'd7,4'b0001};
  // SUB r7 <-r7 - r2
  assign data_wire[13] = {16'd0,4'd2,4'd7,4'd4,4'b0001};
  // SBI r1 4
  assign data_wire[14] = {16'd4,4'd0,4'd4,4'd9,4'b0001};

  // LOGIC Instruction 
  // AND  r1 r2
  assign data_wire[15] = {16'd4,4'd2,4'd1,4'd0,4'b0010};
  // ANI r2 , FF
  assign data_wire[16] = {16'hFFFF,4'd0,4'd2,4'd1,4'b0010};
  // OR r3 , r1
  assign data_wire[17] = {16'd0,4'd1,4'd3,4'd2,4'b0010};
  //ORI r4,FF
  assign data_wire[18] = {16'hFFFF,4'd0,4'd4,4'd3,4'b0010};
  // NOT r5
  assign data_wire[19] = {16'hFFFF,4'd0,4'd5,4'd4,4'b0010};
  // CLEAR r0
  assign data_wire[20] = {16'd0,4'd0,4'd0,4'd5,4'b0010};
  
  // Memory Operations
  
  // STI r7 -> @ 01
  assign data_wire[21] = {12'd0,8'd1,4'd7,1'd1,1'd0,
                          1'd0,1'd1,4'b1000};
  // ST r7 -> @r0
  assign data_wire[22] = {16'd0,4'd0,4'd7,1'd1,1'd0,
                          1'd1,1'd0,4'b1000};
  // LDI r10 <- @01
  assign data_wire[23] = {12'd0,8'd1,4'd10,1'd0,1'd1,
                          1'd0,1'd1,4'b1000}  ;
  // LDI r11 <- @r0
  assign data_wire[24] = {16'd0,4'd0,4'd11,1'd0,1'd1,
                          1'd0,1'd1,4'b1000}  ;
// Load r0 1
assign data_wire[25] =  {16'd1,4'd0,4'd1,4'd1,4'b0001};    
// Load r1 1
assign data_wire[26] =  {16'd1,4'd0,4'd2,4'd1,4'b0001}; 
assign data_wire[27] =  {16'd1,4'd0,4'd3,4'd1,4'b0001};
assign data_wire[28] =  {16'd1,4'd0,4'd5,4'd1,4'b0001};
assign data_wire[29] = {16'd5,4'd0,4'd4,4'd1,4'b0001};
// Add r1 <- r1 + r3
assign data_wire[30] = {16'd0,4'd3,4'd1,4'd2,4'b0001};
// Copy r3 <- r2
assign data_wire[31] =  {16'd7,4'd2,4'd3,4'd0,4'b0001};
// Copy r2 <- r1
assign data_wire[32] = {16'd7,4'd1,4'd2,4'd0,4'b0001};
// ST r1 -> @r4
assign data_wire[33] = {16'd0,4'd4,4'd1,1'd1,1'd0,1'd1,1'd0,4'b1000};
// INC r4
assign data_wire[34] =  {16'd0,4'd0,4'd4,4'd6,4'b0001};
// SUB r1 -
assign data_wire [35] = {16'd89,4'd2,4'd1,4'd10,4'b0001};
assign data_wire[36] = {14'd0,8'd25,4'd3,4'b0100};
assign data_wire[37] = {14'd0,8'd30,4'd0,4'b0100};
assign data_wire[38] = 32'd0;
                                               
  always @( posedge clk )
  begin
    if (rst == 1'd1)
      begin
        data <= 30'd0;
      end
    else if (enable == 1'd1)
      begin
        data <= data_wire[add];
      end
    else
      begin
        data <= data ;
      end
  end
  
  
endmodule
  
Here comes Brain of our processor
module controlunit (T0,T4,arith_reg , logic_reg , branch_reg, 
                    alu_op1,alu_op2,regfile_write,
                    memory_reg,OP1,OP2,sram_write,sram_read,
                    DI,dec_data,alu_sel,data_bus_sel,
                    clk,rst,flags
                    );
  input clk ,rst,T0,T4 ; 
  input [1:0]flags;
  output regfile_write;
  output [1:0]alu_op1,alu_op2;
  output sram_write,sram_read;
  output arith_reg , logic_reg , branch_reg, memory_reg ;
  output [3:0]OP1,OP2;
  output DI ;
  output [1:0]data_bus_sel;
  output [15:0]dec_data;
  output [4:0]alu_sel;
  reg [4:0]alu_sel;
  reg sram_write,sram_read;
 // reg MEM_REG;
  reg regfile_write;
  reg [3:0]OP1,OP2;
  reg DI ;
  reg [1:0]data_bus_sel;
  reg [15:0]dec_data;
//  reg [3:0] old_OP1;
  reg [7:0]PC;
  wire [31:0]decoded_data;
  wire arith_reg , logic_reg , branch_reg, memory_reg ;
  wire [3:0]opcode;
  reg [1:0]alu_op1,alu_op2;
  reg NOP ; 
  


  
always  @ ( * )
begin
  if (arith_reg == 1'd1 )
    begin
    DI = decoded_data[6];
  end
  else if (memory_reg ==1'd1)
    begin
      DI = decoded_data[5];
    end
  else
    begin
      DI  = 1'd1;
    end
end

assign arith_reg  = decoded_data[0];
assign logic_reg  = decoded_data[1];
assign branch_reg = decoded_data[2];
assign memory_reg = decoded_data[3];


always @ ( opcode or branch_reg or flags)
begin
       if (branch_reg == 1'd1)
          begin
            case(opcode)
                4'd0:begin 
                     NOP = 1'd1;
                end
                4'd1:begin 
                  if (flags[1]==1'd1 )
                    begin
                      NOP = 1'd1;
                    end
                  else
                    begin
                      NOP = 1'd0;
                    end
                end
                4'd2:begin 
                  if (flags[1]==1'd0)
                    begin
                      NOP = 1'd1;
                    end
                  else
                    begin
                      NOP = 1'd0;
                    end
                end
                4'd3:begin 
                  if (flags[0]==1'd1)
                    begin
                      NOP = 1'd1;
                    end
                  else
                    begin
                      NOP = 1'd0;
                    end
                end
                4'd4:begin 
                  if (flags[0]==1'd0)
                    begin
                      NOP = 1'd1;
                    end
                  else
                    begin
                      NOP = 1'd0;
                    end
                end
                default:begin 
                  NOP = 1'd0;
                 end
            endcase
          end
      else
         begin
          NOP = 1'd0;
         end

end
  always @ ( posedge clk ) 
    begin
      if ( rst == 1'd1 )
      begin
        PC <= 8'd0;
      end
    else
      begin
        if (branch_reg == 1'd1 && T4 == 1'd1 )
          begin
            case(opcode)
                4'd0:begin 
                     PC <= decoded_data[31:16];
                end
                4'd1:begin 
                  if (flags[1]==1'd1  )
                    begin
                      PC <= decoded_data[31:16];
                    end
                  else
                    begin
                      PC <= PC + 1 ;
                    end
                end
                4'd2:begin 
                  if (flags[1]==1'd0)
                    begin
                      PC <= decoded_data[31:16];
                    end
                  else
                    begin
                      PC <= PC + 1 ;
                    end
                end
                4'd3:begin 
                  if (flags[0]==1'd1)
                    begin
                      PC <= decoded_data[15:8];
                    end
                  else
                    begin
                      PC <= PC + 1 ;
                    end
                end
                4'd4:begin 
                  if (flags[0]==1'd0)
                    begin
                      PC <= decoded_data[15:8];
                    end
                  else
                    begin
                      PC <= PC + 1 ;
                    end
                end
                default:begin 
                  PC <= PC + 1; 
                end
            endcase
          end
      else if (T4 == 1'd1)
         begin
          PC <= PC + 1;
         end
      else
        begin
          PC <= PC ;
        end
      end
    end

  program_rom u_program_rom(.clk(clk),.add(PC),.rst(rst),
                            .data(decoded_data),
                            .enable(T0));
  


always @ ( * )
begin
  if (arith_reg == 1'd1 || logic_reg == 1'd1 )
  begin      
    OP1 =decoded_data[11:8];
  end
  else if (memory_reg == 1'd1)
  begin
    OP1 = decoded_data[11:8];
  end    
  else
  begin
    OP1=4'd0;
  end
end
  
always @ ( * )
begin
  if (arith_reg == 1'd1 || logic_reg == 1'd1 )
  begin      
    OP2 = decoded_data[31:16];
  end
  else if (memory_reg == 1'd1)
  begin
    OP2 = decoded_data[31:16];
  end    
  else
  begin
    OP2 = 4'd0;
  end
end

always @ ( * )
begin
  if (arith_reg == 1'd1 || logic_reg == 1'd1)
    begin
      dec_data = decoded_data[27:12];
    end
  else if (memory_reg == 1'd1)
    begin
      dec_data = decoded_data[31:12];
    end
  else if (branch_reg == 1'd1)
    begin
      dec_data = decoded_data[15:0];
    end
  else
    begin
       dec_data = 16'd0;
    end
    
end

assign opcode=decoded_data[7:4];

always @ ( * )
begin
  if (arith_reg == 1'd1)
    begin
      case(opcode)
        4'd0:
        begin
          alu_sel = 5'd1;
          data_bus_sel = 2'd1;
          sram_write = 1'd0; sram_read =1'd0;
          alu_op1 = 2'd0; alu_op2 = 2'd0;
          regfile_write = 1'd1;
        end
        4'd1:
        begin
          alu_sel = 5'd1;
          data_bus_sel = 2'd1;
          sram_write= 1'd0; sram_read =1'd0;
          alu_op1 = 2'd0; alu_op2 = 2'd0;
          regfile_write = 1'd1;
        end
        4'd2:
        begin
          alu_sel = 5'd0;
          data_bus_sel = 2'd1;
          sram_write = 1'd0; sram_read =1'd1;
          alu_op1 = 2'd0; alu_op2 = 2'd1;
          regfile_write = 1'd0;
        end
        4'd3:
        begin
         alu_sel = 5'd3;
         data_bus_sel = 2'd1;
         sram_write = 1'd0; sram_read =1'd0;
         alu_op1 = 2'd0; alu_op2 = 2'd1;
         regfile_write = 1'd1;
        end
        4'd4:
        begin
          alu_sel = 5'd5;
          data_bus_sel = 2'd1;
          sram_write = 1'd0; sram_read =1'd0;
          alu_op1 = 2'd2; alu_op2 = 2'd1;
          regfile_write = 1'd1;
        end
        4'd5:
        begin
          alu_sel = 5'd6;
          data_bus_sel = 2'd1;
          sram_write = 1'd0; sram_read =1'd0;
          alu_op1 = 2'd0; alu_op2 = 2'd1;
          regfile_write = 1'd1;
        end
        4'd6:
        begin
          alu_sel = 5'd1;
          data_bus_sel = 2'd1;
          sram_write = 1'd0; sram_read =1'd0;
          alu_op1 = 2'd0; alu_op2 = 2'd0;
          regfile_write = 1'd1;
        end
        4'd7:
        begin
          alu_sel = 5'd4;
          data_bus_sel = 2'd1;
          sram_write = 1'd0; sram_read =1'd0;
          alu_op1 = 2'd0; alu_op2 = 2'd0;
          regfile_write = 1'd1;
        end
        4'd8:
        begin
          alu_sel = 5'd2;
          data_bus_sel = 2'd1;
          sram_write = 1'd0; sram_read =1'd0;
          alu_op1 = 2'd0; alu_op2 = 2'd2;
          regfile_write = 1'd1;
        end
        4'd9:
        begin
          alu_sel = 5'd5;
          data_bus_sel = 2'd1;
          sram_write = 1'd0; sram_read =1'd0;
          alu_op1 = 2'd0; alu_op2 = 2'd2;
          regfile_write = 1'd1;
        end
        4'd10:
        begin
          alu_sel = 5'd5;
          data_bus_sel = 2'd1;
          sram_write = 1'd0; sram_read =1'd0;
          alu_op1 = 2'd0; alu_op2 = 2'd2;
          regfile_write = 1'd0;
        end
        default : 
        begin
          alu_sel = 5'd0;
          data_bus_sel = 2'd1;
          sram_write = 1'd0; sram_read =1'd0;
          alu_op1 = 2'd0; alu_op2 = 2'd0;
          regfile_write = 1'd1;
        end
      endcase
    end
  else if ( logic_reg == 1'd1 )
    begin
      case(opcode)
        4'd0:
        begin
          alu_sel = 5'd10;
          data_bus_sel = 2'd1;
          sram_write = 1'd0; sram_read =1'd0;
          alu_op1 = 2'd0; alu_op2 = 2'd1;
          regfile_write = 1'd1;
        end
        4'd1:
        begin
          alu_sel = 5'd10;
          data_bus_sel = 2'd1;
          sram_write = 1'd0; sram_read =1'd1;
          alu_op1 = 2'd0; alu_op2 = 2'd2;
          regfile_write = 1'd0;
        end
        4'd2:
        begin
          alu_sel = 5'd8;
          data_bus_sel = 2'd1;
          sram_write = 1'd0; sram_read =1'd0;
          alu_op1 = 2'd0; alu_op2 = 2'd1;
          regfile_write = 1'd1;
        end
        4'd3:
        begin
          alu_sel = 5'd0;
          data_bus_sel = 2'd1;
          sram_write = 1'd0; sram_read =1'd0;
          alu_op1 = 2'd0; alu_op2 = 2'd2;
          regfile_write = 1'd1;
        end
        4'd4:
        begin
          alu_sel = 5'd11;
          data_bus_sel = 2'd1;
          sram_write = 1'd0; sram_read =1'd0;
          alu_op1 = 2'd0; alu_op2 = 2'd0;
          regfile_write = 1'd1;
        end
        4'd5:
        begin
          alu_sel = 5'd7;
          data_bus_sel = 2'd1;
          sram_write = 1'd0; sram_read =1'd0;
          alu_op1 = 2'd0; alu_op2 = 2'd0;
          regfile_write = 1'd1;
        end       
        default:
        begin
          alu_sel = 5'd0;
          data_bus_sel = 2'd1;
          sram_write = 1'd0; sram_read =1'd0;
          alu_op1 = 2'd0; alu_op2 = 2'd0;
          regfile_write = 1'd1;
        end
      endcase
    end
  else if (memory_reg == 1'd1)
    begin
       alu_op1 = 2'd1; alu_op2 = 2'd0;
       alu_sel = 5'd3;
       sram_write = decoded_data[7]; 
       sram_read =decoded_data[6];
       if (decoded_data[6]==1'd1)
        begin
          regfile_write = 1'd1;
          data_bus_sel = 2'd0;
        end
       else if (decoded_data[7]==1'd1)
         begin
           regfile_write = 1'd0;
           data_bus_sel = 2'd1;
         end
       else
         begin
           regfile_write = 1'd0;
           data_bus_sel = 2'd1;
         end
    end
  else if (branch_reg == 1'd1)
    begin
      alu_op1 = 2'd1; alu_op2 = 2'd0;
      alu_sel = 5'd0;
      sram_write = 1'd0; sram_read =1'd0;
      regfile_write = 1'd0;
      data_bus_sel = 2'd0;
    end
  else
    begin
       alu_op1 = 2'd0; alu_op2 = 2'd0;
       alu_sel = 5'd0;
       sram_write = 1'd0; sram_read =1'd0;
       regfile_write = 1'd0;
       data_bus_sel = 2'd1;
    end
end

endmodule

RISC wrapper connecting everything
module RISC(clk,rst);
    input clk,rst; 
    reg [15:0]gen_reg[15:0];
    reg [15:0]databus;
    wire [7:0]sram_rd_add;
    wire [7:0]sram_wr_add;
    wire [1:0]data_bus_sel;
    wire [3:0]reg_sel_on_addbus;
    wire [7:0]addbus_reg_data;
    wire  sram_rd , sram_wr;
    wire regfile_write,regfile_write_wrap;
    wire [15:0] sram_data;
    reg  [15:0]data_a;
    reg  [15:0]data_b;
    reg  cin;
    wire [15:0]result;
    wire [7:0]mem_add;
    wire [15:0]dec_data;
    wire [4:0] alu_sel ; 
    wire DI,sram_write_back_enable;
    wire [15:0]data_a_gen_reg,data_b_gen_reg;
    wire [3:0]OP1,OP2;
    reg [2:0]SC;
    wire T0,T1,T2,T3,T4;
    wire cout;
    reg zero_flag;
    wire [1:0]flags;
    wire arith_reg , logic_reg , branch_reg, memory_reg ;
    wire [1:0]alu_op1,alu_op2;
    
    
    always @ ( posedge clk )
    begin
        if ( regfile_write == 1'd1 ) 
        begin
            gen_reg[OP1] <= databus;
        end
    end
    
      



    controlunit u_controlunit (.T0(T0),.T4(T4),
                    .regfile_write(regfile_write_wrap),
                    .alu_op1(alu_op1),.alu_op2(alu_op2),
                    .sram_write(sram_write_wrap),
                    .sram_read(sram_read_wrap),
                    .arith_reg(arith_reg) , .logic_reg(logic_reg) , 
                    .branch_reg(branch_reg), .memory_reg(memory_reg),
                    .OP1(OP1),.OP2(OP2),.DI(DI),
                    .dec_data(dec_data),.alu_sel(alu_sel),
                    .data_bus_sel(data_bus_sel),
                    .clk(clk),.rst(rst),.flags(flags)
                    );
    mini_alu u_mini_alu(.a(data_a),.b(data_b),
                       .cin(cin),.result(result),.cout(cout));
                       
    sram u_sram(.datain(databus),.dataout(sram_data),
                .wr_add(sram_wr_add),.rd_add(sram_rd_add),.clk(clk),
                .enable(sram_write_back_enable),
                .read(sram_rd),.write(sram_wr));
                

// Sram Address controller and Address Bus
assign sram_write_back_enable = memory_reg & ( T2 | T4);
assign sram_rd = memory_reg &  sram_read_wrap  & T2 ;
assign sram_wr = memory_reg &  sram_write_wrap & T4 ;
assign regfile_write = regfile_write_wrap & T4 ;
assign mem_add = dec_data[7:0]; 
assign reg_sel_on_addbus = OP2;
assign addbus_reg_data = gen_reg[reg_sel_on_addbus];
assign sram_rd_add = DI?addbus_reg_data:mem_add;
assign sram_wr_add = DI?addbus_reg_data:mem_add;
assign data_a_gen_reg =  gen_reg[OP1];
assign data_b_gen_reg =  gen_reg[OP2];
    
always @ (result or sram_data  or dec_data  or data_bus_sel)
begin
        case(data_bus_sel)
            2'd0:databus = sram_data;
            2'd1:databus = result;
            2'd2:databus = 16'd0;
            2'd3:databus = dec_data;
        endcase
end
  

  always @ (alu_op1 or data_a_gen_reg or data_b_gen_reg or dec_data) 
  begin
    case(alu_op1)
      2'd0:begin
        data_a = data_a_gen_reg;
      end
      2'd1:begin
        data_a = data_b_gen_reg;
      end
      2'd2:begin
        data_a = dec_data;
      end
      2'd3:begin
        data_a = 16'd0;
      end
      default:begin
        data_a = 16'd0;
      end
    endcase
  end

  always @ (alu_op2 or data_a_gen_reg or data_b_gen_reg or dec_data ) 
  begin
    case(alu_op2)
      2'd0:begin
        data_b = data_a_gen_reg;
      end
      2'd1:begin
        data_b = data_b_gen_reg;
      end
      2'd2:begin
        data_b = dec_data;
      end
      2'd3:begin
        data_b = 16'd0;
      end
      default:begin
        data_b = 16'd0;
      end
    endcase
  end


always @ (posedge clk)
begin
  if ( rst == 1'd1 ) 
    begin
      cin <= 1'd0;
    end
    else
    begin
      if ( T3 == 1'd1 & (arith_reg == 1'd1 | logic_reg == 1'd1 ))
        begin
         cin <= cout ;
        end
      else
        begin
          cin <= cin ;
        end
    end
end
 
assign result_zero = (result == 16'd0);
assign flags = {cin,zero_flag};

always @ ( posedge clk )
begin
  if (rst == 1'd0 )
    begin
      zero_flag <= 1'd0;
    end
  else
   begin
     if ( T3 == 1'd1 & (arith_reg == 1'd1 | logic_reg == 1'd1 )) 
      begin
            zero_flag <= result_zero;
       end
     else
       begin
         zero_flag <= zero_flag;
       end
   end
end

assign T0 = (SC == 3'd0);
assign T1 = (SC == 3'd1);
assign T2 = (SC == 3'd2);
assign T3 = (SC == 3'd3);
assign T4 = (SC == 3'd4);

always @ ( posedge clk )
begin
  if (rst == 1'd1)
    begin
      SC <= 3'd0;
    end
  else
    begin
      if (T4 == 1'd1)
        begin
          SC <= 3'd0;
        end
      else
         begin
           SC <= SC + 3'd1 ;
         end
    end
end
endmodule
Test bench for testing our RISC processor
module RISC_test(clk,rst,decoded_data);
    output clk,rst;
    output [29:0]decoded_data;
    reg clk,rst;
    reg [29:0]decoded_data;
    reg [7:0] temp ;

    always 
    begin
        #5 clk = ~ clk ; 
    end

    initial 
    begin : COUNT
        clk = 1'd0;
        rst = 1'd1;
        // Load r1 with direct data
        decoded_data  = {7'd0,16'd1,2'd1,4'd1,1'd0};
        @ (posedge clk);
        #5 rst = 1'd0;
    end

    RISC u_RISC(clk,rst);
    
endmodule