VHDL语法简单总结

一个VHDL程序代码包含实体(entity结构体(architecture、配置(configuration)、程序包(package)、库(library)等。

一、数据类型

1.用户自定义数据类型

使用关键字TYPE,例如:

TYPE my_integer IS RANGE -32 TO 32;

–用户自定义的整数类型的子集

TYPE student_grade IS RANGE 0 TO 100;

–用户自定义的自然数类型的子集

TYPE state IS (idle, forward, backward, stop);

–枚举数据类型,常用于有限状态机的状态定义

一般来说,枚举类型的数据自动按顺序依次编码。

2.子类型

在原有已定义数据类型上加一些约束条件,可以定义该数据类型的子类型。VHDL不允许不同类型的数据直接进行操作运算,而某个数据类型的子类型则可以和原有类型数据直接进行操作运算。

子类型定义使用SUBTYPE关键字。

3.数组(ARRAY)

ARRAY是将相同数据类型的数据集合在一起形成的一种新的数据类型。

TYPE type_name IS ARRAY (specification) OF data_type;

–定义新的数组类型语法结构

SIGNAL signal_name: type_name [:= initial_value];

–使用新的数组类型对SIGNAL,CONSTANT, VARIABLE进行声明

例如:

TYPE delay_lines IS ARRAY (L-2 DOWNTO 0) OF SIGNED (W_IN-1 DOWNTO 0);

–滤波器输入延迟链类型定义

TYPE coeffs IS ARRAY (L-1 DOWNTO 0) OF SIGNED (W_COEF-1 DOWNTO 0);

–滤波器系数类型定义

SIGNAL delay_regs: delay_lines;– 信号延迟寄存器声明

CONSTANT coef: coeffs := (); –常量系数声明并赋初值

4.端口数组

在定义电路的输入/输出端口时,有时需把端口定义为矢量阵列,而在ENTITY中不允许使用TYPE进行类型定义,所以必须在包集(PACKAGE)中根据端口的具体信号特征建立用户自定义的数据类型,该数据类型可以供包括ENTITY在内的整个设计使用。

—————————————PACKAGE———————————-

library ieee;

use ieee.std_logic_1164.all;

——————————————

PACKAGE my_data_types IS

TYPE vector_array IS ARRAY (natural range <>) OF STD_LOGIC_VECTOR(7 DOWNTO 0); –声明8位的数组

END my_data_types;

———————————–Main Code—————————————

library ieee;

use ieee.std_logic_1164.all;

use work.my_data_types.all; –用户自定义包集

——————————————————————

ENTITY mux IS

PORT (inp: IN vector_array(0 to 3);

END mux;

——————————————————————————-

5.有符号数和无符号数

要使用SIGNED和UNSIGNED类型数据,必须在代码开始部分声明ieee库中的包集std_logic_arith。它们支持算术运算但不支持逻辑运算

library ieee;

use ieee.std_logic_1164.all;

use ieee.std_logic_arith.all;

……

SIGNAL a: IN SIGNED (7 DOWNTO 0);

SIGNAL b: IN SIGNED (7 DOWNTO 0);

SIGNAL x: IN SIGNED (7 DOWNTO 0);

……

v <= a + b;

w <= a AND b;–非法(不支持逻辑运算)

——————————————————————————-

STD_LOGIC_VECTOR类型的数据不能直接进行算术运算,只有声明了std_logic_signed和std_logic_unsigned两个包集后才可以像SIGNED和UNSIGNED类型的数据一样进行算术运算。

6.数据类型转换

在ieee库的std_logic_arith包集中提供了许多数据类型转换函数:

1. conv_integer(p): 将数据类型为INTEGER,UNSIGNED,SIGNED,STD_ULOGIC或STD_LOGIC的操作数p转换成INTEGER类型。不包含STD_LOGIC_VECTOR。

2. conv_unsigned(p,b):将数据类型为INTEGER,UNSIGNED,SIGNED或STD_ULOGIC的操作数p转换成位宽为b的UNSIGNED类型数据。

3. conv_signed(p,b):将数据类型为INTEGER, UNSIGNED, SIGNED或STD_ULOGIC的操作数p转换成位宽为b的SIGNED类型的数据。

4. conv_std_logic_vector(p, b):将数据类型为INTEGER, UNSIGNED, SIGNED或STD_LOGIC的操作数p转换成位宽为b的STD_LOGIC_VECTOR类型的数据。

二、运算操作符和属性

1.运算操作符

l赋值运算符

赋值运算符用来给信号、变量和常数赋值。

<=用于对SIGNAL类型赋值;

:=用于对VARIABLE,CONSTANT和GENERIC赋值,也可用于赋初始值;

=>用于对矢量中的某些位赋值,或对某些位之外的其他位赋值(常用OTHERS表示)。

例:

SIGNAL x: STD_LOGIC;

VARIABLE y: STD_LOGIC_VECTOR(3 DOWNTO 0);–最左边的位是MSB

SIGNAL w: STD_LOGIC_VECTOR(0 TO 7);–最右边的位是MSB

x <= ‘1’;

y := “0000”;

w <= “1000_0000”;– LSB位为1,其余位为0

w <= (0 => ‘1’, OTHERS => ‘0’);– LSB位是1, 其他位是0

l逻辑运算符

操作数必须是BIT, STD_LOGIC或STD_ULOGIC类型的数据或者是这些数据类型的扩展,即BIT_VECTOR, STD_LOGIC_VECTOR,STD_ULOGIC_VECTOR。

VHDL的逻辑运算符有以下几种:(优先级递减

ŸNOT —— 取反

ŸAND —— 与

ŸOR —— 或

ŸNAND —— 与非

ŸNOR —— 或非

ŸXOR —— 异或

l算术运算符

操作数可以是INTEGER, SIGNED, UNSIGNED, 如果声明了std_logic_signed或std_logic_unsigned,可对STD_LOGIC_VECTOR类型的数据进行加法或减法运算。

+ —— 加

-—— 减

* —— 乘

/ —— 除

** —— 指数运算

MOD —— 取模

REM —— 取余

ABS —— 取绝对值

加,减,乘是可以综合成逻辑电路的;除法运算只在除数为2的n次幂时才能综合,此时相当于对被除数右移n位;对于指数运算,只有当底数和指数都是静态数值(常量或GENERIC参数)时才是可综合的;对于MOD运算,结果的符号同第二个参数的符号相同,对于REM运算,结果的符号同第一个参数符号相同。

l关系运算符

=, /=, <, >, <=, >=

左右两边操作数的类型必须相同。

l移位操作符

<左操作数> <移位操作符> <右操作数>

其中左操作数必须是BIT_VECTOR类型的,右操作数必须是INTEGER类型的(可以为正数或负数)。

VHDL中移位操作符有以下几种:

usll逻辑左移– 数据左移,右端补0;

usrl逻辑右移– 数据右移,左端补0;

usla算术左移– 数据左移,同时复制最右端的位,填充在右端空出的位置;

usra算术右移– 数据右移,同时复制最左端的位,填充在左端空出的位置;

urol循环逻辑左移 — 数据左移,从左端移出的位填充到右端空出的位置上;

uror循环逻辑右移 – 数据右移,从右端移出的位填充到左端空出的位置上。

例:x <= “01001”,那么:

y <= x sll 2;–逻辑左移2位,y<=”00100”

y <= x sla 2;–算术左移2位,y<=”00111”

y <= x srl 3;–逻辑右移3位,y<=”00001”

y <= x sra 3;–算术右移3位,y<=”00001”

y <= x rol 2;–循环左移2位,y<=”00101”

y <= x srl -2;–相当于逻辑左移2

l并置运算符

用于位的拼接,操作数可以是支持逻辑运算的任何数据类型。有以下两种:

²&

²(, , , )

与Verilog中{}的功能一样。

2.属性(ATTRIBUTE)

l数值类属性

数值类属性用来得到数组、块或一般数据的相关信息,例如可用来获取数组的长度和数值范围等。

以下是VHDL中预定义的可综合的数值类属性:

d’LOW–返回数组索引的下限值

d’HIGH–返回数组索引的上限值

d’LEFT–返回数组索引的左边界值

d’RIGHT–返回数组索引的右边界值

d’LENGTH–返回矢量的长度值

d’RANGE–返回矢量的位宽范围

d’REVERSE_RANGE–按相反的次序返回矢量的位宽范围

例:定义信号 SIGNAL d: STD_LOGIC_VECTOR(7 DOWNTO 0);

则有:d’LOW = 0, d’HIGH = 7, d’LEFT = 7, d’RIGHT = 0, d’LENGTH = 8,d’RANGE = (7 DOWNTO 0), d’REVERSE_RANGE = (0 TO 7).

l信号类属性

对于信号s,有以下预定义的属性(可综合的):

s’EVENT若s的值发生变化,则返回布尔量TRUE,否则返回FALSE

s’STABLE若s保持稳定,则返回TRUE,否则返回FALSE

例:clk的上升沿判断

IF (clk’EVENT AND clk = ‘1’)

IF (NOT clk’STABLE AND clk = ‘1’)

WAIT UNTIL (clk’EVENT AND clk = ‘1’)

3.通用属性语句

GENERIC语句提供了一种指定常规参数的方法,所指定的参数是静态的,增加了代码的可重用性,类似于Verilog中的parameter与defparam。GENERIC语句必须在ENTITY中进行声明,由GENERIC语句指定的参数是全局的,不仅可在ENTITY内部使用,也可在后面的整个设计中使用。语法结构如下:

GENERIC (parameter_name: parameter_type := parameter_value);

用GENERIC语句指定多个参数:

GENERIC (n: INTEGER := 8; vector: BIT_VECTOR := “0000_1111”);

三、并发代码

VHDL中并发描述语句有WHEN和GENERATE。除此之外,仅包含AND, NOT, +, *和sll等逻辑、算术运算操作符的赋值语句也是并发执行的。在BLOCK中的代码也是并发执行的。

从本质上讲,VHDL代码是并行执行的。只有PROCESS, FUNCTION, PROCEDURE内部的代码才是顺序执行的。但是当它们作为一个整体时,与其他模块之间又是并行执行的。并发代码称为“数据流”代码

通常我们只能用并发描述语句来实现组合逻辑电路,为了实现时序逻辑电路,必须使用顺序描述语句。事实上,使用顺序描述语句可以同时实现组合逻辑电路和时序逻辑电路。

在并发代码中可以使用以下各项:

Ø运算操作符

ØWHEN语句(WHEN/ELSE或WITH/SELECT/WHEN)

ØGENERATE语句

ØBLOCK语句

使用运算操作符

运算类型

运算操作符

操作数类型

逻辑运算

NOT, AND, NAND,OR

NOR, XOR, XNORBIT, BIT_VECTOR, STD_LOGIC, STD_LOGIC_VECTOR

STD_ULOGIC, STD_ULOGIC_VECTOR

算术运算符

+, —, *, /, **

INTEGER, SIGNED, UNSIGNED

比较运算符

=, /=, <, >, <=, >=

任意数据类型

移位运算符

sll, srl, sla, sra, rol, ror

BIT_VECTOR

并置运算符

&,(, , ,)

STD_LOGIC, STD_LOGIC_VECTOR, STD_ULOGIC

STD_ULOGIC_VECTOR, SIGNED, UNSIGNED

WHEN语句

WHEN语句是一种基本的并发描述语句,有两种形式:WHEN/ELSE和WITH/SELECT/WHEN。

WHEN/ELSE语法结构:

assignment WHEN condition ELSE

assignment WHEN condition ELSE

…;

WITH/SELECT/WHEN语法结构

WITH identifier SELECT

assignment WHEN value,

assignemnt WHEN value,

…;

当使用WITH/SELECT/WHEN时,必须对所有可能出现的条件给予考虑,使用关键字OTHERS,如果在某些条件出现时不需要进行任何操作,那应该使用UNAFFECTED。

例:

————————————-with WHEN/ELSE——————————————-

Output <= “000” WHEN (inp = ‘0’ OR reset = ‘1’) ELSE

“001” WHEN ctl = ‘1’ ELSE

“010”;

———————————–with WITH/SELECT/WHEN——————————–

WITH control SELECT

Output <= “000” WHEN reset,

“111” WHEN set,

UNAFFECTED WHEN OTHERS;

对于WHEN语句,WHEN value的描述方式有以下几种:

WHEN value–针对单个值进行判断

WHEN value1 to value2–针对取值范围进行判断

WHEN value1 | value2 | …–针对多个值进行判断

GENERATE语句

GENERATE语句和顺序描述语句中的LOOP语句一样用于循环执行某项操作,通常与FOR一起使用。语法结构如下:

label: FOR identifier IN range GENERATE

(concurrent assignments)

END GENERATE

GENERATE语句还有另一种形式:IF/GENERATE,此处不允许使用ELSE。IF/GENERATE可以嵌套在FOR/GENERATE内部使用。反之亦然。

Label1: FOR identifier IN range GENERATE

……

Label2: IF condition GENERATE

(concurrent assignments)

END GENERATE;

……

END GENERATE;

例:

SIGNAL x: BIT_VECTOR(7 DOWNTO 0);

SIGNAL y: BIT_VECTOR(15 DOWNTO 0);

SIGNAL z: BIT_VECTOR(7 DOWNTO 0);

……

G1: FOR i IN x’RANGE GENERATE

z(i) <= x(i) AND y(i+8);

END GENERATE;

GENERATE中循环操作的上界和下界必须是静态的,在使用过程中还要注意多值驱动问题

例:

OK: FOR i IN 0 TO 7 GENERATE

Output(i) <= ‘1’ WHEN (a(i) AND b(i)) = ‘1’ ELSE ‘0’;

END GENERATE;

—————————————————————————

NotOK: FOR i IN 0 TO 7 GENERATE

accum <= “1111_1111”WHEN(a(i) AND b(i)) = ‘1’ ELSE “0000_0000”;

END GENERATE;

—————————————————————-

NotOK: FOR i IN 0 TO 7 GENERATE

Accum <= accum + 1 WHEN x(i) = ‘1’;

END GENERATE;

—————————————————————-

块语句(BLOCK)

VHDL中有两种BLOCK:simple BLOCK和guarded BLOCK。

nSimple BLOCK

Simple BLOCK仅仅是对原有代码进行区域分割,增强整个代码的可读性和可维护性。语法结构如下:

labelBLOCK

[declarative part]

BEGIN

(concurrent statement)

END BLOCK label;

—————————————————————————————————-

ARCHITETURE example…

BEGIN

block1: BLOCK

BEGIN

END BLOCK block1;

block2: BLOCK

BEGIN

END BLOCK block2;

END example;

—————————————————————————————–

例:

b1: BLOCK

SIGNAL a: STD_LOGIC;

BEGIN

a <= input_sig WHEN ena = ‘1’ ELSE ‘z’;

END BLOCK b1;

———————————————————————————————————————-

无论是simple BLOCK还是guarded BLOCK,其内部都可以嵌套其他的BLOCK语句,相应的语法结构如下:

label1: BLOCK

[顶层BLOCK声明部分]

BEGIN

[顶层BLOCK并发描述部分]

label2: BLOCK

[嵌套BLOCK声明部分]

BEGIN

[嵌套BLOCK并发描述部分]

END BLOCK label2;

[顶层BLOCK其他并发描述语句]

END BLOCK label1

———————————————————————————————————

nGuarded BLOCK

多了一个卫式表达式,只有当卫式表达式为真时才能执行。语法结构如下:

Label: BLOCK(卫式表达式)

[声明部分]

BEGIN

(卫式语句和其他并发描述语句)

END BLOCK label;

四、顺序代码

在PROCESS, FUNCTION, PROCEDURE内部的代码都是顺序执行的,这样的语句包括IFWAITCASELOOP。变量只能在顺序代码中使用,相对于信号而言,变量是局部的,所以它的值不能传递到PROCESS,FUNCTION和PROCEDURE的外部。

1.进程(PROCESS)

进程内部经常使用IF,WAIT,CASE或LOOP语句。PROCESS具有敏感信号列表(sensitivity list),或者使用WAIT语句进行执行条件的判断。PROCESS必须包含在主代码段中,当敏感信号列表中的某个信号发生变化时(或者当WAIT语句的条件得到满足时),PROCESS内部的代码就顺序执行一次。语法结构如下:

[label: ] PROCESS (sensitivity list)

[VARIABLE name type [range] [ := initial_value; ]]

BEGIN

(顺序执行的代码)

END PROCESS [label];

如果要在PROCESS内部使用变量,则必须在关键字BEGIN之前的变量声明部分对其进行定义。变量的初始值是不可综合的,只用于仿真。在设计同步电路时,要对某些信号边沿的跳变进行监视(时钟的上升沿或下降沿)。通常使用EVENT属性来监视一个信号是否发生了变化。

2.信号和变量

信号可在PACKAGEENTITYARCHITECTURE中声明,而变量只能在一段顺序描述代码的内部声明。因此,信号通常是全局的,变量通常是局部的。赋予变量的值是立刻生效的,在后续的代码中,此变量将使用新的变量值,而信号的值通常只有在整个PROCESS执行完毕后才开始生效

3.IF语句

IF/ELSE语句在综合时可能会产生不必要的优先级解码电路。IF语句语法结构如下:

IF conditions THEN assignments;

ELSIF conditions THEN assignments;

ELSE assignments;

END IF;

————————————————————————————————

例:

IF (x < y) temp := “1111_1111”;

ELSIF (x = y AND w = ‘0’) THEN temp := “1111_0000”;

ELSE temp := (OTHERS => ‘0’);

4.WAIT语句

如果在process中使用了WAIT语句,就不能使用敏感信号列表了。WAIT语句使用以下3种形式的语法结构:

WAIT UNTIL signal_condition

WAIT ON signal1 [, signal2, ...];

WAIT FOR time;

WAIT UNTIL后面只有一个信号条件表达式,更适合于实现同步电路(将时钟的上升沿或下降沿作为条件),由于没有敏感信号列表,所以它必须是process的第一条语句。当WAIT UNTIL语句的条件满足是,process内部的代码就执行一遍。

–带有同步复位的8bit寄存器

process–没有敏感信号列表

begin

wait until (clk’event and clk = ‘1′);

if (rst = ‘1′) then

output <= (others => ‘0′);

elsif (clk’event and clk = ‘1′) then

output <= input;

end if;

end process;

WAIT ON 语句中可以出现多个信号,只要信号列表中的任何一个发生变化,process内的代码就开始执行。

–带异步复位的8bit寄存器

process

begin

wait on clk, rst;

if (rst = ‘1′) then

output <= (others => ‘0′);

elsif (clk’event and clk = ‘1′) then

output <= input;

end if;

end process;

WAIT FOR 语句只能用于仿真。

5.CASE 语句

CASE语句的语法结构如下:

CASE表达式IS

WHEN条件表达式=>顺序执行语句;

WHEN条件表达式=>顺序执行语句;

……

END CASE

例:

case control is

when “00″=>x <= a; y <= b;

when “01″=>x <= b; y <= c;

when others =>x <= “0000″; y <= “zzzz”;

end case;

关键词OTHERS代表了所有未列出的可能情况,与Verilog中default相当。关键词NULL表示没有操作发生,如WHEN OTHERS => NULL.

CASE语句允许在每个测试条件下执行多个赋值操作,WHEN语句只允许执行一个赋值操作

6.LOOP语句

LOOP语句用在需要多次重复执行时。语法结构有以下几种:

FOR/LOOP: 循环固定次数

[label: ] FOR循环变量IN范围LOOP

(顺序描述语句)

END LOOP [label];

WHILE/LOOP: 循环执行直到某个条件不再满足

[label: ] WHILE condition LOOP

(顺序描述语句)

END LOOP [label];

EXIT: 结束整个循环操作

[label: ] EXIT[label] [WHEN condition];

NEXT: 跳出本次循环

[label: ] NEXT [loop_label] [WHEN condition];

Example: FOR/LOOP

for i in 0 to 5 loop

x(i) <= enable and w(i+2);

y(0, i) <= w(i);

end loop

Example: WHILE/LOOP

while (i < 10) loop — 0~9

wait until clk’event and clk = ‘1′;

(其他语句)

end loop;

for i in 0 to data’range loop

case data(i) is

when ‘0′ =>count := count + 1;

when others => null;

end case;

end loop;

7.CASE语句和IF语句的比较

IF语句和CASE语句编写的代码在综合、优化后最终生成的电路结构是一样的

例:下面两段代码综合后可以得到结构相同的多路复用器

————with IF————–

if(sel = “00″)then x <= a;

elsif (sel = “01″)then x <= b;

elsif (sel = “10″)then x <= c;

else x <= d;

end if;

————-with case———–

case sel is

when “00″ =>x <= a;

when “01″ =>x <= b;

when “10″ =>x <= c;

when others =>x <= d;

end case;

8.CASE语句和WHEN语句的比较

case语句和when语句的不同之处在于,when语句是并发执行的,case语句是顺序实行的

下面两段代码的功能等效

——-with when——————

with sel select

x <= a when “000″,

b when “001″,

c when “101″,

unaffected when others;

——-with case——————

case sel is

when “000″ => x <= a;

when “001″ => x <= b;

when “101″ => x <= c;

when others => null;

end case;

9.使用顺序代码设计组合逻辑电路

原则1:确保在process中用到的所有输入信号都出现在敏感信号列表中;

原则2:电路的真值表必须在代码中完整的反映出来。(否则会生成锁存器)

五、信号和变量

常量和信号是全局的,既可以用在顺序执行的代码中,也可用在并发执行的代码中。变量是局部的,只能用在顺序代码中,并且它们的值是不能直接向外传递的。

1.常量

CONSTANT name: type := value;

2.信号-signal

VHDL中的signal代表的是逻辑电路中的“硬”连线,既可用于电路的输入/输出端口,也可用于电路内部各单元之间的连接。Entity的所有端口默认为signal。格式如下:

SIGNAL name: type [range] [:= initial value];

当信号用在顺序描述语句中时,其值不是立刻更新的,信号值是在相应的进程、函数或过程完成之后才进行更新的。对信号赋初值的操作时不可综合的。

3.变量

变量仅用于局部电路的描述,只能在顺序执行的代码中使用,而且对它的赋值是立即生效的,所以新的值可在下一行代码中立即使用。格式:

VARIABLE name: type [range] [:= initial value];

对变量的赋初值操作也是不可综合的。

4.寄存器的数量

当一个信号的赋值是以另一个信号的跳变为条件时,或者说当发生同步赋值时,该信号经过编译后就会生成寄存器。如果一个变量是在一个信号跳变时被赋值的,并且该值最终又被赋给了另外的信号,则综合后就会生成寄存器。如果一个信号在还没有进行赋值操作时已被使用,那么也会在综合时生成寄存器。

process (clk)

begin

if (clk’event and clk = ‘1′) then

output1 <= temp;– output1被寄存

output2 <= a;– output2被寄存

end if;

end process;

process (clk)

begin

if (clk’event and clk = ‘1′) then

output1 <= temp;– output1被寄存

end if;

output2 <= a;– output2未被寄存

end process;

process (clk)

variable temp:bit;

begin

if (clk’event and clk = ‘1′) then

temp <= a;

end if;

x <= temp;– temp促使x被寄存

end process;

六、包集元件

1.包集

经常使用的代码通常以component,function或procedure的形式编写。这些代码被添加到package中,并在最后编译到目标library中。Package中还可以包含TYPE和CONSTANT的定义。语法格式如下:

package package_name is

(declaration)

end package_name;

package body package_name is

(function and procedure description)

end package_name;]

Example6.1 简单的程序包

library ieee;

use ieee.std_logic_1164.all;

———————————————————————-

package my_package is

type state is (st1, st2, st3, st4);

type color is (red, green, blue);

constant vec:std_logic_vector(7 downto0) := “1111_1111″;

end my_package;

Example6.2 内部包含函数的package

library ieee;

use ieee.std_logic_1164.all;

———————————————————————-

package my_package is

type state is (st1, st2, st3, st4);

type color is (red, green, blue);

contant vec: std_logic_vector(7 downto 0) := “1111_1111″;

function positive_edge(signal s: std_logic) return boolean;

end my_package;

———————————————————————-

package body my_package is

function positive_edge(signal s: std_logic) return booleanis

begin

return(s’event and s = ‘1′);

end positive_edge;

end my_package;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容