1
0
mirror of https://github.com/pConst/basic_verilog.git synced 2025-02-04 07:12:56 +08:00
Konstantin Pavlov (pt) 40533743d7 Added altera cookbook
2015-12-15 22:44:58 +03:00

375 lines
9.0 KiB
Verilog

// Copyright 2007 Altera Corporation. All rights reserved.
// Altera products are protected under numerous U.S. and foreign patents,
// maskwork rights, copyrights and other intellectual property laws.
//
// This reference design file, and your use thereof, is subject to and governed
// by the terms and conditions of the applicable Altera Reference Design
// License Agreement (either as signed by you or found at www.altera.com). By
// using this reference design file, you indicate your acceptance of such terms
// and conditions between you and Altera Corporation. In the event that you do
// not agree with such terms and conditions, you may not use the reference
// design file and please promptly destroy any copies you have made.
//
// This reference design file is being provided on an "as-is" basis and as an
// accommodation and therefore all warranties, representations or guarantees of
// any kind (whether express, implied or statutory) including, without
// limitation, warranties of merchantability, non-infringement, or fitness for
// a particular purpose, are specifically disclaimed. By making this reference
// design file available, Altera expressly does not recommend, suggest or
// require that this reference design file be used in combination with any
// other product not provided by Altera.
/////////////////////////////////////////////////////////////////////////////
// baeckler - 04-13-2006
// RC4 stream
// algorithm taken from "Applied Cryptography" by Bruce Schneier
////////////////////////////////////////////////////
// dual port RAM helper, 256 words x 8 bits
////////////////////////////////////////////////////
module sbox_ram (
address_a,
address_b,
clock,
ena,
data_a,
data_b,
wren_a,
wren_b,
q_a,
q_b
);
input [7:0] address_a;
input [7:0] address_b;
input clock,ena;
input [7:0] data_a;
input [7:0] data_b;
input wren_a;
input wren_b;
output [7:0] q_a;
output [7:0] q_b;
wire [7:0] sub_wire0;
wire [7:0] sub_wire1;
wire [7:0] q_a;
wire [7:0] q_b;
altsyncram altsyncram_component (
.wren_a (wren_a),
.clock0 (clock),
.wren_b (wren_b),
.address_a (address_a),
.address_b (address_b),
.data_a (data_a),
.data_b (data_b),
.q_a (q_a),
.q_b (q_b),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clock1 (1'b1),
.clocken0 (ena),
.clocken1 (1'b1),
.rden_b (1'b1));
defparam
altsyncram_component.address_reg_b = "CLOCK0",
altsyncram_component.clock_enable_input_a = "NORMAL",
altsyncram_component.clock_enable_input_b = "NORMAL",
altsyncram_component.clock_enable_output_a = "NORMAL",
altsyncram_component.clock_enable_output_b = "NORMAL",
altsyncram_component.indata_reg_b = "CLOCK0",
altsyncram_component.intended_device_family = "Stratix II",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 256,
altsyncram_component.numwords_b = 256,
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
altsyncram_component.outdata_aclr_a = "NONE",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_a = "CLOCK0",
altsyncram_component.outdata_reg_b = "CLOCK0",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE",
altsyncram_component.widthad_a = 8,
altsyncram_component.widthad_b = 8,
altsyncram_component.width_a = 8,
altsyncram_component.width_b = 8,
altsyncram_component.width_byteena_a = 1,
altsyncram_component.width_byteena_b = 1,
altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK0";
endmodule
////////////////////////////////////////////////////
// stream generator - 1 byte per 4 cycles
////////////////////////////////////////////////////
module rc4 (clk,ena,rst,load_key,key,dat_valid,dat);
parameter KEY_BYTES = 5;
input clk,ena,rst,load_key;
input [KEY_BYTES*8-1:0] key;
output [7:0] dat;
output dat_valid;
reg [7:0] dat;
reg dat_valid;
reg [7:0] i,j;
// state
parameter INIT_SCLR=1, INIT_SPIN=2,
STEP_READY=3,STEP_ONE=4,STEP_TWO=5,STEP_THREE=6,STEP_FOUR=7;
reg [2:0] state;
reg [2:0] next_state;
//////////////////////////
reg [7:0] address_a, address_b;
reg [7:0] data_a, data_b;
reg wren_a,wren_b;
wire [7:0] q_a, q_b;
sbox_ram bx (.address_a(address_a),.address_b(address_b),
.clock(clk),.ena(ena),.data_a(data_a),.data_b(data_b),
.wren_a(wren_a),.wren_b(wren_b),.q_a(q_a),.q_b(q_b)
);
//////////////////////////
reg inc_i, sclr_i;
always @(posedge clk or posedge rst) begin
if (rst) i <= 8'b0;
else begin
if (ena) i <= ~{8{sclr_i}} & (i+inc_i);
end
end
//////////////////////////
reg [7:0] add_j;
reg sclr_j;
always @(posedge clk or posedge rst) begin
if (rst) j <= 8'b0;
else begin
if (ena) j <= ~{8{sclr_j}} & (j+add_j);
end
end
//////////////////////////
reg key_load,key_shft;
reg [KEY_BYTES*8-1:0] key_reg;
always @(posedge clk or posedge rst) begin
if (rst)
key_reg <= 0;
else begin
if (ena) begin
if (key_load) key_reg <= key;
// rotate left one byte
else if (key_shft) key_reg <=
{key_reg[(KEY_BYTES-1)*8-1:0],key_reg[KEY_BYTES*8-1:(KEY_BYTES-1)*8]};
end
end
end
//////////////////////////
reg out_idx_load, out_idx_accum;
reg [7:0] out_idx;
always @(posedge clk or posedge rst) begin
if (rst)
out_idx <= 0;
else begin
if (ena) begin
if (out_idx_load) out_idx <= q_a;
else if (out_idx_accum) out_idx <= out_idx + q_b;
end
end
end
//////////////////////////
reg keying;
reg start_keying,done_keying;
always @(posedge clk or posedge rst) begin
if (rst) keying <= 1'b0;
else begin
if (ena) keying <= (keying & !done_keying) | start_keying;
end
end
//////////////////////////
reg first_load;
reg load_dout;
always @(posedge clk or posedge rst) begin
if (rst) begin
first_load <= 1'b0;
end
else begin
// after keying swallow the 1st output
// byte generated, it's an artifact.
if (ena) begin
if (keying) first_load <= 1'b1;
else if (load_dout) first_load <= 1'b0;
end
end
end
//////////////////////////
always @(posedge clk or posedge rst) begin
if (rst) begin
dat_valid <= 1'b0;
dat <= 0;
end
else begin
// manage the output byte and valid registers
if (ena) begin
if (load_dout && !first_load) begin
dat <= q_b;
dat_valid <= 1'b1;
end
else dat_valid <= 1'b0;
end
end
end
//////////////////////////
// state registers
always @(posedge clk or posedge rst) begin
if (rst) state <= INIT_SCLR;
else if (ena) state <= next_state;
end
// next state and output decisions
always @(*) begin
// control signal defaults
sclr_i = 0;
inc_i = 0;
sclr_j = 0;
add_j = 0;
out_idx_load = 0;
out_idx_accum = 0;
load_dout = 0;
start_keying = 0;
done_keying = 0;
key_load = 0;
key_shft = 0;
wren_a = 0;
wren_b = 0;
// these are really don't care when not specified.
address_a = 8'bx;
address_b = 8'bx;
data_a = 8'bx;
data_b = q_b;
// from any state offer sync reset to the init state
if (load_key) begin
$display ("Reinit requested");
next_state = INIT_SCLR;
end
// otherwise do the state machine...
else begin
case (state)
// The INIT states cover RAM init to 0..255
// the B port is idle. Could double up here.
INIT_SCLR : begin
next_state = INIT_SPIN;
start_keying = 1'b1;
sclr_i = 1'b1;
sclr_j = 1'b1;
end
INIT_SPIN : begin
// write 0..255 to memory 0..255
// on port A
if (i == 255) next_state = STEP_READY;
else next_state = INIT_SPIN;
wren_a = 1'b1;
address_a = i;
data_a = i;
inc_i = 1'b1;
end
// The STEP states cover keying and generation
STEP_READY : begin
$display ("Ready state. keying = %b",keying);
next_state = STEP_ONE;
key_load = keying;
sclr_j = 1'b1;
// i is going to be 0 on entry.
// during generation we want 1, not 0.
inc_i = !keying;
// ask for S[i] on A, correct it if it should be 1
address_a = i | !keying;
end
STEP_ONE : begin
// ask for S[i] on A
// ask for the output byte (s[S[i]+S[j]]) on B
next_state = STEP_TWO;
address_a = i;
address_b = out_idx;
add_j <= keying ? key_reg[KEY_BYTES*8-1:(KEY_BYTES-1)*8] : 0;
key_shft = keying;
end
STEP_TWO : begin
// S[i] ready on A
// ask for j + S[i] aka S[j] on B
next_state = STEP_THREE;
address_b = j + q_a;
add_j = q_a;
end
STEP_THREE : begin
// S[i] still ready on A
// output byte ready on B
// write S[i] to loc j on B
next_state = STEP_FOUR;
wren_a = 1'b1;
address_a = j;
data_a = q_a;
out_idx_load = 1'b1;
load_dout = !keying;
end
STEP_FOUR : begin
// S[j] ready on B
// write S[j] to loc i on B
wren_b = 1'b1;
data_b = q_b;
address_b = i;
if (keying && i == 255) begin
next_state = STEP_READY;
done_keying = 1'b1;
end
else next_state = STEP_ONE;
// ask for the next S[i] on A
address_a = i + 1;
inc_i = 1'b1;
out_idx_accum = 1'b1;
end
endcase
end
end
endmodule