목요일, 12월 10, 2015

찻잔 스케치..... (완성?)

찻잔 스케치.....

본가에 있던 찻잔인데 꽃그림이 더 인쇄되어 있었음. 초벌 그릴때 귀찮아져 한송이만 그렸고 나중에 마져 그리다보니 나머지 꽃들이 없네요.


포트메리온 보태닉 가든 커피잔인데 비슷한가요? 이 잔이 약간 중후한 맛이 나는데 좀 홀쭉하게 그려졌네요.


앞서 그린 찻잔이 아무래도 홀쭉해 보여서 수정 했습니다. 그런데 이번에는 두리뭉실 한게  엽차잔 같아요.


그래서 아랫 부분을 좀더 깍아 봤습니다. 포트메리온 찻잔 디자인이 그냥 나온게 아닌것 같아요. 아무래도 좀 서운한 감이 있군요. 역시 디자인은 이름값 하나 봅니다.



아무래도 찻잔에 프린트됀 꽃그림이 없어서 너무 허전 했습니다. 그래서 마져 그렸네요. 찻잔 크기에 비해 꽃이 작게 그려졌군요.


금요일, 12월 04, 2015

DCT(Discrete Cosine Transform) in SystemVerilog and SystemC Testbench

DCT(Discrete Cosine Transform) in SystemVerilog and SystemC Testbench

Actually DCT is multiplication of 2-D Constant matrix to vector, or input stream. It could be implemented as pipelined parallelism approach. Let's see parallelism,


As the input X[i] is streamed and shifted, constants, noted as W[i][j] have also shifted index of j. So, let's find a rule for index j.

Use one counter as address generator or simply, re-aligning starting address as for pipelining of X. Later method is prefered, because of keeping easy-reading constant table in external file, included into ROM table implementation.


The design could be divided into repetitive element, i.e. Processing Element and all elements are behave like a Systolic Array of parallelism. Each PE is made of input X and W latch, and MAC(Multiplier-Accumulator). Length of Pipelined PE can be varied. For this purpose, it is parameterized design.



Detailed internal architecture of PE and IO timing is as follows. There are three-latency for the pipeline; two for PE and one for final streamed-out purpose.



Simulation result.

And Testbench where SystemC model is used; Generation of input stimulus, X and checking for the result between C-model and SystemVerilog Model.


Codes:

C-model of DCT, simply nested loop.

-----------------
//
// File: dct.h
//
#define DW 16

typedef short dct_data_t;

#define DCT_SIZE 8    /* defines the input matrix as 8x8 */
#define CONST_BITS  13
#define DESCALE(x,n)  (((x) + (1 << ((n)-1))) >> n)

void dct_1d(dct_data_t src[DCT_SIZE], dct_data_t dst[DCT_SIZE]);
-----------------
//
// File: dct.cpp
//

#include "dct.h"

void dct_1d(dct_data_t src[DCT_SIZE], dct_data_t dst[DCT_SIZE])
{
   unsigned int k, n;
   int tmp;
   const dct_data_t dct_coeff_table[DCT_SIZE][DCT_SIZE] = {
  8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192,
 11363,  9633,  6436,  2260, -2260, -6436, -9632,-11362,
 10703,  4433, -4433,-10703,-10703, -4433,  4433, 10703,
  9633, -2260,-11362, -6436,  6436, 11363,  2260, -9632,
  8192, -8192, -8192,  8192,  8192, -8191, -8191,  8192,
  6436,-11362,  2260,  9633, -9632, -2260, 11363, -6436,
  4433,-10703, 10703, -4433, -4433, 10703,-10703,  4433,
  2260, -6436,  9633,-11362, 11363, -9632,  6436, -2260
   };

   for (k = 0; k < DCT_SIZE; k++) {
      for(n = 0, tmp = 0; n < DCT_SIZE; n++) {
         int coeff = (int)dct_coeff_table[k][n];
         tmp += src[n] * coeff;
      }
      dst[k] = DESCALE(tmp, CONST_BITS);
   }
}
------------------------------------------


SystemVerilog Model

------------------------------------------
//
// Project: N-Point DCT
// File   : dct_defs.sv
// Author : Kook, goodkook@gmail.com
//

package dct_defs;
  parameter WIDTH_X = 16;
  parameter WIDTH_Y = 16;
  parameter WIDTH_W = 16;
  parameter POINT_N = 8;
  parameter CONST_BITS = 13;
 
`define CLOG2(x)             \
          (x <=    2) ?  1 : \
          (x <=    4) ?  2 : \
          (x <=    8) ?  3 : \
          (x <=   16) ?  4 : \
          (x <=   32) ?  5 : \
          (x <=   64) ?  6 : \
          (x <=  128) ?  7 : \
          (x <=  256) ?  8 : \
          (x <=  512) ?  9 : \
          (x <= 1024) ? 10 : \
          -1
 
  parameter DEPTH_W = `CLOG2(POINT_N); //$clog2(POINT_N);
endpackage


---------------------------------------------------

//
// Project: N-Point DCT
// File   : dct_W_ROM.sv
// Author : Kook, goodkook@gmail.com
//
////////////////////////////////////////////////////////////////////////////////
//
//       Coeff. Constant store in 2-D ROM
//       --------------------------------
//              +---------+---------+-      -+------------+
// ROM_W[  0]-->|W[  0][0]|W[  0][1]|  ....  |W[   0][N-1]|
//              +---------+---------+-      -+------------+
// ROM_W[  1]-->|W[  1][0]|W[  1][1]|  ....  |W[   1][N-1]|
//              +---------+---------+-      -+------------+
//              | .....ROM data from external file.....   |  
//              +---------+---------+-      -+------------+
// ROM_W[N-1]-->|W[N-1][0]|W[N-1][1]|........|[W[N-1][N-1]|
//              +---------+---------+-      -+------------+
// 
//       ROM(Coeff. Table) Address generator
//       -----------------------------------
//                                           +--------------+
//                              +-[X-0]----->|Addr.W[0][x]  -->init_ACC[0]
//        +--------------+      |            +--------------+
//        |N-bits counter|      +-[X-1]----->|Addr.W[1][x]  -->init_ACC[1]
// Req_X<--      for     --[X]->|            +--------------+
//        | Wnx ROM Addr |      |               ........
//        +--------------+      |            +--------------+
//                              +-[X-(N-1)]->|Addr.W[N-1][x]->init_ACC[N-1]
//                                           +--------------+
// 
//                            * "init_ACC", when Address for W[N][x]=0
//                            * "Req_X", when counter X=0
// 
//       ROM Data out sequence, when N=4
//       -------------------------------
//            W[0][x]           W[1][x]           W[2][x]           W[3][x]
//           +-------+         +-------+         +-------+         +-------+
//    Start->|W[0][0]|         |W[1][0]|         |W[2][0]|         |W[3][0]|
//           +-------+         +-------+         +-------+         +-------+
//           |W[0][1]|         |W[1][1]|         |W[2][1]|  Start->|W[3][1]|
//           +-------+         +-------+         +-------+         +-------+
//           |W[0][2]|         |W[1][2]|  Start->|W[2][2]|         |W[3][2]|
//           +-------+         +-------+         +-------+         +-------+
//           |W[0][3]|  Start->|W[1][3]|         |W[2][3]|         |W[3][3]|
//           +-------+         +-------+         +-------+         +-------+
// 
//       t0: W[0][0]    ...      ...      ...
//       t1: W[0][1]  W[1][0]    ...      ...
//       t2: W[0][2]  W[1][1]  W[2][0]    ...
//       t3: W[0][3]  W[1][2]  W[2][1]  W[3][0]
//       t4:   ...    W[1][3]  W[2][2]  W[3][1]
//       t5:   ...      ...    W[2][3]  W[3][2]
//       t6:   ...      ...      ...    W[3][3]
// 
////////////////////////////////////////////////////////////////////////////////

import dct_defs::*;

module dct_W_ROM(
  input                       clk,
  input                       rst,
  output logic                req,
  output logic                init_ACC[POINT_N],
  output logic [WIDTH_W-1:0]  W[POINT_N]);
  
  // ROMs and read contents from external file
  logic [WIDTH_W-1:0] ROM_W[POINT_N][POINT_N] = {
                        `include "dct_ROM_Table.txt"};

  // Address generator
  logic unsigned [DEPTH_W-1:0] addr_W;
  always_ff @(posedge clk, posedge rst)
  begin : Gen_W_ROM_Addr
    if (rst==1)
      addr_W = 0;  // Coeff. ROM data out, wait for 1-clock after reset
    else
      addr_W += 1;
  end
  
  // ROM Data out
  genvar i;
  wire [DEPTH_W-1:0] addr_Wn[POINT_N];
  for (i=0; i<POINT_N; i++)
  begin
    // ROM Address delayed for Pipelined operation
    assign addr_Wn[i] = addr_W - i;
    assign W[i] = ROM_W[i][addr_Wn[i]];
    //assign W[i] = ROM_W[i][addr_W-i];

    // Control signal for initializing PE's accumulator
    assign init_ACC[i] = (addr_Wn[i]==0)? 1:0;
  end
  //assign req = (addr_W==0)? 1:0;
  assign req = (addr_W=='1)? 1:0;
  
endmodule

----------------------------------------------------------
//
// Project: N-Point DCT
// File   : dct_ROM_Table.txt
// Author : Kook, goodkook@gmail.com
//
// 2-Dimensional Array Contents
//    for 8-Point DCT
//

{ 8192,  8192,  8192,  8192,  8192,  8192,  8192,  8192},
{11363,  9633,  6436,  2260, -2260, -6436, -9632,-11362},
{10703,  4433, -4433,-10703,-10703, -4433,  4433, 10703},
{ 9633, -2260,-11362, -6436,  6436, 11363,  2260, -9632},
{ 8192, -8192, -8192,  8192,  8192, -8191, -8191,  8192},
{ 6436,-11362,  2260,  9633, -9632, -2260, 11363, -6436},
{ 4433,-10703, 10703, -4433, -4433, 10703,-10703,  4433},
{ 2260, -6436,  9633,-11362, 11363, -9632,  6436, -2260}
---------------------------------------------------------
//
// Project: N-Point DCT
// File   : dct_PE.sv
// Author : Kook, goodkook@gmail.com
//
///////////////////////////////////////////////////////////////////////
//
//        Processing Element for Pipelined 1-D DCT
//        ----------------------------------------
//        - Parametized design in
//             WIDTH_X, WIDTH_W, WIDTH_Y, CONST_BITS
//
//     [WIDTH_X]  +-----+
// in_X------\---->     -----------+---------------------------->out_X
//                |     |          |
//           clk-->     |          |
//                +-----+          |
//                                 \
//     [WIDTH_W]  +-----+          |
// in_W------\---->     -------+   |
//                |     |      |   |
//           clk-->     |      |   |
//                +-----+   +--V---V--+ 
//                          \ MULTPLY /
//                           +---|---+
//                               |
//               +-----\-----+   \[WIDTH_X+WIDTH_W]
//               |           |   |
//               |         +-V---V-+
//               |         \  ADD  /
//               |          +--|--+
//           +---|---+         |
//           |  MUX  |         |
// init_ACC--> 1   0 |         \[WIDTH_X+WIDTH_W+1]
//           +-|---|-+         |
//             |   |           |
//            '0   |  +-----+  |
//                 +<--     <--+
//                 |  | ACC |
//                 |  |     <--clk
//                 |  +-----+
//                 |
//                 |  +-------+     [WIDTH_Y]
//                 +--|DESCALE|-----\-----------> out_Y(Yn)
//                    +-------+
//                    [CONST_BITS]
//    
///////////////////////////////////////////////////////////////////////

import dct_defs::*;
`define DESCALE(x,n)  (((x) + (1 << ((n)-1))) >> n)

module dct_PE(
  input                       clk,
  input                       rst,
  input         [WIDTH_X-1:0] in_X,
  input         [WIDTH_W-1:0] in_W,
  input                       init_ACC,
  output  logic [WIDTH_X-1:0] out_X,
  output  logic               valid_Y,
  output        [WIDTH_Y-1:0] out_Y );

  // Register for X to be shifted
  always_ff @(posedge clk, posedge rst)
  begin : Reg_X
    if (rst==1)
   out_X = 0;
    else
      out_X = in_X;
  end

  // Latch W & init_ACC input (Delay, because of in_X shift)
  logic signed [WIDTH_W-1:0]  latch_W;
  logic                       _init_ACC;
  always_ff @(posedge clk, posedge rst)
  begin : Reg_W
    if (rst==1) begin
      latch_W   = 0;
      _init_ACC = 0;
    end
    else begin
      latch_W   = in_W;
      _init_ACC = init_ACC;
    end
  end

  // Multiplier
  logic signed [(WIDTH_W+WIDTH_X)-1:0] mult_W_X;
  assign mult_W_X = signed'(latch_W) * signed'(out_X);

  // Accunulator
  logic signed [(WIDTH_W+WIDTH_X)-1:0] Acc;
  always_ff @(posedge clk, posedge rst)
  begin : Accmulator
    if (rst==1)
      Acc = 0;
    else
    begin
      if (_init_ACC==1)
        Acc = mult_W_X;
      else
        Acc = signed'(Acc) + signed'(mult_W_X);
    end // if-else
  end // always_ff

  // Output Y
  assign out_Y   = `DESCALE(Acc, CONST_BITS); // De-Scale!!!
  assign valid_Y = _init_ACC;
  
/*  
  always_ff @(posedge clk, posedge rst)
  begin
    if (rst==1)
      valid_Y = 0;
    else
      valid_Y = init_ACC;
  end
*/
endmodule
----------------------------------------------------
//
// Project: N-Point DCT
// File   : dct_Out.sv
// Author : Kook, goodkook@gmail.com
//
//
///////////////////////////////////////////////////////////////////////////////
//
//          Serialized out_Y
//          ----------------
//  
//   from multiple PE (it was pipelined parallelism)
//                   +-----\
//                   |      \
//      out_Y[0]--\-->    S  \
//                   |    E   |
//      out_Y[1]--\-->    L   |
//                   |    E   |      +------+
//      out_Y[2]--\-->    C   |      |      |
//                   |    T   ----\-->      ---\--> out_Y
//                   |        |      |      |
//         .....              |      |      |
//                   |    Y   |  clk->      |
//                   |        |      |      |
//     out_Y[N-1]-\-->       /       +------+
//                   |      /
//                   +--|--/
//                      |
//     valid_Y[0]-------+
//     valid_Y[1]-------+
//     valid_Y[2]-------+
//       ....           |
//     valid_Y[N-1]-----+
//  
//                  +-+ +-+ +-+ +-+ +-+         +-+ +-+ +-+ +-+ +-+ +-+
//                  | | | | | | | | | |         | | | | | | | | | | | |
//            clk --+ +-+ +-+ +-+ +-+ +-.....  -+ +-+ +-+ +-+ +-+ +-+ +-
//  
//                  +---+                                   +---+
//                  |   |                                   |   |
//      valid_Y[0]--+   +-----------.....-------------------+   +--------
//  
//                --+---+-----------     -------------------+---+--------
//        out_Y[0]..|   |...        .....                ...|   |...
//                --+---+-----------     -------------------+---+--------
//  
//                      +---+                                   +---+
//                      |   |                                   |   |
//      valid_Y[1]------+   +-------.....-----------------------+   +---
//  
//                    --+---+-------     -----------------------+---+---
//        out_Y[1]   ...|   |....   .....                    ...|   |...
//                    --+---+-------     -----------------------+---+--
//  
//                                      ..............
//                                                      +---+
//                                                      |   |
//    valid_Y[N-1]------------------.....---------------+   +---
//  
//                ------------------     ---------------+---+-------------
//    out_Y[N-1]                    .....            ...|   |....
//                ------------------     ---------------+---+-------------
//  
///////////////////////////////////////////////////////////////////////////////

import dct_defs::*;

module dct_Out(
  input                       clk,
  input                       rst,
  input                       valid_Y[POINT_N],
  input         [WIDTH_Y-1:0] in_Y[POINT_N],
  output  logic [WIDTH_Y-1:0] out_Y,
  output  logic               rdy_Y);

  logic _valid_Y[POINT_N*2];
  
  // Serialize for output Y
  integer i;
  always_ff @(posedge clk, posedge rst)
  begin
    if (rst==1)
      out_Y = 0;
    else
      for (i=0; i<POINT_N; i++)
        if (valid_Y[i]==1)
          out_Y = in_Y[i];
  end
  
  // Ready for the first Y
  always_ff @(posedge clk, posedge rst)
  begin
    if (rst==1)
    begin
      for (i=0; i<(POINT_N*2); i++)
        _valid_Y[i] = 0;
      rdy_Y = 0;
    end
    else
    begin
      _valid_Y[0] <= valid_Y[0];
      for (i=1; i<(POINT_N*2); i++)
        _valid_Y[i] <= _valid_Y[i-1]; // Shift!
      rdy_Y <= _valid_Y[(POINT_N*2)-1];
    end
  end

endmodule
-------------------------------------------------------
//
// Project: N-Point DCT
// File   : dct_top.sv
// Author : Kook, goodkook@gmail.com
//
//////////////////////////////////////////////////////////////////////////////
//              N-Point DCT
//              -----------
//         - Commonly used kernel in DSP: 2D_Matrix(Coeff.) * Vector
//         - Applicable to DCT
//         - Pipelined Parallelism
//              Pully Pipelined(0-Clock delay)
//              Latency: N+1 Clocks from first input
//         - Parametized design
//              Pipeline depth(Number of Vector length
//              Width of input X, coeff-W and output Y
// 
//         +---------------------------------------+
//         |            Parametized PEs            |
//         |     PE0       PE1            PEn      |
//         |    +---+     +---+          +---+     |
//         |    |   |     |   |          |   |     |
// in_X --->---->   ------>   -->......-->   --------->out_X
//         |    |   |     |   |          |   |     |
//         |W0x->   | W1x->   |      Wnx->   |     |
//         |    +-|-+     +-|-+          +-|-+     |
//         |      |         |              |       |
//         |      +->Y0     +->Y1          +->Yn   |
//         |                                       |
//         |      +-----------+      +-----------+ |
//         |   W<-- Generate W|   Y0->           ----->out_Y
//         |      | 2-D Array |   Y1-> Serialize | |
// req_X<----------   ROM     |    ..|    Yn     -----> rdy_Y
//         |      +-----------+   Yn->           | |
//   rst--->                         +-----------+ |
//         |                                       |
//   clk--->                                       |
//         +---------------------------------------+
//        
//          +-+ +-+ +-+ +-+ +-+       + +-+ +-+ +-+ +-+ +-+ +-+ +-+
//          | | | | | | | | | |       | | | | | | | | | | | | | | |
//    clk --+ +-+ +-+ +-+ +-+ +-.....-+-+ +-+ +-+ +-+ +-+ +-+ +-+ +-
//          0   1   2   3               N-1 N   N+1
//          :   :   :   :               :   :   :   :
//          +---+   :                   +---+   :   :
//          |   |   :   :               |   |   :   :
//   req_X--+   +-----------------------+   +---------
//          :   :   :   :               :   :   :   :
//           +--*+---+---+---+--       --+--*+---+---+---+--
//    in_X---| X0| X1| X2| X3| ......... |X"0|X"1|X"2|X"3|
//           +---+---+---+---+--       --+---+---+---+---+--
//                  :   :                       :   :
//                  +---+                       +---+
//                  |   |                       |   |
//   rdy_Y----------+   +------.........--------+   +---------------
//                  :   :                       :   :
//                --+---+---+--               --+---+---+---+---+--
//   out_Y--...Y'n-1|Y'0|Y'1| .........    Y'n-1| Y0| Y1| Y2| ......
//                --+---+---+--               --+---+---+---+---+--
//        
//////////////////////////////////////////////////////////////////////////////
       
import dct_defs::*;

module dct_top(
  input                 clk,
  input                 rst,
  input   [WIDTH_X-1:0] in_X,
  output                req_X,
  output  [WIDTH_X-1:0] out_X,
  output  [WIDTH_Y-1:0] out_Y,
  output                rdy_Y );

  // Instantiate DCT Coeff. ROM generator
  wire  [WIDTH_W-1:0] W[POINT_N];
  logic               init_ACC[POINT_N];

  dct_W_ROM U_dct_ROM(  .clk(clk),
                        .rst(rst),
                        .req(req_X),
                        .init_ACC(init_ACC),
                        .W(W));
  
  // Generate DCT processing elements
  genvar i;
  logic [WIDTH_X-1:0] temp_X[POINT_N];
  logic [WIDTH_Y-1:0] temp_Y[POINT_N];
  logic               valid_Y[POINT_N];
  
  // First PE
  dct_PE U_dct_PE0( .clk(clk),
                    .rst(rst),
                    .in_X(in_X),
                    .in_W(W[0]),
                    .init_ACC(init_ACC[0]),
                    .out_X(temp_X[0]),
                    .valid_Y(valid_Y[0]),
                    .out_Y(temp_Y[0]));
  // Pipelined cascade PEs
  for (i=1; i<POINT_N; i++)
  begin
    dct_PE U_dct_PEn( .clk(clk),
                      .rst(rst),
                      .in_X(temp_X[i-1]),
                      .in_W(W[i]),
                      .init_ACC(init_ACC[i]),
                      .out_X(temp_X[i]),
                      .valid_Y(valid_Y[i]),
                      .out_Y(temp_Y[i]));
  end

  // DCT OUT with De-Scaling
  dct_Out U_dct_Out(  .clk(clk),
                      .rst(rst),
                      .valid_Y(valid_Y),
                      .in_Y(temp_Y),
                      .out_Y(out_Y),
                      .rdy_Y(rdy_Y));

  // Output X
  assign out_X = temp_X[POINT_N-1];
  
endmodule
-------------------------------------------------------------

//
// Project: N-Point DCT
// File   : dct_Testbench.sv
// Author : Kook, goodkook@gmail.com
//


import dct_defs::*;

module dct_Testbench();

  logic clk, rst, req_X, rdy_Y, _Error_;
  logic [WIDTH_X-1:0] in_X;
  logic [WIDTH_X-1:0] out_X;
  logic [WIDTH_Y-1:0] out_Y;

  integer idx_X, idx_Y;
  
  // Instantiate DUT
  dct_top DUT_dct_top ( .clk(clk),
                        .rst(rst),
                        .in_X(in_X),
                        .req_X(req_X),
                        .out_X(out_X),
                        .out_Y(out_Y),
                        .rdy_Y(rdy_Y));

  // Instantiate SC module: Stimulus generator
  gen_stim U_gen_stim ( .clk(clk),
                        .req_X(req_X),
                        .out_X(in_X),
                        .idx_X(idx_X));

  // Instance SC module: Check-Out
  check_out u_check_out ( .clk(clk),
                          .req_X(req_X),
                          .in_X(in_X),
                          .rdy_Y(rdy_Y),
                          .in_Y(out_Y),
                          .idx_Y(idx_Y),
                          ._Error_(_Error_));
  
  // Clock Generator
  always
  begin
    clk = 0;
    forever #10 clk = ~clk;
  end

  // Reset
  initial begin
    #0  rst = 0;
    #5  rst = 1;
    #15 rst = 0;
  end

/* **************************************
  // Input X
  initial begin
    in_X =0;
    @(posedge req_X);
    @(posedge req_X);
    in_X = 2048;

    @(posedge req_X);
    in_X = 1024;

    @(posedge req_X);
    in_X = 2048;

    @(posedge req_X);
    in_X = 0;

    @(posedge req_X);
    forever @(posedge clk)
      in_X = $random;
  end
****************************************** */

endmodule

---------------------------------------------
//
// Project: N-Point DCT
// File   : gen_stim.h
// Author : Kook, goodkook@gmail.com
//

#ifndef INCLUDED_GEN_STIM
#define INCLUDED_GEN_STIM

#include <systemc.h>

#include "../c/dct.h"

SC_MODULE(gen_stim)
{
public:
    // Ports
    sc_in<sc_logic>       clk;
    sc_in<sc_logic>       req_X;
    sc_out<sc_uint<DW> >  out_X;
    sc_out<int>           idx_X;

    // Internal Signals
    sc_signal<sc_uint<DW> > nTest;

    // Methods
    void stimulus();

    SC_CTOR(gen_stim)
      : clk("clk"),
        req_X("req_X"),
        out_X("out_X"),
        idx_X("idx_X")
    {
        SC_METHOD(stimulus);
        sensitive_pos << clk;
        dont_initialize();

        // Other constructor
        long  ltime;
        int   stime;

        // get the current calendar time
        ltime = time(NULL);
        stime = (unsigned) ltime/2;
        srand(stime); // Init. seed for random number gen.
    }

    // Destructor does nothing
    ~gen_stim()
    {
    }
};

#endif
-------------------------------------------
//
// Project: N-Point DCT
// File   : gen_stim_stimulus.cpp
// Author : Kook, goodkook@gmail.com
//

#include "gen_stim.h"

#include <time.h>
#include <math.h>

#define my_cos(a,p,n) \
              (a * cos((float)p*M_PI*(float)n/(float)DCT_SIZE))
#define my_sin(a,p,n) \
              (a * sin((float)p*M_PI*(float)n/(float)DCT_SIZE))

void gen_stim::stimulus()
{
  static int nTestSet = 0;
  static int nCount;

  // Check for req_X as start of new input frame
  if (req_X.read()=='1')
  {
    nCount = 0;
    // Constant input
    if (nTestSet==0)        out_X.write(0);
    else if (nTestSet==1)   out_X.write(1024);
    else if (nTestSet==2)   out_X.write(2048);
    // cos() input
    else if (nTestSet==3)
      out_X.write((sc_uint<16>)my_cos(2048, 1.0, nCount));
    else if (nTestSet==4)
      out_X.write((sc_uint<16>)my_sin(2048, 1.0, nCount));
    else if (nTestSet==5)
      out_X.write((sc_uint<16>)rand());
  }
  // Stimulus generation during in-frame, 
  else
  {
    nCount++;
    if (nTestSet==3)        // cos()
      out_X.write((sc_uint<16>)my_cos(2048, 1.0, nCount));
    else if (nTestSet==4)   // sin()
      out_X.write((sc_uint<16>)my_cos(2048, 1.0, nCount));
    else if (nTestSet==5)   // rand()
      out_X.write((sc_uint<16>)rand());

    if (nCount==(DCT_SIZE-1))
      if (nTestSet<5) nTestSet++;
  }

  // Signal
  nTest.write((sc_uint<16>)nCount);
  idx_X.write(nCount);
}
--------------------------------------------------------
//
// Project: N-Point DCT
// File   : check_out.h
// Author : Kook, goodkook@gmail.com
//

#ifndef INCLUDED_CHECK_OUT
#define INCLUDED_CHECK_OUT

#include <systemc.h>
#include "../c/dct.h"

SC_MODULE(check_out)
{
public:
    // Ports
    sc_in<sc_logic>       clk;
    sc_in<sc_logic>       req_X;
    sc_in<sc_uint<DW> >   in_X;
    sc_in<sc_logic>       rdy_Y;
    sc_in<sc_uint<DW> >   in_Y;
    sc_out<int>           idx_Y;
    sc_out<sc_logic>      _Error_;

    // Internal Signals
    sc_signal<sc_uint<16> > nTest;

    // Internal variables for DCT Algorithm
    dct_data_t src[DCT_SIZE], _src[DCT_SIZE], __src[DCT_SIZE]; // Inputs
    dct_data_t dst[DCT_SIZE], _dst[DCT_SIZE], __dst[DCT_SIZE]; // C-Result
    dct_data_t rtl[DCT_SIZE];                 // RTL Result

    // Methods
    void Do_C_Model();  // Receive and C-Model
    void Do_Compare();  // Compare RTL vs. C Results

    SC_CTOR(check_out)
      : clk("clk"),
        req_X("req_X"),
        in_X("in_X"),
        rdy_Y("rdy_Y"),
        in_Y("in_Y"),
        idx_Y("idx_Y"),
        _Error_("_Error_")
    {
        SC_METHOD(Do_C_Model);
        sensitive << clk; // Sensitize clk on both edge
        dont_initialize();

        SC_METHOD(Do_Compare);
        sensitive_pos << clk;
        dont_initialize();

        // Initialize local vars
        for (int i=0; i<DCT_SIZE; i++)
        {
          src[i] = _src[i] = __src[i] = 0;
          dst[i] = _dst[i] = __dst[i] = 0;
          rtl[i] = 0;
        }
        _Error_ = sc_logic('0');
    }

    // Destructor does nothing
    ~check_out()
    {
    }
};

#endif
------------------------------------------------------------

//
// Project: N-Point DCT
// File   : check_out_model.cpp
// Author : Kook, goodkook@gmail.com
//

#include "check_out.h"

// METHOD:
//    Receive Data and Do C-Model
void check_out::Do_C_Model()
{
  static int nCount;
 
  if (req_X.read()=='1')
  {
    if (clk.negedge())
    {
      // req_X:
      //   Do C-Model with previous frame data before saving new.

      // Last in_X
      src[nCount] = (dct_data_t)in_X.read();
     
      // Call C-Model DCT
      dct_1d(src, dst);
 
      // DEBUG: Backup Inputs and C-Model results
      for (int i=0; i<DCT_SIZE; i++)
      {
        _src[i] = src[i];
        _dst[i] = dst[i];
      }
    }
    else if (clk.posedge())
    {
      // Start new frame
      nCount = 0;
    }
  }
  else if (clk.negedge())
  {
      src[nCount] = (dct_data_t)in_X.read();
      nCount++;
  }

  // Signal
  //nTest.write((sc_uint<16>)nCount);
}

// METHOD:
//    Compare RTL vs. C Result
void check_out::Do_Compare()
{
  static int nCount;
  dct_data_t  temp_Y = (dct_data_t)in_Y.read();

  if (rdy_Y.read()=='1')
  {
    // rdy_Y:
    //   As new result started,
    //   Compare RTL-Model with previous frame result

    // DEBUG: Show inputs
    printf("\nDCT Inputs:");
    for (int i=0; i<DCT_SIZE; i++)
      printf("%10d", __src[i]);

    // DEBUG: Show C-Model results
    printf("\nDCT Result:");
    for (int i=0; i<DCT_SIZE; i++)
      printf("%10d", __dst[i]);

    // DEBUG: Show RTL result
    printf("\nRTL Result:");
    for (int i=0; i<DCT_SIZE; i++)
      printf("%10d", rtl[i]);
    printf("\n===============================================================\n");

    // Compare two results
    for (int i=0; i<DCT_SIZE; i++)
    {
      if (rtl[i]!=__dst[i])
      {
        _Error_ = sc_logic('1');
        printf("ERROR at [%d]: Cout=%d RTLout=%d", i, dst[nCount], temp_Y);
        printf("\n===============================================================\n");
      }
      else
        _Error_ = sc_logic('0');
    }

    // DEBUG: Backup Inputs and C-Model results
    for (int i=0; i<DCT_SIZE; i++)
    {
      __src[i] = _src[i];
      __dst[i] = _dst[i];
    }

    nCount = 0;
    rtl[nCount] = temp_Y;
  }
  else
  {
    if (nCount<(DCT_SIZE-1))
    {
      nCount++;
      rtl[nCount] = temp_Y;
    }
  }

  // Showing out_Y index, 1-clock delayed
  //idx_Y.write(nCount);
  idx_Y.write( ((nCount+1)>=DCT_SIZE)? 0:nCount+1 );
  // Signal
  //nTest.write((sc_uint<16>)nCount);
}


12월 밤하늘 관측(365 Days of Astronomy)

12월 밤하늘 관측(365 Days of Astronomy)

Sky Guide - December 2015
* 365 Days of Astronomy 팟 캐스트를 통해 방송되는 매월 관측 정보 입니다.

음원 및 녹취: http://cosmoquest.org/x/365daysofastronomy/2015/12/02/dec-2nd-awesome-astronomys-december-sky-guide-2/

폴(Paul):
Paul: December for astronomers means three things, new kit, the longest darkest nights and new socks… and all are very welcome! It is a month to get out and wrap up warm to take advantage of those long nights and of course the winter sky is one of the most spectacular of the year. But before we look at what the solar system is giving us and our deep sky tour, what has Ralph lined up for our beginners guide?

천문가에게 12월이란 새장비, 길고 어두운 밤하늘 그리고 새양말을 의미하죠. 다 수긍이 갑니다. 이달은 연중 가장 멋진 모습을 보여 줍니다. 따뜻하게 꽁꽁 싸메고 긴 겨울 밤하늘을 즐기러 나가봅시다. 먼저, 태양계에서 벌어지는 사건과 심우주 관측을 떠나기 전에 랄프(Ralph)가 준비한 초보자 관측안내를 들어보기로 하죠.

랄프(Ralph):
Well, in December we welcome back the Gemini twins. We’ve got an easy binary star, an open cluster, a faint planetary nebula and a bit of exoplanet hunting to finish with in Gemini.

쌍둥이, 제미나이(Gemini)가 12월에 다시 찾아왔습니다. 쌍둥이 자리에서 쉽게 관측 가능한 이중성(binary star), 산개성단(open cluster), 어둡긴 하지만 행성상 성운(planetary cloud), 끝으로 외계행성(exoplanet) 찾기에 대해 살짝 알아 봅니다.

Firstly, you’ll want to find the shape of the two twins Castor and Pollux (that’s Pollux) which are also the names of the brightest two stars in the constellation that sit at the head of the twins. Pollux is the lower one of the two, with Castor looking slightly dimmer immediately above it. And by the end of the month they’ll be high up in the south around midnight.

먼저 쌍둥이의 머리에 해당하는 두개의 별 이름은 카스토(Castor) 와 폴룩스(Pollux) 입니다. 두 별중 아래의 별이 폴룩스 이고 그보다 조금 어두운 카스토가 바로 위에 있죠.  이달 말경에 한밤중이 되면 이 별들은 남쪽 하늘 높이 뜨겠습니다.




Our first stop is Castor which is actually a quadruple star system but we can only easily resolve it into two stars. With a modest 60x magnification a small scope will easily split Castor into the two white stars that sit 50 light years away orbiting around their centre of gravity every 450 years or so.

먼저 살펴볼 대상은 카스토인데 언뜻 보기엔 이중성(binary star)으로 보이지만 실제로 4중성(quadruple)입니다. 배율이 60배 가량 정도되는 작은 망원경으로도 카스토가 두개의 밝은 흰색 별로 분리된 모습을 볼 수 있습니다. 두별은 약 50광년 떨어져 있으며 중력을 중심으로 두고 약 450년 만에 한바퀴 돕니다.






출처: Meet Castor, Remarkable double star

Next up we go to the far end of Gemini and the outstretched leg of Castor. Actually, there’s a line of 4 open clusters all within 2 degrees of each other here, just above the highest foot. But we’re interested in the brightest cluster that appears to be sitting on top of castor’s foot. This is Messier 35 or NGC 2168 and at magnitude 5 you might just be able to see it with the naked eye in dark skies and it’s a favourite with binocular viewers. But just a little extra magnification will show the tendrils of stars that seem to emanate from a dark void in the centre. But do trace the line back down to 1 Geminorum in the foot and see how many of the 4 open clusters you can bag.

다음은 쌍동이 자리 끝으로 가보죠. 카스토의 발치쪽 입니다. 실제로 4개의 산개 성단이 2도 간격을두고 줄서 있습니다. 메시에 35번 또는 NGC2168은 5등성으로 어두운 밤이면 맨눈으로도 볼 수 있습니다. 쌍안경으로도 즐겨 관측하는 대상이기도 합니다. 배율을 좀더 높여 보면 어둠속에서 중심으로 부터 빛을 발산하는 덩쿨의 모습을 볼 수 있습니다. 발끝을 따라 늘어선 4개의 산개성단도 찾아보세요.


M35

Next up is more of a challenge and I’d recommend at least a 5” scope for this. If you draw line from the star in the waist of the Castor, through to Wasat in the waist of Pollux, then extend this line for two more degrees or the width of two fingers held at arm’s length. This should find you in the right spot for the Eskimo Nebula NGC 2392. Although a faint smudge in small scopes, a larger aperture will show you the iconic face inside a Parka hood that gives this planetary nebula its name. At almost 3,000 light years away William Herschel was still able to spot this magnitude 10 fuzzy star, which we now know is shells of gas that are energised by the star in the centre.

다음은 난이도가 좀더 높은 대상입니다. 구경이 5인치는 되야 볼 수 있죠. 카스토의 허리에서 폴룩스의 허리에 있는 와삿(Wasat)을 지나는 선을 2도, 즉 팔을 뻗혀본 손가락 두개 굵기 가량 되는 만큼 더 연장한 위치를 잘 살펴 봅시다. 이 위치에 에스키모(Eskimo) 성운으로 알려진 NGC2392가 있죠. 작은 망원경으로 보면 그냥 어두운 흔적정도로 보이겠지만 대구경 망원경으로 보면 털모자를 둘러쓴 얼굴 모양이 선명하게 나타납니다. 거의 3천 광년쯤 떨어진 이별은 윌리엄 허셜이 10개의 기이한 천체라고 지명했던 것으로 지금은 중심부의 밝은 별에서 발산된 빛이 주변을 둘러싼 먼지에 반사된 것으로 밝혀졌죠. (*중심에 별이 있고 주변을 둥글게 둘러싼 먼지를 행성상 성운(Planetary Nebula)이라함. 이 먼지들이 나중에 행성(Planet)으로 진화 할 수 있음. 수억~수십억년이 걸리겠지만...)

에스키모 성운 위치(무려 10등성!)

12인치/F5 뉴턴 반사망원경으로 관측한 에스키모 성운 스케치

35인치 망원경으로 본 에스키모 성운

허블 우주망원경으로 본 에스키모성운

Finally we go exogazing. We can’t spot exoplanets with amateur telescopes but we can take a look at their host stars and know the characteristics of the planets that orbit some of them. And in Gemini we have the exoplanet with the brightest host star, Pollux in the head of the lower twin in the sky.

끝으로 외계행성에 대해 이야기 해봅니다. 사실 아마추어 천문가용의 망원경으로 외계행성을 관측할 순 없죠. 하지만 이 행성의 중심에 있는 별은 볼 수 있으며 공전하고 있는 행성이 있음직한 특성은 알 수 있습니다. 쌍둥이 자리에서 행성을 가진 밝은 별이 있는데 바로 아랫쪽 머리 별인 폴룩스 입니다.


Taking a look at this orange giant, you can know with some certainty that there is a gas giant planet called Pollux b orbiting a similar distance from Pollux as Mars is from our sun, but three times the size of Jupiter. And there are at least 6 other stars in Gemini that are known to play host to other planets.

이 오랜지색 밝은 거성은 폴룩스 b(Pollux b)라는 거대한 가스 덩어리 행성을 가지고 있습니다. 태양에서 지구까지 거리만큼 떨어져 있고 크기는 목송의 세배에 달하죠. 그외 쌍둥이 자리에 행성을 가진 별이 6개 더 있다고 알려 졌습니다.

참조: Pollux b

So back to you Paul.
폴 나오세요...

Paul:

The Solar system this month sees all the real action in the constellation of Virgo, which is hoarding all of this month’s solar system treasure. It is a view for the night owls but well worth staying up beyond midnight for. First we have Jupiter that rises around midnight and is once again really starting to come into it’s own, by 2.30 jupiter is joined by mars which is still pretty unimpressive in all but the largest scopes but is beginning to improve as we slowly move towards the 2016 opposition. Then before 4am the potential highlight of the season appears comet C2013 US10 Catalina. This of course has a big caveat of “it’s a comet” on it so of course may never hold to predictions, but at present we are looking at a naked eye comet, possible getting down to magnitude 4. I know, I know you’re excited, i’m excited too, but please don’t get cross if it doesn’t behave. The comet will move through the month towards Arcturus in Bootes, passing that star on new years day. To complete the set Venus gives you the finale of this solar system extravaganza, rising about 4.30. If you have the energy to do so, several early morning sessions of astronomy are probably in order through December, which if you are out and about on the 13th and 14th you will also have the added bonus of one of the great meteor showers, the Geminids.

Indeed the Geminids have a ZHR bigger than the perseids. It is perhaps less famous because of the time of year, the perseids picking the warmer less cloudy time of the year to put on their show. The radiant will move past Castor in Gemini through the month with the radiant just next to Castor at the showers peak on the 13th/14th. The best time to see the shower is in the early hours of the 14th. This should be a great year for seeing the geminids as the moon is new on the 11th so will be well out of the way for the peak. Our companion is at last quarter on the 3rd, first quarter on the 18th and full on the 25th.

For our deep sky challenge this month we are going look at objects that are in or near Orion that aren’t the habit forming M42 or flame and horsehead nebulae. The area of sky around Orion is one of the skies most famous and always eagerly anticipated, but hidden around it are perhaps some of the most overlooked deepsky objects, drowned out by the clamour for perhaps the most famous objects in the sky.

First of all let’s start with two of the most ignored Messier objects on the list. M78 is in Orion just to the left of a line from Betelgeuse and alnitak in the belt. This is an emission nebula that is also part of the orion molecular cloud and is around 1600 light years away. You will see two stars with this cloud that are around magnitude 10 and are responsible for lighting up this cloud of dust.

Next we are dropping below Orion into the rarely viewed constellation of Lepus the Hare, the poor creature being chased by Orions dogs. Below the main body of the constellation you can find Messier 79 a globular cluster, unusual for the time of year as we mainly think of globs as a summer target and also a bit of an enigma as it is thought that M79 is not native to our galaxy and may have originally formed part of the disputed canis major dwarf galaxy. It is often described as starfish shaped and is magnitude 8 and 42,000 light years away.

We will now jump to the right of Orion and look at the constellation Eridanus, the river. It is a long indistinct constellation that fills the sky in the area to the right of Rigel. Here you can track down two nice targets in the form of planetary nebula NGC1535 which is a real challenge for observer and imager alike and will need patience and good skies, but you will be rewarded with a distinctive blue fuzzy disc. To begin your hunt start at the star Zaurak and move back towards Rigel and as Zaurak leaves your finder scope you are close. Now above 1535 is a nice multiple known as Keid which has celebrity status, for this is the home star of the planet Vulcan. Keid A is in fact very similar to our sun and must be a prime target for SETI, it has two faint companions B which is easily seen in a reasonable sized scope at low power and C which is much fainter and requires high magnification and a good clear sky.

For our last around Orion challenge we go back into the constellation itself but this time to the rarely visited club, the area of stars above betelgeuse towards gemini. Here you will find The monkey head nebula NGC2174 and an associated cluster 2175. This is an Hii emission nebula 6,400 light years away and is magnitude 6.8.

So I wish you happy hunting and clear skies.