2012年11月30日 星期五

Digital Course Demonstrations

源自於 http://elm.eeng.dcu.ie/~digital1/afdez/index.html

First Year Digital Course. Demonstrations:


 Binary Logic: Basic Boolean Operators (AND, OR, NOT).
 Boolean algebra: De Morgan's Laws. Further Boolean Operators (XOR, NAND, NOR). Minimization of logic functions using boolean algebra; using Karnaugh maps.
 Binary Arithmetic: Conversion between decimal and binary notations (Conversion from integer decimal to binary orfrom fraction decimal to binary, and from binary to decimal). Addition of binary numbers.
 Sequential Logic: Sequential logic elements including S-R flip-flops (RS Flip-Flop Using NOR Gates , RS Flip-Flop Using AND GatesClocked RS Flip-Flop ), D flip-flops(D Type Flip-Flop), and J-K flip-flops(JK Flip-Flop).
 Applications of flip-flops: including Data Registers and shift registers( Shift RegistersShift Registers With Parallel InputsRight-Left Shift RegisterShift Registers With Feed-Back). 
 
 
Created by Final Year Project Supervised by Derek Molloy
Ana Cristina Fernandez EE4. DCU
 
 
 
 
 

BCD ADDER/SUBSTRATOR


Boolean Algebra: Chapter 6


源自於 http://lizarum.com/assignments/boolean_algebra/chapter6.html
Circuits 2011-2012
SACC

Boolean Algebra: Chapter 6

// INTRODUCTION



BCD binary numbers represent Decimal digits 0 to 9. A 4-bit BCD code is used to represent the ten numbers 0 to 9. Since the 4-bit Code allows 16 possibilities, the first 10 4-bit combinations are considered to be valid BCD combinations. The latter six combinations are invalid and do not occur.



You can produce a one-bit sum and one bit carry using 2 boolean functions:
Sum=AB +AB
Carry=AB
Together these functions produce a half-adder, which adds two bits together, but cannot add in a carry from a previous operation.

A full-adder adds 3 1-bit inputs (2-bits and a carry from a previous addition) and produces two outputs (sum and the carry):
Sum=(A BCin) +(ACin)+(AB Cin)+(ABCin)
Cout=(AB)+ACin)+BCin)


// LAB



  1. Design a circuit to add 2 2-bit numbers using a 7483 4-bit adder. Use 2 switches on the designer to input 1 value and 2 other switches to input the other value.

    • The 7483 adds 2 4-bit values. What must be done with the unused inputs?
    • What should be done with the carry input?
    • How many outputs from the adder must be connected to the LEDs to see all the possible outputs?



  2. Design a circuit to display the decimal equivalent of a 4-bit BCD value. Use a 7447 BCD, and a seven-segment common anode display.


  3. Design a circuit to subtract values. Take the number you want to subtract, invert it, add 1 to it, then add this value to the number you want to subtract from.


  4. For sums between 10 and 18, you must subtract 10 and produce a carry. Subtract 10 from 10102 and add 2s complement >01102

    For sums >9 you need to add 2's complement of 1010 to the uncorrected result(S3,S2,S1,S0).

    Correction is also needed when a carry out (C3 is generated (16,17,18)

    A decoder is needed to detect when carry out (Cn to the next stage is needed.

    K-Map for Cn
    S'1S;0
    S'3S;200011110
    000132
    014576
    11
    1089

    Cn=C'3+S'3S'2+S'3S'1

    To implement a 4-bit BDC adder you need 2 4-bit full adders. One to add 2 4-bit BCD numbers and the other full adder to add the 2's complement of 1010 to the result if Cn=1

    You also need 2 AND gates and one OR gate to generate Cn
    adders.png

  5. BDCD Subtraction

    Design a 9's Complement Generator for a BCD Digit 9's complement
    The 9's complement of a decimal number is found by subtracting each digit in the number from 9
    Decimal Digit9's complement
    09
    18
    27
    ||
    90

    the 9's complement of 28=99-28=71
    the 9's complement of 562=999-562=437

    Subtraction of a smaller decimal number from a larger one can be done by adding the 9's complement of the smaller number to the larger number and then adding the carry to the result (end around carry). When subtracting a larger number from a smaller one there is no carry and the result in the 9's complement form is negative:
    nines.png
    86-99=-13

    Rules
    • Add 9's complement of B to A
    • If result>9, correct by adding 0110
    • If most significant carry is produced (i.e.=1), then the result is positive and the end around carry must be added
    • If the most significant carry is 0 (no carry) then the result is negative and you get the 9's complement of the result

    rules.png
    rules2.png

    nines_compl.png
    But, unfortunately subtractors are not widely available. Fortunately, you can generate the 9's complement b adding 1010 to the inverted number:
    BCD DigitDIGITDIGIT+1010
    000011111001
    000111101000
    001011010111
    001111000110
    010010110101
    010110100100
    011010010011
    011110000010
    100001110001
    100101100000

    Ignore the carry out

    generator.png


Source: Passafine, John and Michael Douglas, Digital Logic Design

2012年11月29日 星期四

9s complement basics


9s complement basics


源自於 http://6502.org/users/dieter/bcd2/bcd2_1.htm


First, we are starting with a concept
which you are already supposed to know...
from some "ALU design" articles, for instance.
A simple 4 Bit binary adder/subtractor:

Q=A+B:
c_in is a high_active carry,
the multiplexer routes B to the adder B' input,
it's simple.
Q=A-B
is less simple to understand.
Because we are using an adder,
we need to do something like Q=A+(-B).
In other words: we have to complement B
into a negative number.
-B is the 2s complement of B.
As we know from the school books:
in order to convert B into a negative number,
we first have to invert B into /B, then to add 1.
/B is the 1s complement of B.
The box labeled "1s complement" only contains
four 7404 type inverters.
For instance:
the 1s complement of binary 0000 (decimal 0)
is binary 1111 (decimal 15).
"But how to increment /B ?", you may ask.
The simplest way is to set the ALU carry input to 1.
So Q=A-B is done by this hardware as Q=A+/B +1
And because of that, c_in now is a low_active borrow
instead of a high_active carry.

"Yeah, every little kid knows this,
but why is that guy lamenting
about the boring basics again ?"

Answer:
To give you a better chance of understanding this:

A 4 bit BCD adder/subtractor.
The concept is very similar to the binary adder/subtractor,
only that we are using a 10s complement of B this time.
To be more exact: for Q=A-B, we do a 9s complement of B,
and c_in works as a low_active borrow.
Downside is, that we still are using a binary adder
inside our schematic, so we have to correct the adder
output if the result is greater than 9...
but we are talking about this later.

Now a look inside the box labeled "9s complement".

From the truth table above, four inverters won't do this time.
Here an example, of how the 9s complement was generated
inside the Wang 700 calculator:

For better readability of the schematic, I did draw an
AND OR combination gate generating B2'.
The Wang actually does this with NAND gates.
On the next page, I'll show a few more schematics
for generating a 9s complement.

[HOME] [UP][BACK] [1] [2] [3] [4] [5] [6] [7] [8] [NEXT]
(c) Dieter Mueller 2012

Digital Logic & Design

源自於
http://www.zeepedia.com/read.php?an_overview_number_systems_digital_logic_design&b=9&c=1

Table of Contents: 
  1. AN OVERVIEW & NUMBER SYSTEMS
  2. Binary to Decimal to Binary conversion, Binary Arithmetic, 1’s & 2’s complement
  3. Range of Numbers and Overflow, Floating-Point, Hexadecimal Numbers
  4. Octal Numbers, Octal to Binary Decimal to Octal Conversion
  5. LOGIC GATES: AND Gate, OR Gate, NOT Gate, NAND Gate
  6. AND OR NAND XOR XNOR Gate Implementation and Applications
  7. DC Supply Voltage, TTL Logic Levels, Noise Margin, Power Dissipation
  8. Boolean Addition, Multiplication, Commutative Law, Associative Law, Distributive Law, Demorgan’s Theorems
  9. Simplification of Boolean Expression, Standard POS form, Minterms and Maxterms
  10. KARNAUGH MAP, Mapping a non-standard SOP Expression
  11. Converting between POS and SOP using the K-map
  12. COMPARATOR: Quine-McCluskey Simplification Method
  13. ODD-PRIME NUMBER DETECTOR, Combinational Circuit Implementation
  14. IMPLEMENTATION OF AN ODD-PARITY GENERATOR CIRCUIT
  15. BCD ADDER: 2-digit BCD Adder, A 4-bit Adder Subtracter Unit
  16. 16-BIT ALU, MSI 4-bit Comparator, Decoders
  17. BCD to 7-Segment Decoder, Decimal-to-BCD Encoder
  18. 2-INPUT 4-BIT MULTIPLEXER, 8, 16-Input Multiplexer, Logic Function Generator
  19. Applications of Demultiplexer, PROM, PLA, PAL, GAL
  20. OLMC Combinational Mode, Tri-State Buffers, The GAL16V8, Introduction to ABEL
  21. OLMC for GAL16V8, Tri-state Buffer and OLMC output pin
  22. Implementation of Quad MUX, Latches and Flip-Flops
  23. APPLICATION OF S-R LATCH, Edge-Triggered D Flip-Flop, J-K Flip-flop
  24. Data Storage using D-flip-flop, Synchronizing Asynchronous inputs using D flip-flop
  25. Dual Positive-Edge triggered D flip-flop, J-K flip-flop, Master-Slave Flip-Flops
  26. THE 555 TIMER: Race Conditions, Asynchronous, Ripple Counters
  27. Down Counter with truncated sequence, 4-bit Synchronous Decade Counter
  28. Mod-n Synchronous Counter, Cascading Counters, Up-Down Counter
  29. Integrated Circuit Up Down Decade Counter Design and Applications
  30. DIGITAL CLOCK: Clocked Synchronous State Machines
  31. NEXT-STATE TABLE: Flip-flop Transition Table, Karnaugh Maps
  32. D FLIP-FLOP BASED IMPLEMENTATION
  33. Moore Machine State Diagram, Mealy Machine State Diagram, Karnaugh Maps
  34. SHIFT REGISTERS: Serial In/Shift Left,Right/Serial Out Operation
  35. APPLICATIONS OF SHIFT REGISTERS: Serial-to-Parallel Converter
  36. Elevator Control System: Elevator State Diagram, State Table, Input and Output Signals, Input Latches
  37. Traffic Signal Control System: Switching of Traffic Lights, Inputs and Outputs, State Machine
  38. Traffic Signal Control System: EQUATION DEFINITION
  39. Memory Organization, Capacity, Density, Signals and Basic Operations, Read, Write, Address, data Signals
  40. Memory Read, Write Cycle, Synchronous Burst SRAM, Dynamic RAM
  41. Burst, Distributed Refresh, Types of DRAMs, ROM Read-Only Memory, Mask ROM
  42. First In-First Out (FIFO) Memory
  43. LAST IN-FIRST OUT (LIFO) MEMORY
  44. THE LOGIC BLOCK: Analogue to Digital Conversion, Logic Element, Look-Up Table
  45. SUCCESSIVE –APPROXIMATION ANALOGUE TO DIGITAL CONVERTER

LAB10 BCD substrator (BCD減法器)

LAB10 BCD substrator (BCD減法器) 適用於DE2-70
a - b - bor_in  = {bor_out , diff_10out, diff_out}
0-0-0=0 , 9-0-0=9 , 0-9-1=-10

SW[17] 前一級借位  輸入
SW[7:4] 被減數  輸入
SW[3:0] 減數 輸入
HEX1-HEX0 差  輸出
LEDG[0] 借位  輸出







//------------------------------------
//4-bit BCD substrator
//Filename : BCD_substrator.v
//------------------------------------
module BCD_Substrator(SW, LEDR, LEDG , CLOCK_27 ,KEY ,HEX0 ,HEX1 ,HEX2,HEX3 );

input  [17:0] SW;   // toggle switches
input  [7:0] KEY;       // Push bottom
input  CLOCK_27;   //Clock 27MHz , 50Mhz

output [17:0] LEDR;   // red  LEDS   
output [8:0] LEDG;   // green LEDs
    
output [6:0] HEX0,HEX1,HEX2,HEX3; //7-segment display
    
  

//(Diff , Bor_out, Bor_in, A, B);
//output Diff [3:0] S; //Difference output
//output Bor_out;   //Borrow out
//input Bor_in;       //Borrow in
//input [3:0] A, B; //Input data  minuend /  subtrahend  A-B
// A-B-Bor_in = Diff , Bor_out
    wire Bor_in;       //Borrow  in
    wire [3:0] A,B; //Input data  minuend /  subtrahend  A-B
    reg  [3:0] Diff_out; //Difference output
    reg  [3:0] Diff_10out;
    wire Bor_out;     //Carry out
    

    wire [7:0] segout0;   //HEX 0
    wire [7:0] segout1;   //HEX 1
    
    assign  A=SW[7:4] ; //minuend A      
    assign  B=SW[3:0] ; //subtrahend  B
    assign  Bor_in=SW[17];  //Borrow in Bor_in
    
    assign  LEDR[7:0]=SW[7:0];
    assign  LEDR[17]=SW[17];
    
    reg [3:0] A_tmp,B_tmp1;
    wire [3:0] S_tmp,B_tmp,Diff_tmp;
wire C4;
reg  [3:0] A_mod,B_mod;
//debug 
//wire [3:0] B_tmp2;
    always @ ( A or B or Bor_in )
begin
if (A<10)
A_tmp = A;   //若是>9 則為9
else
A_tmp =4'b1001;
  
if (B<10)
B_tmp1 = B;  //若是>9 則為9
else
B_tmp1 =4'b1001;
end
_9s_complement(.Xin(B_tmp1), .Xout(B_tmp));

BCD_4bit_FA U1( .S1(S_tmp),
.Cout1(C4),
.Cin1(1'b0), 
.A1(A_tmp), 
.B1(B_tmp));
//debug
//assign LEDR[15:12]=S_tmp;
//assign LEDR[16]=C4;
           
    
    always @ ( A_tmp or B_tmp or C4 or S_tmp or Bor_in)
begin
        case (C4)
   0 : begin 
B_mod = ~S_tmp; //Modified code
A_mod = 4'b1010;
end
1: begin
B_mod = S_tmp;
A_mod = 4'b0000;
end
   endcase
end

adder4 U2 ( .S(Diff_tmp),
           .Cout(),
           .A(A_mod), 
           .B(B_mod),
           .Cin(C4));
 
always @ ( A_mod or B_mod or Diff_tmp or Bor_in)
begin
      Diff_10out=4'b0;  //前一級借位的處理
      case (Bor_in)     //Process Borrow in 
        0:
        Diff_out=Diff_tmp;     //前一級借位=0
        
        1: begin   // Diff_out <0  //前一級借位=1
           if (Bor_out)
                Diff_out= Diff_tmp + 4'b1;     //結果<0  ,  負號
           else
                Diff_out= Diff_tmp + 4'b1111;  //結果>0  , 正號
        
           if (Diff_out==4'b1111)       // 結果=0    0-1=0xf  ,  變成-1
               Diff_out=4'b1; 
               
           if (Diff_out==4'b1010)       // A=1010 ==>0001  0000  變成- 10  
               begin
Diff_10out=4'b1; 
Diff_out=4'b0;
             end
           else
               Diff_10out=4'b0;         
           end            
default:
Diff_out=Diff_tmp;
      endcase   
      
     end
     
     /*  
     always @ ( C4)
begin 
      if  (~C4) 
          segout1[6:0]=7'b011_1111; //minus 
      else
          segout1[6:0]=7'b111_1111;
     end
    
      assign HEX1=segout1[6:0];
      
      */
       
 assign Bor_out = ~C4;    
 assign LEDG[0]=Bor_out;
    


_7seg UUT0(.hex((Diff_out)),
               .seg(segout0));
    
    assign HEX0=segout0[6:0];
    
    _7seg UUT1(.hex({3'b0,Diff_10out}),
               .seg(segout1));
    
    assign HEX1=segout1[6:0];
    
    assign HEX2=7'b111_1111;
    assign HEX3=7'b111_1111;

    
endmodule




//----------------------
//4-bit unsigned adder
//Filename : adder4.v
//----------------------                                                                                                                                                                                                                   
module adder4(S, Cout, A, B, Cin);
output [3:0] S;   //4-bit sum
output Cout;    //Carry out
input [3:0] A, B; //Inputs
input Cin;    //Carry in

//Assign the sum of (A+B+Cin) to Cout and Sum
assign {Cout, S} = A + B + Cin;

endmodule



//----------------------
//
//Filename : nine's complement 
//----------------------                                                                                                                                                                                                                   
module _9s_complement(Xin, Xout);
output [3:0] Xout;   //4-bit 9's complement 
input [3:0] Xin; //Inputs
    //Assign the 9's complement Xout = Xin + 1010 ;
assign Xout  = ~Xin + 4'b1010 ;
    /*adder4(.S(Xout), 
  .Cout(), 
  .A(~Xin), 
  .B(4'b1010), 
  .Cin(1'b0)
  ); */
endmodule





//-----------------------------------------
//Common-cathod seven segment display
//using case.....endcase statement
//Filename : sevenseg_case.v
//----------------------------------------- 
module _7seg(hex , seg);
    input  [3:0] hex;
    output [7:0] seg;
    reg    [7:0] seg;
    
        

 // segment encoding
 //      0
 //     ---  
 //  5 |   | 1
 //     ---   <- 6
 //  4 |   | 2
 //     ---
 //      3
 always @(hex)
 begin
  case (hex)
       // Dot point is always disable
       4'b0001 : seg = 8'b11111001;   //1 = F9H
       4'b0010 : seg = 8'b10100100;   //2 = A4H
       4'b0011 : seg = 8'b10110000;   //3 = B0H
       4'b0100 : seg = 8'b10011001;   //4 = 99H
       4'b0101 : seg = 8'b10010010;   //5 = 92H
       4'b0110 : seg = 8'b10000010;   //6 = 82H
       4'b0111 : seg = 8'b11111000;   //7 = F8H
       4'b1000 : seg = 8'b10000000;   //8 = 80H
       4'b1001 : seg = 8'b10010000;   //9 = 90H
       4'b1010 : seg = 8'b10001000;   //A = 88H
       4'b1011 : seg = 8'b10000011;   //b = 83H
       4'b1100 : seg = 8'b11000110;   //C = C6H
       4'b1101 : seg = 8'b10100001;   //d = A1H
       4'b1110 : seg = 8'b10000110;   //E = 86H
       4'b1111 : seg = 8'b10001110;   //F = 8EH
       default : seg = 8'b11000000;   //0 = C0H
     endcase
   end
   
endmodule




 module BCD_4bit_FA ( S1, Cout1, Cin1, A1, B1);
output [3:0] S1; //Sumation output
output Cout1;    //Carry out
input Cin1;      //Carry in
input [3:0] A1, B1;//Input data
wire [3:0] A_tmp11,B_tmp11,S_tmp11;
wire C41;
reg [3:0] B_mod11;
reg F1;

//4-bit binary adder
adder4 BINADD(
            .S(S_tmp11),
            .Cout(C41),
            .Cin(Cin1),
            .A(A1),
            .B(B1)
           );

//Modify binary code with '0110'
adder4 MODADD(
            .S(S1),
            .Cout(),
            .Cin(1'b0),
            .A(S_tmp11),
            .B(B_mod11)
           );

always @ (Cin1 or A1 or B1 or C41 or S_tmp11)
begin
//F=C4+S3(S2+S1)
F1 = (C41 | (S_tmp11[3] & (S_tmp11[2] | S_tmp11[1])));
B_mod11 = {1'b0, F1, F1, 1'b0}; //Modified code
end
 assign Cout1 = F1;

 endmodule





2012年11月26日 星期一

Task & Function

Task & Function 


// an example illustrating how to count the zeros in a byte.
module zero_count_task (data, out); 
   input [7:0] data;
   output reg [3:0] out; // output declared as register
   
   always @(data)
   count_0s_in_byte(data, out);
   // task declaration from here.


    task count_0s_in_byte(input [7:0] data, 
                                          output reg [3:0] count);
    integer i;
       begin // task body
          count = 0; 
          for (i = 0; i <= 7; i = i + 1)
            // The following statement can be replaced by
           // : count = count + ~data[i]. Why?
           if (data[i] == 0) count= count + 1;
       end 
   endtask

endmodule




// an example illustrating how to count the zeros in a byte.
module zero_count_function (data, out); 
    input [7:0] data;
   output reg [3:0] out; // output declared as register

   always @(data)

   out = count_0s_in_byte(data);


   // function declaration from here.
   function [3:0] count_0s_in_byte(input [7:0] data);
       integer i; 
       begin 
           count_0s_in_byte = 0;
           for (i = 0; i <= 7; i = i + 1)

            // the following statement can be replaced by: 
            // count_0s_in_byte = count_0s_in_byte + ~data[i]. Why?

         if (data[i] == 0) 
                count_0s_in_byte = count_0s_in_byte + 1;
     end

     endfunction


endmodule




Case 與if..else 合成後的電路結構

Case 與if..else 合成後的電路結構
能用case盡量用case 



Blocking & non-blocking

Blocking & non-blocking 

4 Logic value 0/1/X/Z

4 Logic value 0/1/X/Z




2012年11月22日 星期四

LAB09 PS2 Scan Code 送至 LCD1602 適用於DE2-70

LAB09 PS2 Keyboard Scan Code 送至 LCD1602 適用於DE2-70

修改自 DE2 johnloomis-org









module lcdlab3(
  
  input CLOCK_50, // 50 MHz clock
  input [3:0] KEY,      // Pushbutton[3:0]
  input [17:0] SW, // Toggle Switch[17:0]
  
  output [8:0] LEDG,  // LED Green
  output [17:0] LEDR,  // LED Red
  inout [35:0] GPIO_0,GPIO_1, // GPIO Connections
  //LCD Module 16X2
  output LCD_ON, // LCD Power ON/OFF
  output LCD_BLON, // LCD Back Light ON/OFF
  output LCD_RW, // LCD Read/Write Select, 0 = Write, 1 = Read
  output LCD_EN, // LCD Enable
  output LCD_RS, // LCD Command/Data Select, 0 = Command, 1 = Data
  inout [7:0] LCD_DATA, // LCD Data bus 8 bits
  
  //  PS2 data and clock lines
  input PS2_DAT,
  input PS2_CLK
    
);

// All inout port turn to tri-state
assign GPIO_0 = 36'hzzzzzzzzz;
assign GPIO_1 = 36'hzzzzzzzzz;

wire RST;
assign RST = KEY[0];

// reset delay gives some time for peripherals to initialize
wire DLY_RST;
Reset_Delay r0( .iCLK(CLOCK_50),.oRESET(DLY_RST) );

// Send switches to red leds 
assign LEDR = SW;

// turn LCD ON
assign LCD_ON = 1'b1;
assign LCD_BLON = 1'b1;

//wire [3:0] hex1, hex0;
//assign hex1 = SW[7:4];
//assign hex0 = SW[3:0];

wire reset = 1'b0;
wire [7:0] scan_code;
wire read, scan_ready;


oneshot pulser(
   .pulse_out(read),
   .trigger_in(scan_ready),
   .clk(CLOCK_50)
);

keyboard kbd(
  .keyboard_clk(PS2_CLK),
  .keyboard_data(PS2_DAT),
  .clock50(CLOCK_50),
  .reset(reset),
  .read(read),
  .scan_ready(scan_ready),
  .scan_code(scan_code)
);


LCD_Display u1(
// Host Side
   .iCLK_50MHZ(CLOCK_50),
   .iRST_N(DLY_RST),
   .hex0(scan_code[3:0]),   //Display Scan_Code
   .hex1(scan_code[7:4]),
// LCD Side
   .DATA_BUS(LCD_DATA),
   .LCD_RW(LCD_RW),
   .LCD_E(LCD_EN),
   .LCD_RS(LCD_RS)
);

endmodule





module oneshot(output reg pulse_out, input trigger_in, input clk);
reg delay;

always @ (posedge clk)
begin
if (trigger_in && !delay) pulse_out <= 1'b1;
else pulse_out <= 1'b0;
delay <= trigger_in;
end 
endmodule





module Reset_Delay(iCLK,oRESET);
input iCLK;
output reg oRESET;
reg [19:0] Cont;

always@(posedge iCLK)
begin
if(Cont!=20'hFFFFF)
begin
Cont <= Cont+1'b1;
oRESET <= 1'b0;
end
else
oRESET <= 1'b1;
end

endmodule




module keyboard(keyboard_clk, keyboard_data, clock50, reset, read, scan_ready, scan_code);
input keyboard_clk;
input keyboard_data;
input clock50; // 50 Mhz system clock
input reset;
input read;
output scan_ready;
output [7:0] scan_code;
reg ready_set;
reg [7:0] scan_code;
reg scan_ready;
reg read_char;
reg clock; // 25 Mhz internal clock

reg [3:0] incnt;
reg [8:0] shiftin;

reg [7:0] filter;
reg keyboard_clk_filtered;

// scan_ready is set to 1 when scan_code is available.
// user should set read to 1 and then to 0 to clear scan_ready

always @ (posedge ready_set or posedge read)
if (read == 1) scan_ready <= 0;
else scan_ready <= 1;

// divide-by-two 50MHz to 25MHz
always @(posedge clock50)
clock <= ~clock;



// This process filters the raw clock signal coming from the keyboard 
// using an eight-bit shift register and two AND gates

always @(posedge clock)
begin
   filter <= {keyboard_clk, filter[7:1]};
   if (filter==8'b1111_1111) keyboard_clk_filtered <= 1;
   else if (filter==8'b0000_0000) keyboard_clk_filtered <= 0;
end


// This process reads in serial data coming from the terminal

always @(posedge keyboard_clk_filtered)
begin
   if (reset==1)
   begin
      incnt <= 4'b0000;
      read_char <= 0;
   end
   else if (keyboard_data==0 && read_char==0)
   begin
read_char <= 1;
ready_set <= 0;
   end
   else
   begin
  // shift in next 8 data bits to assemble a scan code
  if (read_char == 1)
    begin
      if (incnt < 9) 
      begin
incnt <= incnt + 1'b1;
shiftin = { keyboard_data, shiftin[8:1]};
ready_set <= 0;
end
else
begin
incnt <= 0;
scan_code <= shiftin[7:0];
read_char <= 0;
ready_set <= 1;
end
end
end
end

endmodule




/*
ENTITY LCD_Display IS
-- Enter number of live Hex hardware data values to display
-- (do not count ASCII character constants)
GENERIC(Num_Hex_Digits: Integer:= 2); 
-----------------------------------------------------------------------
-- LCD Displays 16 Characters on 2 lines
------------------------------------------------------------------- 
--                        ASCII HEX TABLE
--  Hex Low Hex Digit
-- Value  0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
------\----------------------------------------------------------------
--H  2 |  SP  !   "   #   $   %   &   '   (   )   *   +   ,   -   .   /
--i  3 |  0   1   2   3   4   5   6   7   8   9   :   ;   <   =   >   ?
--g  4 |  @   A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
--h  5 |  P   Q   R   S   T   U   V   W   X   Y   Z   [   \   ]   ^   _
--   6 |  `   a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
--   7 |  p   q   r   s   t   u   v   w   x   y   z   {   |   }   ~ DEL
-----------------------------------------------------------------------

*/

module LCD_Display(iCLK_50MHZ, iRST_N, hex1, hex0, 
LCD_RS,LCD_E,LCD_RW,DATA_BUS);
input iCLK_50MHZ, iRST_N;
input [3:0] hex1, hex0;
output LCD_RS, LCD_E, LCD_RW;
inout [7:0] DATA_BUS;

parameter
HOLD = 4'h0,
FUNC_SET = 4'h1,
DISPLAY_ON = 4'h2,
MODE_SET = 4'h3,
Print_String = 4'h4,
LINE2 = 4'h5,
RETURN_HOME = 4'h6,
DROP_LCD_E = 4'h7,
RESET1 = 4'h8,
RESET2 = 4'h9,
RESET3 = 4'ha,
DISPLAY_OFF = 4'hb,
DISPLAY_CLEAR = 4'hc;

reg [3:0] state, next_command;
// Enter new ASCII hex data above for LCD Display
reg [7:0] DATA_BUS_VALUE;
wire [7:0] Next_Char;
reg [19:0] CLK_COUNT_400HZ;
reg [4:0] CHAR_COUNT;
reg CLK_400HZ, LCD_RW_INT, LCD_E, LCD_RS;

// BIDIRECTIONAL TRI STATE LCD DATA BUS
assign DATA_BUS = (LCD_RW_INT? 8'bZZZZZZZZ: DATA_BUS_VALUE);

LCD_display_string u1(
.index(CHAR_COUNT),
.out(Next_Char),
.hex1(hex1),
.hex0(hex0));

assign LCD_RW = LCD_RW_INT;

always @(posedge iCLK_50MHZ or negedge iRST_N)
if (!iRST_N)
begin
  CLK_COUNT_400HZ <= 20'h00000;
  CLK_400HZ <= 1'b0;
end
else if (CLK_COUNT_400HZ < 20'h0F424)
begin
  CLK_COUNT_400HZ <= CLK_COUNT_400HZ + 1'b1;
end
else
begin
 CLK_COUNT_400HZ <= 20'h00000;
 CLK_400HZ <= ~CLK_400HZ;
end
// State Machine to send commands and data to LCD DISPLAY

always @(posedge CLK_400HZ or negedge iRST_N)
if (!iRST_N)
begin
state <= RESET1;
end
else
case (state)
RESET1:
// Set Function to 8-bit transfer and 2 line display with 5x8 Font size
// see Hitachi HD44780 family data sheet for LCD command and timing details
begin
 LCD_E <= 1'b1;
 LCD_RS <= 1'b0;
 LCD_RW_INT <= 1'b0;
 DATA_BUS_VALUE <= 8'h38;
 state <= DROP_LCD_E;
 next_command <= RESET2;
 CHAR_COUNT <= 5'b00000;
end
RESET2:
begin
 LCD_E <= 1'b1;
 LCD_RS <= 1'b0;
 LCD_RW_INT <= 1'b0;
 DATA_BUS_VALUE <= 8'h38;
 state <= DROP_LCD_E;
 next_command <= RESET3;
end
RESET3:
begin
 LCD_E <= 1'b1;
 LCD_RS <= 1'b0;
 LCD_RW_INT <= 1'b0;
 DATA_BUS_VALUE <= 8'h38;
 state <= DROP_LCD_E;
 next_command <= FUNC_SET;
end
// EXTRA STATES ABOVE ARE NEEDED FOR RELIABLE PUSHBUTTON RESET OF LCD

FUNC_SET:
begin
 LCD_E <= 1'b1;
 LCD_RS <= 1'b0;
 LCD_RW_INT <= 1'b0;
 DATA_BUS_VALUE <= 8'h38;
 state <= DROP_LCD_E;
 next_command <= DISPLAY_OFF;
end

// Turn off Display and Turn off cursor
DISPLAY_OFF:
begin
 LCD_E <= 1'b1;
 LCD_RS <= 1'b0;
 LCD_RW_INT <= 1'b0;
 DATA_BUS_VALUE <= 8'h08;
 state <= DROP_LCD_E;
 next_command <= DISPLAY_CLEAR;
end

// Clear Display and Turn off cursor
DISPLAY_CLEAR:
begin
 LCD_E <= 1'b1;
 LCD_RS <= 1'b0;
 LCD_RW_INT <= 1'b0;
 DATA_BUS_VALUE <= 8'h01;
 state <= DROP_LCD_E;
 next_command <= DISPLAY_ON;
end

// Turn on Display and Turn off cursor
DISPLAY_ON:
begin
 LCD_E <= 1'b1;
 LCD_RS <= 1'b0;
 LCD_RW_INT <= 1'b0;
 DATA_BUS_VALUE <= 8'h0C;
 state <= DROP_LCD_E;
 next_command <= MODE_SET;
end

// Set write mode to auto increment address and move cursor to the right
MODE_SET:
begin
 LCD_E <= 1'b1;
 LCD_RS <= 1'b0;
 LCD_RW_INT <= 1'b0;
 DATA_BUS_VALUE <= 8'h06;
 state <= DROP_LCD_E;
 next_command <= Print_String;
end

// Write ASCII hex character in first LCD character location
Print_String:
begin
 state <= DROP_LCD_E;
 LCD_E <= 1'b1;
 LCD_RS <= 1'b1;
 LCD_RW_INT <= 1'b0;
// ASCII character to output
 if (Next_Char[7:4] != 4'h0)
DATA_BUS_VALUE <= Next_Char;
// Convert 4-bit value to an ASCII hex digit
 else if (Next_Char[3:0] >9)
// ASCII A...F
DATA_BUS_VALUE <= {4'h4,Next_Char[3:0]-4'h9};
 else
// ASCII 0...9
DATA_BUS_VALUE <= {4'h3,Next_Char[3:0]};
// Loop to send out 32 characters to LCD Display  (16 by 2 lines)
 if ((CHAR_COUNT < 31) && (Next_Char != 8'hFE))
    CHAR_COUNT <= CHAR_COUNT + 1'b1;
 else
    CHAR_COUNT <= 5'b00000; 
// Jump to second line?
 if (CHAR_COUNT == 15)
   next_command <= LINE2;
// Return to first line?
 else if ((CHAR_COUNT == 31) || (Next_Char == 8'hFE))
   next_command <= RETURN_HOME;
 else
   next_command <= Print_String;
end

// Set write address to line 2 character 1
LINE2:
begin
 LCD_E <= 1'b1;
 LCD_RS <= 1'b0;
 LCD_RW_INT <= 1'b0;
 DATA_BUS_VALUE <= 8'hC0;
 state <= DROP_LCD_E;
 next_command <= Print_String;
end

// Return write address to first character postion on line 1
RETURN_HOME:
begin
 LCD_E <= 1'b1;
 LCD_RS <= 1'b0;
 LCD_RW_INT <= 1'b0;
 DATA_BUS_VALUE <= 8'h80;
 state <= DROP_LCD_E;
 next_command <= Print_String;
end

// The next three states occur at the end of each command or data transfer to the LCD
// Drop LCD E line - falling edge loads inst/data to LCD controller
DROP_LCD_E:
begin
 LCD_E <= 1'b0;
 state <= HOLD;
end
// Hold LCD inst/data valid after falling edge of E line
HOLD:
begin
 state <= next_command;
end
endcase
endmodule

module LCD_display_string(index,out,hex0,hex1);
input [4:0] index;
input [3:0] hex0,hex1;
output [7:0] out;
reg [7:0] out;
// ASCII hex values for LCD Display
// Enter Live Hex Data Values from hardware here
// LCD DISPLAYS THE FOLLOWING:
//----------------------------
//| Count=XX                  |
//| DE2                       |
//----------------------------
// Line 1
   always 
     case (index)
5'h00: out <= 8'h50; //P
5'h01: out <= 8'h53; //S
5'h02: out <= 8'h32; //2
5'h03: out <= 8'h20; //
5'h04: out <= 8'h53; //S
5'h05: out <= 8'h63; //c
5'h06: out <= 8'h61; //a
5'h07: out <= 8'h6e; //n
5'h08: out <= 8'h43; //C
5'h09: out <= 8'h6f; //o
5'h0a: out <= 8'h64; //d
5'h0b: out <= 8'h65; //e
5'h0c: out <= 8'h3D; //=
5'h0d: out <= {4'h0,hex1};
5'h0e: out <= {4'h0,hex0};
// Line 2
5'h10: out <= 8'h44; //D
5'h11: out <= 8'h45; //E
5'h12: out <= 8'h32; //2
5'h13: out <= 8'h5f; // 
5'h14: out <= 8'h37; //7
5'h15: out <= 8'h30; //0
5'h16: out <= 8'h20; //
5'h17: out <= 8'h50; //P
5'h18: out <= 8'h53; //S
5'h19: out <= 8'h32; //2
5'h1a: out <= 8'h2b; //+
5'h1b: out <= 8'h4c; //L
5'h1c: out <= 8'h43; //C
5'h1d: out <= 8'h44; //D

default: out <= 8'h20;
     endcase
endmodule








源自於
Keyboard Scan Codes: Set 2
*All values are in hexadecimal
101-, 102-, and 104-key keyboards:

KEY
MAKE
BREAK
-----
KEY
MAKE
BREAK
-----
KEY
MAKE
BREAK
A
1C
F0,1C
 
9
46
F0,46
 
[
54
FO,54
B
32
F0,32
 
`
0E
F0,0E
 
INSERT
E0,70
E0,F0,70
C
21
F0,21
 
-
4E
F0,4E
 
HOME
E0,6C
E0,F0,6C
D
23
F0,23
 
=
55
FO,55
 
PG UP
E0,7D
E0,F0,7D
E
24
F0,24
 
\
5D
F0,5D
 
DELETE
E0,71
E0,F0,71
F
2B
F0,2B
 
BKSP
66
F0,66
 
END
E0,69
E0,F0,69
G
34
F0,34
 
SPACE
29
F0,29
 
PG DN
E0,7A
E0,F0,7A
H
33
F0,33
 
TAB
0D
F0,0D
 
U ARROW
E0,75
E0,F0,75
I
43
F0,43
 
CAPS
58
F0,58
 
L ARROW
E0,6B
E0,F0,6B
J
3B
F0,3B
 
L SHFT
12
FO,12
 
D ARROW
E0,72
E0,F0,72
K
42
F0,42
 
L CTRL
14
FO,14
 
R ARROW
E0,74
E0,F0,74
L
4B
F0,4B
 
L GUI
E0,1F
E0,F0,1F
 
NUM
77
F0,77
M
3A
F0,3A
 
L ALT
11
F0,11
 
KP /
E0,4A
E0,F0,4A
N
31
F0,31
 
R SHFT
59
F0,59
 
KP *
7C
F0,7C
O
44
F0,44
 
R CTRL
E0,14
E0,F0,14
 
KP -
7B
F0,7B
P
4D
F0,4D
 
R GUI
E0,27
E0,F0,27
 
KP +
79
F0,79
Q
15
F0,15
 
R ALT
E0,11
E0,F0,11
 
KP EN
E0,5A
E0,F0,5A
R
2D
F0,2D
 
APPS
E0,2F
E0,F0,2F
 
KP .
71
F0,71
S
1B
F0,1B
 
ENTER
5A
F0,5A
 
KP 0
70
F0,70
T
2C
F0,2C
 
ESC
76
F0,76
 
KP 1
69
F0,69
U
3C
F0,3C
 
F1
05
F0,05
 
KP 2
72
F0,72
V
2A
F0,2A
 
F2
06
F0,06
 
KP 3
7A
F0,7A
W
1D
F0,1D
 
F3
04
F0,04
 
KP 4
6B
F0,6B
X
22
F0,22
 
F4
0C
F0,0C
 
KP 5
73
F0,73
Y
35
F0,35
 
F5
03
F0,03
 
KP 6
74
F0,74
Z
1A
F0,1A
 
F6
0B
F0,0B
 
KP 7
6C
F0,6C
0
45
F0,45
 
F7
83
F0,83
 
KP 8
75
F0,75
1
16
F0,16
 
F8
0A
F0,0A
 
KP 9
7D
F0,7D
2
1E
F0,1E
 
F9
01
F0,01
 
]
5B
F0,5B
3
26
F0,26
 
F10
09
F0,09
 
;
4C
F0,4C
4
25
F0,25
 
F11
78
F0,78
 
'
52
F0,52
5
2E
F0,2E
 
F12
07
F0,07
 
,
41
F0,41
6
36
F0,36
 
PRNT
SCRN
E0,12,
E0,7C 
E0,F0,
7C,E0,
F0,12 
 
.
49
F0,49
7
3D
F0,3D
 
SCROLL
7E
F0,7E
 
/
4A
F0,4A
8
3E
F0,3E
 
PAUSE
E1,14,77,
E1,F0,14,
F0,77
-NONE-

 
 

2024_09 作業3 以Node-Red 為主

 2024_09 作業3  (以Node-Red 為主  Arduino 可能需要配合修改 ) Arduino 可能需要修改的部分 1)mqtt broker  2) 主題Topic (發行 接收) 3) WIFI ssid , password const char br...